/[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 17 by matty, Thu Sep 28 15:54:11 2000 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-2000     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include <stdlib.h>     /* malloc realloc free */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>     /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>      /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>        /* getpwuid */  #include <pwd.h>                /* getpwuid */
25  #include <sys/stat.h>   /* stat */  #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/time.h>   /* gettimeofday */  #include <sys/stat.h>           /* stat */
27  #include <sys/times.h>  /* times */  #include <sys/time.h>           /* gettimeofday */
28    #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 = 800;  #endif
36  int height = 600;  #ifdef HAVE_ICONV
37  int keylayout = 0x409;  #ifdef HAVE_LANGINFO_H
38  BOOL motion = False;  #include <langinfo.h>
39  BOOL orders = True;  #endif
40  BOOL licence = True;  #endif
41    
42    #ifdef EGD_SOCKET
43    #include <sys/types.h>
44    #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 usage(char *program)  static void
116    usage(char *program)
117  {  {
118          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
119          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
120          STATUS("   -n: client hostname\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
121          STATUS("   -w: desktop width\n");  
122          STATUS("   -h: desktop height\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
123          STATUS("   -k: keyboard layout (hex)\n");  #ifdef RDP2VNC
124          STATUS("   -m: send motion events\n");          fprintf(stderr, "   -V: vnc port\n");
125          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
126          STATUS("   -l: do not request licence\n\n");  #endif
127            fprintf(stderr, "   -u: user name\n");
128            fprintf(stderr, "   -d: domain\n");
129            fprintf(stderr, "   -s: shell\n");
130            fprintf(stderr, "   -c: working directory\n");
131            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 main(int argc, char *argv[])  int
363    main(int argc, char *argv[])
364  {  {
365            char server[64];
366            char fullhostname[64];
367            char domain[16];
368            char password[64];
369            char shell[128];
370            char directory[32];
371            BOOL prompt_password, deactivated;
372          struct passwd *pw;          struct passwd *pw;
373          char *server;          uint32 flags, ext_disc_reason = 0;
374          char title[32];          char *p;
375          int c;          int c;
376            char *locale;
377            int username_option = 0;
378    
379            /* Set locale according to environment */
380            locale = setlocale(LC_ALL, "");
381            if (locale)
382            {
383                    xkeymap_from_locale(locale);
384            }
385    
386          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          flags = RDP_LOGON_NORMAL;
387          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n");          prompt_password = False;
388          STATUS("See http://www.rdesktop.org/ for more information.\n\n");          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:n:w:h:k:mbl?")) != -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;                                  break;
422    
423                          case 'n':                          case 'L':
424                                  strncpy(hostname, optarg, sizeof(hostname));  #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 'w':                          case 'd':
432                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(domain, optarg, sizeof(domain));
433                                  break;                                  break;
434    
435                          case 'h':                          case 's':
436                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
437                                    break;
438    
439                            case 'c':
440                                    STRNCPY(directory, optarg, sizeof(directory));
441                                    break;
442    
443                            case 'p':
444                                    if ((optarg[0] == '-') && (optarg[1] == 0))
445                                    {
446                                            prompt_password = True;
447                                            break;
448                                    }
449    
450                                    STRNCPY(password, optarg, sizeof(password));
451                                    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;
458    
459                            case 'n':
460                                    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                                  break;                                  break;
466    
467                          case 'm':                          case 'g':
468                                  motion = True;                                  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 geometry\n");
479                                            return 1;
480                                    }
481    
482                                    if (*p == 'x')
483                                            g_height = strtol(p + 1, &p, 10);
484    
485                                    if (g_height <= 0)
486                                    {
487                                            error("invalid geometry\n");
488                                            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;
510    
511                            case 'f':
512                                    g_fullscreen = True;
513                                  break;                                  break;
514    
515                          case 'b':                          case 'b':
516                                  orders = False;                                  g_bitmap_cache = False;
517                                    break;
518    
519                            case 'B':
520                                    g_ownbackstore = False;
521                                    break;
522    
523                            case 'e':
524                                    g_encryption = False;
525                                    break;
526                            case 'E':
527                                    packet_encryption = False;
528                                    break;
529                            case 'm':
530                                    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;                                  break;
540    
541                          case 'l':                          case 'K':
542                                  licence = False;                                  g_grab_keyboard = False;
543                                  break;                                  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;
561    
562                            case 'T':
563                                    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;
693    
694                            case 'h':
695                          case '?':                          case '?':
696                          default:                          default:
697                                  usage(argv[0]);                                  usage(argv[0]);
# Line 105  int main(int argc, char *argv[]) Line 699  int 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))
715                  {                  {
716                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
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 (gethostname(hostname, sizeof(hostname)) == -1)                  if (setlocale(LC_CTYPE, ""))
727                  {                  {
728                          STATUS("Could not determine host name.\n");                          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)
740                    {
741                            error("could not determine local hostname, use -n\n");
742                          return 1;                          return 1;
743                  }                  }
744    
745                    p = strchr(fullhostname, '.');
746                    if (p != NULL)
747                            *p = 0;
748    
749                    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
750          }          }
751    
752          if (!rdp_connect(server))          if (prompt_password && read_password(password, sizeof(password)))
753                    flags |= RDP_LOGON_AUTO;
754    
755            if (g_title[0] == 0)
756            {
757                    strcpy(g_title, "rdesktop - ");
758                    strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
759            }
760    
761    #ifdef RDP2VNC
762            rdp2vnc_connect(server, flags, domain, password, shell, directory);
763            return 0;
764    #else
765    
766            if (!ui_init())
767                    return 1;
768    
769    #ifdef WITH_RDPSND
770            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;                  return 1;
777    
778          STATUS("Connection successful.\n");          /* 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          strcpy(title, "rdesktop - ");          DEBUG(("Connection successful.\n"));
785          strncat(title, server, sizeof(title));          memset(password, 0, sizeof(password));
786    
787          if (ui_create_window(title))          if (ui_create_window())
788          {          {
789                  rdp_main_loop();                  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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
826  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
831          uint32 *r = (uint32 *)random;          BOOL ret = False;
832          int fd;          int fd;
833    
834          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
835          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
864    void
865    generate_random(uint8 * random)
866    {
867            struct stat st;
868            struct tms tmsbuf;
869            MD5_CTX md5;
870            uint32 *r;
871            int fd, n;
872    
873            /* If we have a kernel random device, try that first */
874            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
875                || ((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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
894          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
895          stat("/tmp", &st);          stat("/tmp", &st);
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 */
909  void *xmalloc(int size)  void *
910    xmalloc(int size)
911  {  {
912          void *mem = malloc(size);          void *mem = malloc(size);
913          if (mem == NULL)          if (mem == NULL)
914          {          {
915                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
916                  exit(1);                  exit(1);
917          }          }
918          return mem;          return mem;
919  }  }
920    
921  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
922  void *xrealloc(void *oldmem, int size)  void *
923    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);
933                  exit(1);                  exit(1);
934          }          }
935          return mem;          return mem;
936  }  }
937    
938  /* free */  /* free */
939  void xfree(void *mem)  void
940    xfree(void *mem)
941  {  {
942          free(mem);          free(mem);
943  }  }
944    
945  /* Produce a hex dump */  /* report an error */
946  void hexdump(unsigned char *p, unsigned int len)  void
947    error(char *format, ...)
948    {
949            va_list ap;
950    
951            fprintf(stderr, "ERROR: ");
952    
953            va_start(ap, format);
954            vfprintf(stderr, format, ap);
955            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 */
972    void
973    unimpl(char *format, ...)
974    {
975            va_list ap;
976    
977            fprintf(stderr, "NOT IMPLEMENTED: ");
978    
979            va_start(ap, format);
980            vfprintf(stderr, format, ap);
981            va_end(ap);
982    }
983    
984    /* produce a hex dump */
985    void
986    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          {          {
993                  STATUS("%04x ", offset);                  printf("%04x ", offset);
994                  thisline = len - offset;                  thisline = len - offset;
995                  if (thisline > 16)                  if (thisline > 16)
996                          thisline = 16;                          thisline = 16;
997    
998                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
999                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
1000    
1001                  for (; i < 16; i++)                  for (; i < 16; i++)
1002                          STATUS("   ");                          printf("   ");
1003    
1004                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1005                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1006    
1007                  STATUS("\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.17  
changed lines
  Added in v.964

  ViewVC Help
Powered by ViewVC 1.1.26