/[rdesktop]/jpeg/rdesktop/trunk/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 /jpeg/rdesktop/trunk/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.25  
changed lines
  Added in v.962

  ViewVC Help
Powered by ViewVC 1.1.26