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

Legend:
Removed from v.10  
changed lines
  Added in v.977

  ViewVC Help
Powered by ViewVC 1.1.26