/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.30  
changed lines
  Added in v.973

  ViewVC Help
Powered by ViewVC 1.1.26