/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdesktop.c

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

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

Legend:
Removed from v.79  
changed lines
  Added in v.855

  ViewVC Help
Powered by ViewVC 1.1.26