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

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

  ViewVC Help
Powered by ViewVC 1.1.26