/[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 867 by stargo, Wed Mar 23 12:25:54 2005 UTC
# Line 1  Line 1 
1  /*  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-2000     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include <stdlib.h>             /* malloc realloc free */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25    #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
29    #include <ctype.h>              /* toupper */
30    #include <errno.h>
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33  char username[16];  #ifdef HAVE_ICONV
34  char hostname[16];  #ifdef HAVE_LOCALE_H
35  int width = 800;  #include <locale.h>
36  int height = 600;  #endif
37  int keylayout = 0x409;  #ifdef HAVE_LANGINFO_H
38  BOOL bitmap_compression = True;  #include <langinfo.h>
39  BOOL sendmotion = True;  #endif
40  BOOL orders = True;  #endif
41  BOOL licence = True;  
42  BOOL use_encryption = True;  #ifdef EGD_SOCKET
43  BOOL desktop_save = True;  #include <sys/socket.h>         /* socket connect */
44  BOOL fullscreen = False;  #include <sys/un.h>             /* sockaddr_un */
45    #endif
46    
47    #include <openssl/md5.h>
48    
49    char g_title[64] = "";
50    char g_username[64];
51    char g_hostname[16];
52    char keymapname[16];
53    int g_keylayout = 0x409;        /* Defaults to US keyboard layout */
54    
55    int g_width = 800;              /* width is special: If 0, the
56                                       geometry will be fetched from
57                                       _NET_WORKAREA. If negative,
58                                       absolute value specifies the
59                                       percent of the whole screen. */
60    int g_height = 600;
61    int g_xpos = 0;
62    int g_ypos = 0;
63    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          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
115          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
116          STATUS("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
117          STATUS("   -s: shell\n");  
118          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
119          STATUS("   -p: password (autologon)\n");  #ifdef RDP2VNC
120          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
121          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
122          STATUS("   -h: desktop height\n");  #endif
123          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -u: user name\n");
124          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
125          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -s: shell\n");
126          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -c: working directory\n");
127            fprintf(stderr, "   -p: password (- to prompt)\n");
128            fprintf(stderr, "   -n: client hostname\n");
129            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          struct passwd *pw;          char server[64];
362          char *server;          char fullhostname[64];
         uint32 flags;  
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;
369            uint32 flags, ext_disc_reason = 0;
370            char *p;
371          int c;          int c;
372    
373          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");  
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, "en-us");
379            g_embed_wnd = 0;
380    
381            g_num_devices = 0;
382    
383    #ifdef RDP2VNC
384    #define VNCOPT "V:Q:"
385    #else
386    #define VNCOPT
387    #endif
388    
389          while ((c = getopt(argc, argv, "u:d:s:c:p:n:g:k:mbleKFVh?")) != -1)          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;                                  break;
412    
413                          case 'd':                          case 'L':
414                                  strncpy(domain, optarg, sizeof(domain));  #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 'p':                          case 'd':
422                                  flags |= RDP_LOGON_AUTO;                                  STRNCPY(domain, optarg, sizeof(domain));
                                 strncpy(password, optarg, sizeof(password));  
423                                  break;                                  break;
424    
425                          case 's':                          case 's':
426                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
427                                  break;                                  break;
428    
429                          case 'c':                          case 'c':
430                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
431                                    break;
432    
433                            case 'p':
434                                    if ((optarg[0] == '-') && (optarg[1] == 0))
435                                    {
436                                            prompt_password = True;
437                                            break;
438                                    }
439    
440                                    STRNCPY(password, optarg, sizeof(password));
441                                    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;
452    
453                            case 'k':
454                                    STRNCPY(keymapname, optarg, sizeof(keymapname));
455                                  break;                                  break;
456    
457                          case 'g':                          case 'g':
458                                    g_fullscreen = False;
459                                    if (!strcmp(optarg, "workarea"))
460                                  {                                  {
461                                          char *tgem = 0;                                          g_width = g_height = 0;
462                                          width = strtol(optarg, NULL, 10);                                          break;
463                                          tgem = strchr(optarg, 'x');                                  }
464                                          if ((tgem == 0) || (strlen(tgem) < 2))  
465                                          {                                  g_width = strtol(optarg, &p, 10);
466                                                  ERROR                                  if (g_width <= 0)
467                                                          ("-g: invalid parameter. Syntax example: -g 1024x768\n");                                  {
468                                                  exit(1);                                          error("invalid geometry\n");
469                                          }                                          return 1;
470                                          height = strtol(tgem + 1, NULL, 10);                                  }
471    
472                                    if (*p == 'x')
473                                            g_height = strtol(p + 1, &p, 10);
474    
475                                    if (g_height <= 0)
476                                    {
477                                            error("invalid geometry\n");
478                                            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                                  }                                  }
                                 break;  
498    
                         case 'k':  
                                 keylayout = strtol(optarg, NULL, 16);  
                                 /* keylayout = find_keyb_code(optarg); */  
                                 if (keylayout == 0)  
                                         return 0;  
499                                  break;                                  break;
500    
501                          case 'm':                          case 'f':
502                                  sendmotion = False;                                  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 'l':                          case 'B':
510                                  licence = False;                                  g_ownbackstore = False;
511                                  break;                                  break;
512    
513                          case 'e':                          case 'e':
514                                  use_encryption = False;                                  g_encryption = False;
515                                    break;
516                            case 'E':
517                                    packet_encryption = False;
518                                    break;
519                            case 'm':
520                                    g_sendmotion = False;
521                                    break;
522    
523                            case 'C':
524                                    g_owncolmap = True;
525                                    break;
526    
527                            case 'D':
528                                    g_hide_decorations = True;
529                                    break;
530    
531                            case 'K':
532                                    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, 10);
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;                                  break;
599    
600                          case 'F':                          case 'P':
601                                  fullscreen = True;                                  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 159  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))
705                  {                  {
706                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
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          if (hostname[0] == 0)  #ifdef HAVE_ICONV
714            if (g_codepage[0] == 0)
715          {          {
716                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (setlocale(LC_CTYPE, ""))
717                  {                  {
718                          STATUS("Could not determine host name.\n");                          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 (g_hostname[0] == 0)
728            {
729                    if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
730                    {
731                            error("could not determine local hostname, use -n\n");
732                          return 1;                          return 1;
733                  }                  }
734    
735                    p = strchr(fullhostname, '.');
736                    if (p != NULL)
737                            *p = 0;
738    
739                    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
740          }          }
741    
742          strcpy(title, "rdesktop - ");          if ((flags & RDP_COMPRESSION) && (g_server_bpp > 8))
743          strncat(title, server, sizeof(title));          {
744                    warning("rdp compression not supported for bpp > 8, compression disabled\n");
745                    flags ^= RDP_COMPRESSION;
746            }
747    
748          if (ui_create_window(title))          if (prompt_password && read_password(password, sizeof(password)))
749                    flags |= RDP_LOGON_AUTO;
750    
751            if (g_title[0] == 0)
752          {          {
753                  if (!rdp_connect(server, flags, domain, password, shell,                  strcpy(g_title, "rdesktop - ");
754                                   directory))                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
755                          return 1;          }
756    
757    #ifdef RDP2VNC
758            rdp2vnc_connect(server, flags, domain, password, shell, directory);
759            return 0;
760    #else
761    
762            if (!ui_init())
763                    return 1;
764    
765    #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))
772                    return 1;
773    
774            /* 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                  STATUS("Connection successful.\n");          if (ui_create_window())
784                  rdp_main_loop();          {
785                    rdp_main_loop(&deactivated, &ext_disc_reason);
786                  ui_destroy_window();                  ui_destroy_window();
787          }          }
788    
789            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
861  generate_random(uint8 *random)  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          /* If we have a kernel random device, use it. */  
869          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
870            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
871                || ((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 232  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 241  xmalloc(int size) Line 908  xmalloc(int size)
908          void *mem = malloc(size);          void *mem = malloc(size);
909          if (mem == NULL)          if (mem == NULL)
910          {          {
911                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
912                  exit(1);                  exit(1);
913          }          }
914          return mem;          return mem;
# Line 251  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);
929                  exit(1);                  exit(1);
930          }          }
931          return mem;          return mem;
# Line 267  xfree(void *mem) Line 938  xfree(void *mem)
938          free(mem);          free(mem);
939  }  }
940    
941  /* Produce a hex dump */  /* report an error */
942    void
943    error(char *format, ...)
944    {
945            va_list ap;
946    
947            fprintf(stderr, "ERROR: ");
948    
949            va_start(ap, format);
950            vfprintf(stderr, format, ap);
951            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 */
968    void
969    unimpl(char *format, ...)
970    {
971            va_list ap;
972    
973            fprintf(stderr, "NOT IMPLEMENTED: ");
974    
975            va_start(ap, format);
976            vfprintf(stderr, format, ap);
977            va_end(ap);
978    }
979    
980    /* produce a hex dump */
981  void  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          {          {
989                  STATUS("%04x ", offset);                  printf("%04x ", offset);
990                  thisline = len - offset;                  thisline = len - offset;
991                  if (thisline > 16)                  if (thisline > 16)
992                          thisline = 16;                          thisline = 16;
993    
994                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
995                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
996                                  STATUS("   ");  
997                    for (; i < 16; i++)
998                            printf("   ");
999    
1000                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1001                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
1002    
1003                  STATUS("\n");                  printf("\n");
1004                  offset += thisline;                  offset += thisline;
1005                  line += thisline;                  line += thisline;
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
1128    load_licence(unsigned char **data)
1129    {
1130            char *home, *path;
1131            struct stat st;
1132            int fd, length;
1133    
1134            home = getenv("HOME");
1135            if (home == NULL)
1136                    return -1;
1137    
1138            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1139            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1140    
1141            fd = open(path, O_RDONLY);
1142            if (fd == -1)
1143                    return -1;
1144    
1145            if (fstat(fd, &st))
1146                    return -1;
1147    
1148            *data = (uint8 *) xmalloc(st.st_size);
1149            length = read(fd, *data, st.st_size);
1150            close(fd);
1151            xfree(path);
1152            return length;
1153    }
1154    
1155    void
1156    save_licence(unsigned char *data, int length)
1157    {
1158            char *home, *path, *tmppath;
1159            int fd;
1160    
1161            home = getenv("HOME");
1162            if (home == NULL)
1163                    return;
1164    
1165            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1166    
1167            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            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(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1182            if (fd == -1)
1183            {
1184                    perror(tmppath);
1185                    return;
1186            }
1187    
1188            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);
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.29  
changed lines
  Added in v.867

  ViewVC Help
Powered by ViewVC 1.1.26