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

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

  ViewVC Help
Powered by ViewVC 1.1.26