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

Legend:
Removed from v.17  
changed lines
  Added in v.975

  ViewVC Help
Powered by ViewVC 1.1.26