/[rdesktop]/jpeg/rdesktop/trunk/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 39 by matthewc, Fri Apr 5 07:57:43 2002 UTC revision 968 by astrand, Thu Aug 4 11:19:06 2005 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-2001     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25  #include <limits.h>             /* PATH_MAX */  #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
29    #include <ctype.h>              /* toupper */
30    #include <limits.h>             /* PATH_MAX */
31    #include <errno.h>
32  #include "rdesktop.h"  #include "rdesktop.h"
33    
34  char username[16];  #ifdef HAVE_LOCALE_H
35  char hostname[16];  #include <locale.h>
36  char keymapname[16];  #endif
37  int keylayout;  #ifdef HAVE_ICONV
38  int width;  #ifdef HAVE_LANGINFO_H
39  int height;  #include <langinfo.h>
40  BOOL bitmap_compression = True;  #endif
41  BOOL sendmotion = True;  #endif
42  BOOL orders = True;  
43  BOOL licence = True;  #ifdef EGD_SOCKET
44  BOOL encryption = True;  #include <sys/types.h>
45  BOOL desktop_save = True;  #include <sys/socket.h>         /* socket connect */
46  BOOL fullscreen = False;  #include <sys/un.h>             /* sockaddr_un */
47    #endif
48    
49    #include <openssl/md5.h>
50    
51    char g_title[64] = "";
52    char g_username[64];
53    char g_hostname[16];
54    char keymapname[PATH_MAX] = "en-us";
55    int g_keylayout = 0x409;        /* Defaults to US keyboard layout */
56    int g_keyboard_type = 0x4;      /* Defaults to US keyboard layout */
57    int g_keyboard_subtype = 0x0;   /* Defaults to US keyboard layout */
58    int g_keyboard_functionkeys = 0xc;      /* Defaults to US keyboard layout */
59    
60    int g_width = 800;              /* width is special: If 0, the
61                                       geometry will be fetched from
62                                       _NET_WORKAREA. If negative,
63                                       absolute value specifies the
64                                       percent of the whole screen. */
65    int g_height = 600;
66    int g_xpos = 0;
67    int g_ypos = 0;
68    int g_pos = 0;                  /* 0 position unspecified,
69                                       1 specified,
70                                       2 xpos neg,
71                                       4 ypos neg  */
72    extern int g_tcp_port_rdp;
73    int g_server_bpp = 8;
74    int g_win_button_size = 0;      /* If zero, disable single app mode */
75    BOOL g_bitmap_compression = True;
76    BOOL g_sendmotion = True;
77    BOOL g_bitmap_cache = True;
78    BOOL g_bitmap_cache_persist_enable = False;
79    BOOL g_bitmap_cache_precache = True;
80    BOOL g_encryption = True;
81    BOOL packet_encryption = True;
82    BOOL g_desktop_save = True;     /* desktop save order */
83    BOOL g_polygon_ellipse_orders = True;   /* polygon / ellipse orders */
84    BOOL g_fullscreen = False;
85    BOOL g_grab_keyboard = True;
86    BOOL g_hide_decorations = False;
87    BOOL g_use_rdp5 = True;
88    BOOL g_console_session = False;
89    BOOL g_numlock_sync = False;
90    BOOL g_owncolmap = False;
91    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
92    uint32 g_embed_wnd;
93    uint32 g_rdp5_performanceflags =
94            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
95    
96    #ifdef WITH_RDPSND
97    BOOL g_rdpsnd = False;
98    #endif
99    
100    #ifdef HAVE_ICONV
101    char g_codepage[16] = "";
102    #endif
103    
104    extern RDPDR_DEVICE g_rdpdr_device[];
105    extern uint32 g_num_devices;
106    extern char *g_rdpdr_clientname;
107    
108    #ifdef RDP2VNC
109    extern int rfb_port;
110    extern int defer_time;
111    void
112    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
113                    char *shell, char *directory);
114    #endif
115  /* Display usage information */  /* Display usage information */
116  static void  static void
117  usage(char *program)  usage(char *program)
118  {  {
119          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
120          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
121          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
122          printf("   -s: shell\n");  
123          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
124          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
125          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
126          printf("   -k: keyboard layout\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
127          printf("   -g: desktop geometry (WxH)\n");  #endif
128          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
129          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
130          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
131          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
132          printf("   -l: do not request licence\n\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
133            fprintf(stderr, "   -n: client hostname\n");
134            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
135            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
136            fprintf(stderr, "   -f: full-screen mode\n");
137            fprintf(stderr, "   -b: force bitmap updates\n");
138    #ifdef HAVE_ICONV
139            fprintf(stderr, "   -L: local codepage\n");
140    #endif
141            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
142            fprintf(stderr, "   -e: disable encryption (French TS)\n");
143            fprintf(stderr, "   -E: disable encryption from client to server\n");
144            fprintf(stderr, "   -m: do not send motion events\n");
145            fprintf(stderr, "   -C: use private colour map\n");
146            fprintf(stderr, "   -D: hide window manager decorations\n");
147            fprintf(stderr, "   -K: keep window manager key bindings\n");
148            fprintf(stderr, "   -S: caption button size (single application mode)\n");
149            fprintf(stderr, "   -T: window title\n");
150            fprintf(stderr, "   -N: enable numlock syncronization\n");
151            fprintf(stderr, "   -X: embed into another window with a given id.\n");
152            fprintf(stderr, "   -a: connection colour depth\n");
153            fprintf(stderr, "   -z: enable rdp compression\n");
154            fprintf(stderr, "   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
155            fprintf(stderr, "   -P: use persistent bitmap caching\n");
156            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
157            fprintf(stderr,
158                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
159            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
160            fprintf(stderr,
161                    "         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
162            fprintf(stderr, "             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
163            fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
164            fprintf(stderr, "             for redirected disks\n");
165            fprintf(stderr,
166                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
167            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
168            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
169            fprintf(stderr,
170                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
171            fprintf(stderr, "         '-r sound:[local|off|remote]': enable sound redirection\n");
172            fprintf(stderr, "                     remote would leave sound on server\n");
173            fprintf(stderr, "   -0: attach to console\n");
174            fprintf(stderr, "   -4: use RDP version 4\n");
175            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
176    }
177    
178    static void
179    print_disconnect_reason(uint16 reason)
180    {
181            char *text;
182    
183            switch (reason)
184            {
185                    case exDiscReasonNoInfo:
186                            text = "No information available";
187                            break;
188    
189                    case exDiscReasonAPIInitiatedDisconnect:
190                            text = "Server initiated disconnect";
191                            break;
192    
193                    case exDiscReasonAPIInitiatedLogoff:
194                            text = "Server initiated logoff";
195                            break;
196    
197                    case exDiscReasonServerIdleTimeout:
198                            text = "Server idle timeout reached";
199                            break;
200    
201                    case exDiscReasonServerLogonTimeout:
202                            text = "Server logon timeout reached";
203                            break;
204    
205                    case exDiscReasonReplacedByOtherConnection:
206                            text = "The session was replaced";
207                            break;
208    
209                    case exDiscReasonOutOfMemory:
210                            text = "The server is out of memory";
211                            break;
212    
213                    case exDiscReasonServerDeniedConnection:
214                            text = "The server denied the connection";
215                            break;
216    
217                    case exDiscReasonServerDeniedConnectionFips:
218                            text = "The server denied the connection for security reason";
219                            break;
220    
221                    case exDiscReasonLicenseInternal:
222                            text = "Internal licensing error";
223                            break;
224    
225                    case exDiscReasonLicenseNoLicenseServer:
226                            text = "No license server available";
227                            break;
228    
229                    case exDiscReasonLicenseNoLicense:
230                            text = "No valid license available";
231                            break;
232    
233                    case exDiscReasonLicenseErrClientMsg:
234                            text = "Invalid licensing message";
235                            break;
236    
237                    case exDiscReasonLicenseHwidDoesntMatchLicense:
238                            text = "Hardware id doesn't match software license";
239                            break;
240    
241                    case exDiscReasonLicenseErrClientLicense:
242                            text = "Client license error";
243                            break;
244    
245                    case exDiscReasonLicenseCantFinishProtocol:
246                            text = "Network error during licensing protocol";
247                            break;
248    
249                    case exDiscReasonLicenseClientEndedProtocol:
250                            text = "Licensing protocol was not completed";
251                            break;
252    
253                    case exDiscReasonLicenseErrClientEncryption:
254                            text = "Incorrect client license enryption";
255                            break;
256    
257                    case exDiscReasonLicenseCantUpgradeLicense:
258                            text = "Can't upgrade license";
259                            break;
260    
261                    case exDiscReasonLicenseNoRemoteConnections:
262                            text = "The server is not licensed to accept remote connections";
263                            break;
264    
265                    default:
266                            if (reason > 0x1000 && reason < 0x7fff)
267                            {
268                                    text = "Internal protocol error";
269                            }
270                            else
271                            {
272                                    text = "Unknown reason";
273                            }
274            }
275            fprintf(stderr, "disconnect: %s.\n", text);
276    }
277    
278    static BOOL
279    read_password(char *password, int size)
280    {
281            struct termios tios;
282            BOOL ret = False;
283            int istty = 0;
284            char *p;
285    
286            if (tcgetattr(STDIN_FILENO, &tios) == 0)
287            {
288                    fprintf(stderr, "Password: ");
289                    tios.c_lflag &= ~ECHO;
290                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
291                    istty = 1;
292            }
293    
294            if (fgets(password, size, stdin) != NULL)
295            {
296                    ret = True;
297    
298                    /* strip final newline */
299                    p = strchr(password, '\n');
300                    if (p != NULL)
301                            *p = 0;
302            }
303    
304            if (istty)
305            {
306                    tios.c_lflag |= ECHO;
307                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
308                    fprintf(stderr, "\n");
309            }
310    
311            return ret;
312    }
313    
314    static void
315    parse_server_and_port(char *server)
316    {
317            char *p;
318    #ifdef IPv6
319            int addr_colons;
320    #endif
321    
322    #ifdef IPv6
323            p = server;
324            addr_colons = 0;
325            while (*p)
326                    if (*p++ == ':')
327                            addr_colons++;
328            if (addr_colons >= 2)
329            {
330                    /* numeric IPv6 style address format - [1:2:3::4]:port */
331                    p = strchr(server, ']');
332                    if (*server == '[' && p != NULL)
333                    {
334                            if (*(p + 1) == ':' && *(p + 2) != '\0')
335                                    g_tcp_port_rdp = strtol(p + 2, NULL, 10);
336                            /* remove the port number and brackets from the address */
337                            *p = '\0';
338                            strncpy(server, server + 1, strlen(server));
339                    }
340            }
341            else
342            {
343                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
344                    p = strchr(server, ':');
345                    if (p != NULL)
346                    {
347                            g_tcp_port_rdp = strtol(p + 1, NULL, 10);
348                            *p = 0;
349                    }
350            }
351    #else /* no IPv6 support */
352            p = strchr(server, ':');
353            if (p != NULL)
354            {
355                    g_tcp_port_rdp = strtol(p + 1, NULL, 10);
356                    *p = 0;
357            }
358    #endif /* IPv6 */
359    
360  }  }
361    
362  /* Client program */  /* Client program */
363  int  int
364  main(int argc, char *argv[])  main(int argc, char *argv[])
365  {  {
366            char server[64];
367          char fullhostname[64];          char fullhostname[64];
368          char domain[16];          char domain[16];
369          char password[16];          char password[64];
370          char shell[32];          char shell[128];
371          char directory[32];          char directory[32];
372          char title[32];          BOOL prompt_password, deactivated;
373          struct passwd *pw;          struct passwd *pw;
374          char *server, *p;          uint32 flags, ext_disc_reason = 0;
375          uint32 flags;          char *p;
376          int c;          int c;
377            char *locale;
378            int username_option = 0;
379    
380          printf("rdesktop: A Remote Desktop Protocol client.\n");          /* Set locale according to environment */
381          printf("Version " VERSION ". Copyright (C) 1999-2001 Matt Chapman.\n");          locale = setlocale(LC_ALL, "");
382          printf("See http://www.rdesktop.org/ for more information.\n\n");          if (locale)
383            {
384                    xkeymap_from_locale(locale);
385            }
386    
387          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
388            prompt_password = False;
389          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
390          strcpy(keymapname, "us");          g_embed_wnd = 0;
391    
392            g_num_devices = 0;
393    
394    #ifdef RDP2VNC
395    #define VNCOPT "V:Q:"
396    #else
397    #define VNCOPT
398    #endif
399    
400          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemlh?")) != -1)          while ((c = getopt(argc, argv,
401                               VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
402          {          {
403                  switch (c)                  switch (c)
404                  {                  {
405    #ifdef RDP2VNC
406                            case 'V':
407                                    rfb_port = strtol(optarg, NULL, 10);
408                                    if (rfb_port < 100)
409                                            rfb_port += 5900;
410                                    break;
411    
412                            case 'Q':
413                                    defer_time = strtol(optarg, NULL, 10);
414                                    if (defer_time < 0)
415                                            defer_time = 0;
416                                    break;
417    #endif
418    
419                          case 'u':                          case 'u':
420                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
421                                    username_option = 1;
422                                    break;
423    
424                            case 'L':
425    #ifdef HAVE_ICONV
426                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
427    #else
428                                    error("iconv support not available\n");
429    #endif
430                                  break;                                  break;
431    
432                          case 'd':                          case 'd':
# Line 107  main(int argc, char *argv[]) Line 442  main(int argc, char *argv[])
442                                  break;                                  break;
443    
444                          case 'p':                          case 'p':
445                                    if ((optarg[0] == '-') && (optarg[1] == 0))
446                                    {
447                                            prompt_password = True;
448                                            break;
449                                    }
450    
451                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
452                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
453    
454                                    /* try to overwrite argument so it won't appear in ps */
455                                    p = optarg;
456                                    while (*p)
457                                            *(p++) = 'X';
458                                  break;                                  break;
459    
460                          case 'n':                          case 'n':
461                                  STRNCPY(hostname, optarg, sizeof(hostname));                                  STRNCPY(g_hostname, optarg, sizeof(g_hostname));
462                                  break;                                  break;
463    
464                          case 'k':                          case 'k':
# Line 120  main(int argc, char *argv[]) Line 466  main(int argc, char *argv[])
466                                  break;                                  break;
467    
468                          case 'g':                          case 'g':
469                                  width = strtol(optarg, &p, 10);                                  g_fullscreen = False;
470                                    if (!strcmp(optarg, "workarea"))
471                                    {
472                                            g_width = g_height = 0;
473                                            break;
474                                    }
475    
476                                    g_width = strtol(optarg, &p, 10);
477                                    if (g_width <= 0)
478                                    {
479                                            error("invalid geometry\n");
480                                            return 1;
481                                    }
482    
483                                  if (*p == 'x')                                  if (*p == 'x')
484                                          height = strtol(p+1, NULL, 10);                                          g_height = strtol(p + 1, &p, 10);
485    
486                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
487                                  {                                  {
488                                          error("invalid geometry\n");                                          error("invalid geometry\n");
489                                          return 1;                                          return 1;
490                                  }                                  }
491    
492                                    if (*p == '%')
493                                    {
494                                            g_width = -g_width;
495                                            p++;
496                                    }
497    
498                                    if (*p == '+' || *p == '-')
499                                    {
500                                            g_pos |= (*p == '-') ? 2 : 1;
501                                            g_xpos = strtol(p, &p, 10);
502    
503                                    }
504                                    if (*p == '+' || *p == '-')
505                                    {
506                                            g_pos |= (*p == '-') ? 4 : 1;
507                                            g_ypos = strtol(p, NULL, 10);
508                                    }
509    
510                                  break;                                  break;
511    
512                          case 'f':                          case 'f':
513                                  fullscreen = True;                                  g_fullscreen = True;
514                                  break;                                  break;
515    
516                          case 'b':                          case 'b':
517                                  orders = False;                                  g_bitmap_cache = False;
518                                  break;                                  break;
519    
520                          case 'e':                          case 'B':
521                                  encryption = False;                                  g_ownbackstore = False;
522                                  break;                                  break;
523    
524                            case 'e':
525                                    g_encryption = False;
526                                    break;
527                            case 'E':
528                                    packet_encryption = False;
529                                    break;
530                          case 'm':                          case 'm':
531                                  sendmotion = False;                                  g_sendmotion = False;
532                                    break;
533    
534                            case 'C':
535                                    g_owncolmap = True;
536                                    break;
537    
538                            case 'D':
539                                    g_hide_decorations = True;
540                                    break;
541    
542                            case 'K':
543                                    g_grab_keyboard = False;
544                                    break;
545    
546                            case 'S':
547                                    if (!strcmp(optarg, "standard"))
548                                    {
549                                            g_win_button_size = 18;
550                                            break;
551                                    }
552    
553                                    g_win_button_size = strtol(optarg, &p, 10);
554    
555                                    if (*p)
556                                    {
557                                            error("invalid button size\n");
558                                            return 1;
559                                    }
560    
561                                    break;
562    
563                            case 'T':
564                                    STRNCPY(g_title, optarg, sizeof(g_title));
565                                    break;
566    
567                            case 'N':
568                                    g_numlock_sync = True;
569                                    break;
570    
571                            case 'X':
572                                    g_embed_wnd = strtol(optarg, NULL, 0);
573                                    break;
574    
575                            case 'a':
576                                    g_server_bpp = strtol(optarg, NULL, 10);
577                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
578                                        && g_server_bpp != 24)
579                                    {
580                                            error("invalid server bpp\n");
581                                            return 1;
582                                    }
583                                    break;
584    
585                            case 'z':
586                                    DEBUG(("rdp compression enabled\n"));
587                                    flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
588                                    break;
589    
590                            case 'x':
591                                    if (strncmp("modem", optarg, 1) == 0)
592                                    {
593                                            g_rdp5_performanceflags =
594                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
595                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
596                                    }
597                                    else if (strncmp("broadband", optarg, 1) == 0)
598                                    {
599                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
600                                    }
601                                    else if (strncmp("lan", optarg, 1) == 0)
602                                    {
603                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
604                                    }
605                                    else
606                                    {
607                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
608                                    }
609                                  break;                                  break;
610    
611                          case 'l':                          case 'P':
612                                  licence = False;                                  g_bitmap_cache_persist_enable = True;
613                                    break;
614    
615                            case 'r':
616    
617                                    if (strncmp("sound", optarg, 5) == 0)
618                                    {
619                                            optarg += 5;
620    
621                                            if (*optarg == ':')
622                                            {
623                                                    *optarg++;
624                                                    while ((p = next_arg(optarg, ',')))
625                                                    {
626                                                            if (strncmp("remote", optarg, 6) == 0)
627                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
628    
629                                                            if (strncmp("local", optarg, 5) == 0)
630    #ifdef WITH_RDPSND
631                                                                    g_rdpsnd = True;
632    #else
633                                                                    warning("Not compiled with sound support\n");
634    #endif
635    
636                                                            if (strncmp("off", optarg, 3) == 0)
637    #ifdef WITH_RDPSND
638                                                                    g_rdpsnd = False;
639    #else
640                                                                    warning("Not compiled with sound support\n");
641    #endif
642    
643                                                            optarg = p;
644                                                    }
645                                            }
646                                            else
647                                            {
648    #ifdef WITH_RDPSND
649                                                    g_rdpsnd = True;
650    #else
651                                                    warning("Not compiled with sound support\n");
652    #endif
653                                            }
654                                    }
655                                    else if (strncmp("disk", optarg, 4) == 0)
656                                    {
657                                            /* -r disk:h:=/mnt/floppy */
658                                            disk_enum_devices(&g_num_devices, optarg + 4);
659                                    }
660                                    else if (strncmp("comport", optarg, 7) == 0)
661                                    {
662                                            serial_enum_devices(&g_num_devices, optarg + 7);
663                                    }
664                                    else if (strncmp("lptport", optarg, 7) == 0)
665                                    {
666                                            parallel_enum_devices(&g_num_devices, optarg + 7);
667                                    }
668                                    else if (strncmp("printer", optarg, 7) == 0)
669                                    {
670                                            printer_enum_devices(&g_num_devices, optarg + 7);
671                                    }
672                                    else if (strncmp("clientname", optarg, 7) == 0)
673                                    {
674                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
675                                            strcpy(g_rdpdr_clientname, optarg + 11);
676                                    }
677                                    else
678                                    {
679                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
680                                    }
681                                    break;
682    
683                            case '0':
684                                    g_console_session = True;
685                                    break;
686    
687                            case '4':
688                                    g_use_rdp5 = False;
689                                    break;
690    
691                            case '5':
692                                    g_use_rdp5 = True;
693                                  break;                                  break;
694    
695                          case 'h':                          case 'h':
# Line 159  main(int argc, char *argv[]) Line 700  main(int argc, char *argv[])
700                  }                  }
701          }          }
702    
703          if (argc - optind < 1)          if (argc - optind != 1)
704          {          {
705                  usage(argv[0]);                  usage(argv[0]);
706                  return 1;                  return 1;
707          }          }
708    
709          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
710            parse_server_and_port(server);
711    
712          if (username[0] == 0)          if (!username_option)
713          {          {
714                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
715                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 176  main(int argc, char *argv[]) Line 718  main(int argc, char *argv[])
718                          return 1;                          return 1;
719                  }                  }
720    
721                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
722          }          }
723    
724          if (hostname[0] == 0)  #ifdef HAVE_ICONV
725            if (g_codepage[0] == 0)
726            {
727                    if (setlocale(LC_CTYPE, ""))
728                    {
729                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
730                    }
731                    else
732                    {
733                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
734                    }
735            }
736    #endif
737    
738            if (g_hostname[0] == 0)
739          {          {
740                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
741                  {                  {
# Line 191  main(int argc, char *argv[]) Line 747  main(int argc, char *argv[])
747                  if (p != NULL)                  if (p != NULL)
748                          *p = 0;                          *p = 0;
749    
750                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
751          }          }
752    
753          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
754                    flags |= RDP_LOGON_AUTO;
755    
756            if (g_title[0] == 0)
757          {          {
758                  p = getpass("Password: ");                  strcpy(g_title, "rdesktop - ");
759                  if (p == NULL)                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
760          }          }
761    
762          if ((width == 0) || (height == 0))  #ifdef RDP2VNC
763            rdp2vnc_connect(server, flags, domain, password, shell, directory);
764            return 0;
765    #else
766    
767            if (!ui_init())
768                    return 1;
769    
770    #ifdef WITH_RDPSND
771            if (g_rdpsnd)
772                    rdpsnd_init();
773    #endif
774            rdpdr_init();
775    
776            if (!rdp_connect(server, flags, domain, password, shell, directory))
777                    return 1;
778    
779            /* By setting encryption to False here, we have an encrypted login
780               packet but unencrypted transfer of other packets */
781            if (!packet_encryption)
782                    g_encryption = False;
783    
784    
785            DEBUG(("Connection successful.\n"));
786            memset(password, 0, sizeof(password));
787    
788            if (ui_create_window())
789          {          {
790                  width = 800;                  rdp_main_loop(&deactivated, &ext_disc_reason);
791                  height = 600;                  ui_destroy_window();
792          }          }
793    
794          strcpy(title, "rdesktop - ");          DEBUG(("Disconnecting...\n"));
795          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp_disconnect();
796            cache_save_state();
797            ui_deinit();
798    
799          if (ui_create_window(title))          if (ext_disc_reason >= 2)
800          {                  print_disconnect_reason(ext_disc_reason);
                 if (!rdp_connect(server, flags, domain, password, shell,  
                                  directory))  
                         return 1;  
801    
802                  printf("Connection successful.\n");          if (deactivated)
803                  rdp_main_loop();          {
804                  printf("Disconnecting...\n");                  /* clean disconnect */
805                  ui_destroy_window();                  return 0;
806                  rdp_disconnect();          }
807            else
808            {
809                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
810                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
811                    {
812                            /* not so clean disconnect, but nothing to worry about */
813                            return 0;
814                    }
815                    else
816                    {
817                            /* return error */
818                            return 2;
819                    }
820          }          }
821    
822          return 0;  #endif
823    
824  }  }
825    
826    #ifdef EGD_SOCKET
827    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
828    static BOOL
829    generate_random_egd(uint8 * buf)
830    {
831            struct sockaddr_un addr;
832            BOOL ret = False;
833            int fd;
834    
835            fd = socket(AF_UNIX, SOCK_STREAM, 0);
836            if (fd == -1)
837                    return False;
838    
839            addr.sun_family = AF_UNIX;
840            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
841            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
842                    goto err;
843    
844            /* PRNGD and EGD use a simple communications protocol */
845            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
846            buf[1] = 32;            /* Number of requested random bytes */
847            if (write(fd, buf, 2) != 2)
848                    goto err;
849    
850            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
851                    goto err;
852    
853            if (read(fd, buf, 32) != 32)
854                    goto err;
855    
856            ret = True;
857    
858          err:
859            close(fd);
860            return ret;
861    }
862    #endif
863    
864  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
865  void  void
866  generate_random(uint8 *random)  generate_random(uint8 * random)
867  {  {
868          struct stat st;          struct stat st;
869          struct tms tmsbuf;          struct tms tmsbuf;
870          uint32 *r = (uint32 *) random;          MD5_CTX md5;
871          int fd;          uint32 *r;
872            int fd, n;
873    
874          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
875          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
876              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
877          {          {
878                  read(fd, random, 32);                  n = read(fd, random, 32);
879                  close(fd);                  close(fd);
880                  return;                  if (n == 32)
881                            return;
882          }          }
883    
884    #ifdef EGD_SOCKET
885            /* As a second preference use an EGD */
886            if (generate_random_egd(random))
887                    return;
888    #endif
889    
890          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
891            r = (uint32 *) random;
892          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
893          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
894          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 257  generate_random(uint8 *random) Line 897  generate_random(uint8 *random)
897          r[5] = st.st_atime;          r[5] = st.st_atime;
898          r[6] = st.st_mtime;          r[6] = st.st_mtime;
899          r[7] = st.st_ctime;          r[7] = st.st_ctime;
900    
901            /* Hash both halves with MD5 to obscure possible patterns */
902            MD5_Init(&md5);
903            MD5_Update(&md5, random, 16);
904            MD5_Final(random, &md5);
905            MD5_Update(&md5, random + 16, 16);
906            MD5_Final(random + 16, &md5);
907  }  }
908    
909  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 276  xmalloc(int size) Line 923  xmalloc(int size)
923  void *  void *
924  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
925  {  {
926          void *mem = realloc(oldmem, size);          void *mem;
927    
928            if (size < 1)
929                    size = 1;
930            mem = realloc(oldmem, size);
931          if (mem == NULL)          if (mem == NULL)
932          {          {
933                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 305  error(char *format, ...) Line 956  error(char *format, ...)
956          va_end(ap);          va_end(ap);
957  }  }
958    
959    /* report a warning */
960    void
961    warning(char *format, ...)
962    {
963            va_list ap;
964    
965            fprintf(stderr, "WARNING: ");
966    
967            va_start(ap, format);
968            vfprintf(stderr, format, ap);
969            va_end(ap);
970    }
971    
972  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
973  void  void
974  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 323  void Line 987  void
987  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
988  {  {
989          unsigned char *line = p;          unsigned char *line = p;
990          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
991    
992          while (offset < len)          while (offset < len)
993          {          {
# Line 337  hexdump(unsigned char *p, unsigned int l Line 1000  hexdump(unsigned char *p, unsigned int l
1000                          printf("%02x ", line[i]);                          printf("%02x ", line[i]);
1001    
1002                  for (; i < 16; i++)                  for (; i < 16; i++)
1003                                  printf("   ");                          printf("   ");
1004    
1005                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1006                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
1007    
1008                  printf("\n");                  printf("\n");
1009                  offset += thisline;                  offset += thisline;
# Line 350  hexdump(unsigned char *p, unsigned int l Line 1011  hexdump(unsigned char *p, unsigned int l
1011          }          }
1012  }  }
1013    
1014    /*
1015      input: src is the string we look in for needle.
1016             Needle may be escaped by a backslash, in
1017             that case we ignore that particular needle.
1018      return value: returns next src pointer, for
1019            succesive executions, like in a while loop
1020            if retval is 0, then there are no more args.
1021      pitfalls:
1022            src is modified. 0x00 chars are inserted to
1023            terminate strings.
1024            return val, points on the next val chr after ins
1025            0x00
1026    
1027            example usage:
1028            while( (pos = next_arg( optarg, ',')) ){
1029                    printf("%s\n",optarg);
1030                    optarg=pos;
1031            }
1032    
1033    */
1034    char *
1035    next_arg(char *src, char needle)
1036    {
1037            char *nextval;
1038            char *p;
1039            char *mvp = 0;
1040    
1041            /* EOS */
1042            if (*src == (char) 0x00)
1043                    return 0;
1044    
1045            p = src;
1046            /*  skip escaped needles */
1047            while ((nextval = strchr(p, needle)))
1048            {
1049                    mvp = nextval - 1;
1050                    /* found backslashed needle */
1051                    if (*mvp == '\\' && (mvp > src))
1052                    {
1053                            /* move string one to the left */
1054                            while (*(mvp + 1) != (char) 0x00)
1055                            {
1056                                    *mvp = *(mvp + 1);
1057                                    *mvp++;
1058                            }
1059                            *mvp = (char) 0x00;
1060                            p = nextval;
1061                    }
1062                    else
1063                    {
1064                            p = nextval + 1;
1065                            break;
1066                    }
1067    
1068            }
1069    
1070            /* more args available */
1071            if (nextval)
1072            {
1073                    *nextval = (char) 0x00;
1074                    return ++nextval;
1075            }
1076    
1077            /* no more args after this, jump to EOS */
1078            nextval = src + strlen(src);
1079            return nextval;
1080    }
1081    
1082    
1083    void
1084    toupper_str(char *p)
1085    {
1086            while (*p)
1087            {
1088                    if ((*p >= 'a') && (*p <= 'z'))
1089                            *p = toupper((int) *p);
1090                    p++;
1091            }
1092    }
1093    
1094    
1095    /* not all clibs got ltoa */
1096    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1097    
1098    char *
1099    l_to_a(long N, int base)
1100    {
1101            static char ret[LTOA_BUFSIZE];
1102    
1103            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1104    
1105            register int divrem;
1106    
1107            if (base < 36 || 2 > base)
1108                    base = 10;
1109    
1110            if (N < 0)
1111            {
1112                    *head++ = '-';
1113                    N = -N;
1114            }
1115    
1116            tail = buf + sizeof(buf);
1117            *--tail = 0;
1118    
1119            do
1120            {
1121                    divrem = N % base;
1122                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1123                    N /= base;
1124            }
1125            while (N);
1126    
1127            strcpy(head, tail);
1128            return ret;
1129    }
1130    
1131    
1132  int  int
1133  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1134  {  {
1135          char path[PATH_MAX];          char *home, *path;
         char *home;  
1136          struct stat st;          struct stat st;
1137          int fd;          int fd, length;
1138    
1139          home = getenv("HOME");          home = getenv("HOME");
1140          if (home == NULL)          if (home == NULL)
1141                  return -1;                  return -1;
1142    
1143          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1144          strncat(path, "/.rdesktop/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1145    
1146          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1147          if (fd == -1)          if (fd == -1)
# Line 372  load_licence(unsigned char **data) Line 1150  load_licence(unsigned char **data)
1150          if (fstat(fd, &st))          if (fstat(fd, &st))
1151                  return -1;                  return -1;
1152    
1153          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1154          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1155            close(fd);
1156            xfree(path);
1157            return length;
1158  }  }
1159    
1160  void  void
1161  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1162  {  {
1163          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1164          int fd;          int fd;
1165    
1166          home = getenv("HOME");          home = getenv("HOME");
1167          if (home == NULL)          if (home == NULL)
1168                  return;                  return;
1169    
1170          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
         strncat(path, "/.rdesktop", sizeof(path)-strlen(path)-1);  
         mkdir(path, 0700);  
1171    
1172          strncat(path, "/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop", home);
1173            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1174            {
1175                    perror(path);
1176                    return;
1177            }
1178    
1179            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1180    
1181            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1182            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1183            strcpy(tmppath, path);
1184            strcat(tmppath, ".new");
1185    
1186          fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1187          if (fd == -1)          if (fd == -1)
1188          {          {
1189                  perror("open");                  perror(tmppath);
1190                  return;                  return;
1191          }          }
1192    
1193          write(fd, data, length);          if (write(fd, data, length) != length)
1194            {
1195                    perror(tmppath);
1196                    unlink(tmppath);
1197            }
1198            else if (rename(tmppath, path) == -1)
1199            {
1200                    perror(path);
1201                    unlink(tmppath);
1202            }
1203    
1204            close(fd);
1205            xfree(tmppath);
1206            xfree(path);
1207    }
1208    
1209    /* Create the bitmap cache directory */
1210    BOOL
1211    rd_pstcache_mkdir(void)
1212    {
1213            char *home;
1214            char bmpcache_dir[256];
1215    
1216            home = getenv("HOME");
1217    
1218            if (home == NULL)
1219                    return False;
1220    
1221            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1222    
1223            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1224            {
1225                    perror(bmpcache_dir);
1226                    return False;
1227            }
1228    
1229            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1230    
1231            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1232            {
1233                    perror(bmpcache_dir);
1234                    return False;
1235            }
1236    
1237            return True;
1238    }
1239    
1240    /* open a file in the .rdesktop directory */
1241    int
1242    rd_open_file(char *filename)
1243    {
1244            char *home;
1245            char fn[256];
1246            int fd;
1247    
1248            home = getenv("HOME");
1249            if (home == NULL)
1250                    return -1;
1251            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1252            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1253            if (fd == -1)
1254                    perror(fn);
1255            return fd;
1256    }
1257    
1258    /* close file */
1259    void
1260    rd_close_file(int fd)
1261    {
1262          close(fd);          close(fd);
1263  }  }
1264    
1265    /* read from file*/
1266    int
1267    rd_read_file(int fd, void *ptr, int len)
1268    {
1269            return read(fd, ptr, len);
1270    }
1271    
1272    /* write to file */
1273    int
1274    rd_write_file(int fd, void *ptr, int len)
1275    {
1276            return write(fd, ptr, len);
1277    }
1278    
1279    /* move file pointer */
1280    int
1281    rd_lseek_file(int fd, int offset)
1282    {
1283            return lseek(fd, offset, SEEK_SET);
1284    }
1285    
1286    /* do a write lock on a file */
1287    BOOL
1288    rd_lock_file(int fd, int start, int len)
1289    {
1290            struct flock lock;
1291    
1292            lock.l_type = F_WRLCK;
1293            lock.l_whence = SEEK_SET;
1294            lock.l_start = start;
1295            lock.l_len = len;
1296            if (fcntl(fd, F_SETLK, &lock) == -1)
1297                    return False;
1298            return True;
1299    }

Legend:
Removed from v.39  
changed lines
  Added in v.968

  ViewVC Help
Powered by ViewVC 1.1.26