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

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

revision 79 by astrand, Mon Jul 29 20:35:13 2002 UTC revision 881 by stargo, Mon Apr 4 16:37:19 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-2001     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    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #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 <limits.h>             /* PATH_MAX */  #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_ICONV
34  char hostname[16];  #ifdef HAVE_LOCALE_H
35    #include <locale.h>
36    #endif
37    #ifdef HAVE_LANGINFO_H
38    #include <langinfo.h>
39    #endif
40    #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[16];  char keymapname[16];
54  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int g_keylayout = 0x409;        /* Defaults to US keyboard layout */
 int width;  
 int height;  
 int tcp_port_rdp = TCP_PORT_RDP;  
 BOOL bitmap_compression = True;  
 BOOL sendmotion = True;  
 BOOL orders = True;  
 BOOL licence = True;  
 BOOL encryption = True;  
 BOOL desktop_save = True;  
 BOOL fullscreen = False;  
 BOOL grab_keyboard = True;  
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          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
116          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
117          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
118          printf("   -s: shell\n");  
119          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
120          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
121          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
122          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
123          printf("   -g: desktop geometry (WxH)\n");  #endif
124          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
125          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
126          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
127          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
128          printf("   -l: do not request licence\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
129          printf("   -t: rdp tcp port\n");          fprintf(stderr, "   -n: client hostname\n");
130          printf("   -K: keep window manager key bindings\n");          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    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            char server[64];
363          char fullhostname[64];          char fullhostname[64];
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;          struct passwd *pw;
370          char *server, *p;          uint32 flags, ext_disc_reason = 0;
371          uint32 flags;          char *p;
372          int c;          int c;
373    
374          printf("rdesktop: A Remote Desktop Protocol client.\n");          int username_option = 0;
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("See http://www.rdesktop.org/ for more information.\n\n");  
375    
376          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
377            prompt_password = False;
378          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
379          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
380            g_embed_wnd = 0;
381    
382            g_num_devices = 0;
383    
384          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -1)  #ifdef RDP2VNC
385    #define VNCOPT "V:Q:"
386    #else
387    #define VNCOPT
388    #endif
389    
390            while ((c = getopt(argc, argv,
391                               VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
392          {          {
393                  switch (c)                  switch (c)
394                  {                  {
395    #ifdef RDP2VNC
396                            case 'V':
397                                    rfb_port = strtol(optarg, NULL, 10);
398                                    if (rfb_port < 100)
399                                            rfb_port += 5900;
400                                    break;
401    
402                            case 'Q':
403                                    defer_time = strtol(optarg, NULL, 10);
404                                    if (defer_time < 0)
405                                            defer_time = 0;
406                                    break;
407    #endif
408    
409                          case 'u':                          case 'u':
410                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
411                                    username_option = 1;
412                                    break;
413    
414                            case 'L':
415    #ifdef HAVE_ICONV
416                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
417    #else
418                                    error("iconv support not available\n");
419    #endif
420                                  break;                                  break;
421    
422                          case 'd':                          case 'd':
# Line 112  main(int argc, char *argv[]) Line 432  main(int argc, char *argv[])
432                                  break;                                  break;
433    
434                          case 'p':                          case 'p':
435                                    if ((optarg[0] == '-') && (optarg[1] == 0))
436                                    {
437                                            prompt_password = True;
438                                            break;
439                                    }
440    
441                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
442                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
443    
444                                    /* try to overwrite argument so it won't appear in ps */
445                                    p = optarg;
446                                    while (*p)
447                                            *(p++) = 'X';
448                                  break;                                  break;
449    
450                          case 'n':                          case 'n':
451                                  STRNCPY(hostname, optarg, sizeof(hostname));                                  STRNCPY(g_hostname, optarg, sizeof(g_hostname));
452                                  break;                                  break;
453    
454                          case 'k':                          case 'k':
455                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
456                                  break;                                  break;
457    
458                          case 'g':                          case 'g':
459                                  width = strtol(optarg, &p, 10);                                  g_fullscreen = False;
460                                    if (!strcmp(optarg, "workarea"))
461                                    {
462                                            g_width = g_height = 0;
463                                            break;
464                                    }
465    
466                                    g_width = strtol(optarg, &p, 10);
467                                    if (g_width <= 0)
468                                    {
469                                            error("invalid geometry\n");
470                                            return 1;
471                                    }
472    
473                                  if (*p == 'x')                                  if (*p == 'x')
474                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, &p, 10);
475    
476                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
477                                  {                                  {
478                                          error("invalid geometry\n");                                          error("invalid geometry\n");
479                                          return 1;                                          return 1;
480                                  }                                  }
481    
482                                    if (*p == '%')
483                                    {
484                                            g_width = -g_width;
485                                            p++;
486                                    }
487    
488                                    if (*p == '+' || *p == '-')
489                                    {
490                                            g_pos |= (*p == '-') ? 2 : 1;
491                                            g_xpos = strtol(p, &p, 10);
492    
493                                    }
494                                    if (*p == '+' || *p == '-')
495                                    {
496                                            g_pos |= (*p == '-') ? 4 : 1;
497                                            g_ypos = strtol(p, NULL, 10);
498                                    }
499    
500                                  break;                                  break;
501    
502                          case 'f':                          case 'f':
503                                  fullscreen = True;                                  g_fullscreen = True;
504                                  break;                                  break;
505    
506                          case 'b':                          case 'b':
507                                  orders = False;                                  g_bitmap_cache = False;
508                                  break;                                  break;
509    
510                          case 'e':                          case 'B':
511                                  encryption = False;                                  g_ownbackstore = False;
512                                  break;                                  break;
513    
514                            case 'e':
515                                    g_encryption = False;
516                                    break;
517                            case 'E':
518                                    packet_encryption = False;
519                                    break;
520                          case 'm':                          case 'm':
521                                  sendmotion = False;                                  g_sendmotion = False;
522                                  break;                                  break;
523    
524                          case 'l':                          case 'C':
525                                  licence = False;                                  g_owncolmap = True;
526                                  break;                                  break;
527    
528                          case 't':                          case 'D':
529                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_hide_decorations = True;
530                                  break;                                  break;
531    
532                          case 'K':                          case 'K':
533                                  grab_keyboard = False;                                  g_grab_keyboard = False;
534                                    break;
535    
536                            case 'S':
537                                    if (!strcmp(optarg, "standard"))
538                                    {
539                                            g_win_button_size = 18;
540                                            break;
541                                    }
542    
543                                    g_win_button_size = strtol(optarg, &p, 10);
544    
545                                    if (*p)
546                                    {
547                                            error("invalid button size\n");
548                                            return 1;
549                                    }
550    
551                                    break;
552    
553                            case 'T':
554                                    STRNCPY(g_title, optarg, sizeof(g_title));
555                                    break;
556    
557                            case 'N':
558                                    g_numlock_sync = True;
559                                    break;
560    
561                            case 'X':
562                                    g_embed_wnd = strtol(optarg, NULL, 0);
563                                    break;
564    
565                            case 'a':
566                                    g_server_bpp = strtol(optarg, NULL, 10);
567                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
568                                        && g_server_bpp != 24)
569                                    {
570                                            error("invalid server bpp\n");
571                                            return 1;
572                                    }
573                                    break;
574    
575                            case 'z':
576                                    DEBUG(("rdp compression enabled\n"));
577                                    flags |= RDP_COMPRESSION;
578                                    break;
579    
580                            case 'x':
581                                    if (strncmp("modem", optarg, 1) == 0)
582                                    {
583                                            g_rdp5_performanceflags =
584                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
585                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
586                                    }
587                                    else if (strncmp("broadband", optarg, 1) == 0)
588                                    {
589                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
590                                    }
591                                    else if (strncmp("lan", optarg, 1) == 0)
592                                    {
593                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
594                                    }
595                                    else
596                                    {
597                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
598                                    }
599                                    break;
600    
601                            case 'P':
602                                    g_bitmap_cache_persist_enable = True;
603                                    break;
604    
605                            case 'r':
606    
607                                    if (strncmp("sound", optarg, 5) == 0)
608                                    {
609                                            optarg += 5;
610    
611                                            if (*optarg == ':')
612                                            {
613                                                    *optarg++;
614                                                    while ((p = next_arg(optarg, ',')))
615                                                    {
616                                                            if (strncmp("remote", optarg, 6) == 0)
617                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
618    
619                                                            if (strncmp("local", optarg, 5) == 0)
620    #ifdef WITH_RDPSND
621                                                                    g_rdpsnd = True;
622    #else
623                                                                    warning("Not compiled with sound support\n");
624    #endif
625    
626                                                            if (strncmp("off", optarg, 3) == 0)
627    #ifdef WITH_RDPSND
628                                                                    g_rdpsnd = False;
629    #else
630                                                                    warning("Not compiled with sound support\n");
631    #endif
632    
633                                                            optarg = p;
634                                                    }
635                                            }
636                                            else
637                                            {
638    #ifdef WITH_RDPSND
639                                                    g_rdpsnd = True;
640    #else
641                                                    warning("Not compiled with sound support\n");
642    #endif
643                                            }
644                                    }
645                                    else if (strncmp("disk", optarg, 4) == 0)
646                                    {
647                                            /* -r disk:h:=/mnt/floppy */
648                                            disk_enum_devices(&g_num_devices, optarg + 4);
649                                    }
650                                    else if (strncmp("comport", optarg, 7) == 0)
651                                    {
652                                            serial_enum_devices(&g_num_devices, optarg + 7);
653                                    }
654                                    else if (strncmp("lptport", optarg, 7) == 0)
655                                    {
656                                            parallel_enum_devices(&g_num_devices, optarg + 7);
657                                    }
658                                    else if (strncmp("printer", optarg, 7) == 0)
659                                    {
660                                            printer_enum_devices(&g_num_devices, optarg + 7);
661                                    }
662                                    else if (strncmp("clientname", optarg, 7) == 0)
663                                    {
664                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
665                                            strcpy(g_rdpdr_clientname, optarg + 11);
666                                    }
667                                    else
668                                    {
669                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
670                                    }
671                                    break;
672    
673                            case '0':
674                                    g_console_session = True;
675                                    break;
676    
677                            case '4':
678                                    g_use_rdp5 = False;
679                                    break;
680    
681                            case '5':
682                                    g_use_rdp5 = True;
683                                  break;                                  break;
684    
685                          case 'h':                          case 'h':
# Line 173  main(int argc, char *argv[]) Line 690  main(int argc, char *argv[])
690                  }                  }
691          }          }
692    
693          if (argc - optind < 1)          if (argc - optind != 1)
694          {          {
695                  usage(argv[0]);                  usage(argv[0]);
696                  return 1;                  return 1;
697          }          }
698    
699          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
700            parse_server_and_port(server);
701    
702          if (username[0] == 0)          if (!username_option)
703          {          {
704                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
705                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 190  main(int argc, char *argv[]) Line 708  main(int argc, char *argv[])
708                          return 1;                          return 1;
709                  }                  }
710    
711                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
712            }
713    
714    #ifdef HAVE_ICONV
715            if (g_codepage[0] == 0)
716            {
717                    if (setlocale(LC_CTYPE, ""))
718                    {
719                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
720                    }
721                    else
722                    {
723                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
724                    }
725          }          }
726    #endif
727    
728          if (hostname[0] == 0)          if (g_hostname[0] == 0)
729          {          {
730                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
731                  {                  {
# Line 205  main(int argc, char *argv[]) Line 737  main(int argc, char *argv[])
737                  if (p != NULL)                  if (p != NULL)
738                          *p = 0;                          *p = 0;
739    
740                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
741          }          }
742    
743          if (!strcmp(password, "-"))          if ((flags & RDP_COMPRESSION) && (g_server_bpp > 8))
744          {          {
745                  p = getpass("Password: ");                  warning("rdp compression not supported for bpp > 8, compression disabled\n");
746                  if (p == NULL)                  flags ^= RDP_COMPRESSION;
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
747          }          }
748    
749          if ((width == 0) || (height == 0))          if (prompt_password && read_password(password, sizeof(password)))
750                    flags |= RDP_LOGON_AUTO;
751    
752            if (g_title[0] == 0)
753          {          {
754                  width = 800;                  strcpy(g_title, "rdesktop - ");
755                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
756          }          }
757    
758          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
759          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
760            return 0;
761    #else
762    
763            if (!ui_init())
764                    return 1;
765    
766          xkeymap_init1();  #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          printf("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            DEBUG(("Connection successful.\n"));
782            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          printf("Disconnecting...\n");          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
# Line 252  generate_random(uint8 * random) Line 863  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    
870          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
871          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
872              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((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 273  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 292  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);
# Line 321  error(char *format, ...) Line 952  error(char *format, ...)
952          va_end(ap);          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 */  /* report an unimplemented protocol feature */
969  void  void
970  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 339  void Line 983  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          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 999  hexdump(unsigned char *p, unsigned int l
999                          printf("   ");                          printf("   ");
1000    
1001                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1002                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
1003    
1004                  printf("\n");                  printf("\n");
1005                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 1007  hexdump(unsigned char *p, unsigned int l
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  int
1129  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1130  {  {
1131          char path[PATH_MAX];          char *home, *path;
         char *home;  
1132          struct stat st;          struct stat st;
1133          int fd;          int fd, length;
1134    
1135          home = getenv("HOME");          home = getenv("HOME");
1136          if (home == NULL)          if (home == NULL)
1137                  return -1;                  return -1;
1138    
1139          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1140          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1141    
1142          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1143          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 1146  load_licence(unsigned char **data)
1146          if (fstat(fd, &st))          if (fstat(fd, &st))
1147                  return -1;                  return -1;
1148    
1149          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1150          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1151            close(fd);
1152            xfree(path);
1153            return length;
1154  }  }
1155    
1156  void  void
1157  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1158  {  {
1159          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1160          int fd;          int fd;
1161    
1162          home = getenv("HOME");          home = getenv("HOME");
1163          if (home == NULL)          if (home == NULL)
1164                  return;                  return;
1165    
1166          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1167          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
1168          mkdir(path, 0700);          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          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          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(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1183          if (fd == -1)          if (fd == -1)
1184          {          {
1185                  perror("open");                  perror(tmppath);
1186                  return;                  return;
1187          }          }
1188    
1189          write(fd, data, length);          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);          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.79  
changed lines
  Added in v.881

  ViewVC Help
Powered by ViewVC 1.1.26