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

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

  ViewVC Help
Powered by ViewVC 1.1.26