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

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

  ViewVC Help
Powered by ViewVC 1.1.26