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

Legend:
Removed from v.33  
changed lines
  Added in v.964

  ViewVC Help
Powered by ViewVC 1.1.26