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

Legend:
Removed from v.29  
changed lines
  Added in v.861

  ViewVC Help
Powered by ViewVC 1.1.26