/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

revision 79 by astrand, Mon Jul 29 20:35:13 2002 UTC revision 958 by astrand, Wed Aug 3 08:36:08 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  char keymapname[16];  #include <locale.h>
36  int keylayout = 0x409;          /* Defaults to US keyboard layout */  #endif
37  int width;  #ifdef HAVE_LANGINFO_H
38  int height;  #include <langinfo.h>
39  int tcp_port_rdp = TCP_PORT_RDP;  #endif
40  BOOL bitmap_compression = True;  #endif
41  BOOL sendmotion = True;  
42  BOOL orders = True;  #ifdef EGD_SOCKET
43  BOOL licence = True;  #include <sys/types.h>
44  BOOL encryption = True;  #include <sys/socket.h>         /* socket connect */
45  BOOL desktop_save = True;  #include <sys/un.h>             /* sockaddr_un */
46  BOOL fullscreen = False;  #endif
47  BOOL grab_keyboard = True;  
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];
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          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    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            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    #ifdef RDP2VNC
385    #define VNCOPT "V:Q:"
386    #else
387    #define VNCOPT
388    #endif
389    
390          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -1)          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_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
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          if (hostname[0] == 0)  #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 (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 (prompt_password && read_password(password, sizeof(password)))
744          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
745    
746          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
747          {          {
748                  width = 800;                  strcpy(g_title, "rdesktop - ");
749                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
750          }          }
751    
752          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
753          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
754            return 0;
755    #else
756    
757            if (!ui_init())
758                    return 1;
759    
760          xkeymap_init1();  #ifdef WITH_RDPSND
761            if (g_rdpsnd)
762                    rdpsnd_init();
763    #endif
764            rdpdr_init();
765    
766          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
767                  return 1;                  return 1;
768    
769          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
770               packet but unencrypted transfer of other packets */
771            if (!packet_encryption)
772                    g_encryption = False;
773    
774    
775          if (ui_create_window(title))          DEBUG(("Connection successful.\n"));
776            memset(password, 0, sizeof(password));
777    
778            if (ui_create_window())
779          {          {
780                  rdp_main_loop();                  rdp_main_loop(&deactivated, &ext_disc_reason);
781                  ui_destroy_window();                  ui_destroy_window();
782          }          }
783    
784          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
785          rdp_disconnect();          rdp_disconnect();
786          return 0;          cache_save_state();
787            ui_deinit();
788    
789            if (ext_disc_reason >= 2)
790                    print_disconnect_reason(ext_disc_reason);
791    
792            if (deactivated)
793            {
794                    /* clean disconnect */
795                    return 0;
796            }
797            else
798            {
799                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
800                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
801                    {
802                            /* not so clean disconnect, but nothing to worry about */
803                            return 0;
804                    }
805                    else
806                    {
807                            /* return error */
808                            return 2;
809                    }
810            }
811    
812    #endif
813    
814    }
815    
816    #ifdef EGD_SOCKET
817    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
818    static BOOL
819    generate_random_egd(uint8 * buf)
820    {
821            struct sockaddr_un addr;
822            BOOL ret = False;
823            int fd;
824    
825            fd = socket(AF_UNIX, SOCK_STREAM, 0);
826            if (fd == -1)
827                    return False;
828    
829            addr.sun_family = AF_UNIX;
830            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
831            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
832                    goto err;
833    
834            /* PRNGD and EGD use a simple communications protocol */
835            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
836            buf[1] = 32;            /* Number of requested random bytes */
837            if (write(fd, buf, 2) != 2)
838                    goto err;
839    
840            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
841                    goto err;
842    
843            if (read(fd, buf, 32) != 32)
844                    goto err;
845    
846            ret = True;
847    
848          err:
849            close(fd);
850            return ret;
851  }  }
852    #endif
853    
854  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
855  void  void
# Line 252  generate_random(uint8 * random) Line 857  generate_random(uint8 * random)
857  {  {
858          struct stat st;          struct stat st;
859          struct tms tmsbuf;          struct tms tmsbuf;
860          uint32 *r = (uint32 *) random;          MD5_CTX md5;
861          int fd;          uint32 *r;
862            int fd, n;
863    
864          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
865          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
866              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
867          {          {
868                  read(fd, random, 32);                  n = read(fd, random, 32);
869                  close(fd);                  close(fd);
870                  return;                  if (n == 32)
871                            return;
872          }          }
873    
874    #ifdef EGD_SOCKET
875            /* As a second preference use an EGD */
876            if (generate_random_egd(random))
877                    return;
878    #endif
879    
880          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
881            r = (uint32 *) random;
882          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
883          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
884          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 887  generate_random(uint8 * random)
887          r[5] = st.st_atime;          r[5] = st.st_atime;
888          r[6] = st.st_mtime;          r[6] = st.st_mtime;
889          r[7] = st.st_ctime;          r[7] = st.st_ctime;
890    
891            /* Hash both halves with MD5 to obscure possible patterns */
892            MD5_Init(&md5);
893            MD5_Update(&md5, random, 16);
894            MD5_Final(random, &md5);
895            MD5_Update(&md5, random + 16, 16);
896            MD5_Final(random + 16, &md5);
897  }  }
898    
899  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 292  xmalloc(int size) Line 913  xmalloc(int size)
913  void *  void *
914  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
915  {  {
916          void *mem = realloc(oldmem, size);          void *mem;
917    
918            if (size < 1)
919                    size = 1;
920            mem = realloc(oldmem, size);
921          if (mem == NULL)          if (mem == NULL)
922          {          {
923                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 321  error(char *format, ...) Line 946  error(char *format, ...)
946          va_end(ap);          va_end(ap);
947  }  }
948    
949    /* report a warning */
950    void
951    warning(char *format, ...)
952    {
953            va_list ap;
954    
955            fprintf(stderr, "WARNING: ");
956    
957            va_start(ap, format);
958            vfprintf(stderr, format, ap);
959            va_end(ap);
960    }
961    
962  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
963  void  void
964  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 339  void Line 977  void
977  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
978  {  {
979          unsigned char *line = p;          unsigned char *line = p;
980          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
981    
982          while (offset < len)          while (offset < len)
983          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 993  hexdump(unsigned char *p, unsigned int l
993                          printf("   ");                          printf("   ");
994    
995                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
996                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
997    
998                  printf("\n");                  printf("\n");
999                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 1001  hexdump(unsigned char *p, unsigned int l
1001          }          }
1002  }  }
1003    
1004    /*
1005      input: src is the string we look in for needle.
1006             Needle may be escaped by a backslash, in
1007             that case we ignore that particular needle.
1008      return value: returns next src pointer, for
1009            succesive executions, like in a while loop
1010            if retval is 0, then there are no more args.
1011      pitfalls:
1012            src is modified. 0x00 chars are inserted to
1013            terminate strings.
1014            return val, points on the next val chr after ins
1015            0x00
1016    
1017            example usage:
1018            while( (pos = next_arg( optarg, ',')) ){
1019                    printf("%s\n",optarg);
1020                    optarg=pos;
1021            }
1022    
1023    */
1024    char *
1025    next_arg(char *src, char needle)
1026    {
1027            char *nextval;
1028            char *p;
1029            char *mvp = 0;
1030    
1031            /* EOS */
1032            if (*src == (char) 0x00)
1033                    return 0;
1034    
1035            p = src;
1036            /*  skip escaped needles */
1037            while ((nextval = strchr(p, needle)))
1038            {
1039                    mvp = nextval - 1;
1040                    /* found backslashed needle */
1041                    if (*mvp == '\\' && (mvp > src))
1042                    {
1043                            /* move string one to the left */
1044                            while (*(mvp + 1) != (char) 0x00)
1045                            {
1046                                    *mvp = *(mvp + 1);
1047                                    *mvp++;
1048                            }
1049                            *mvp = (char) 0x00;
1050                            p = nextval;
1051                    }
1052                    else
1053                    {
1054                            p = nextval + 1;
1055                            break;
1056                    }
1057    
1058            }
1059    
1060            /* more args available */
1061            if (nextval)
1062            {
1063                    *nextval = (char) 0x00;
1064                    return ++nextval;
1065            }
1066    
1067            /* no more args after this, jump to EOS */
1068            nextval = src + strlen(src);
1069            return nextval;
1070    }
1071    
1072    
1073    void
1074    toupper_str(char *p)
1075    {
1076            while (*p)
1077            {
1078                    if ((*p >= 'a') && (*p <= 'z'))
1079                            *p = toupper((int) *p);
1080                    p++;
1081            }
1082    }
1083    
1084    
1085    /* not all clibs got ltoa */
1086    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1087    
1088    char *
1089    l_to_a(long N, int base)
1090    {
1091            static char ret[LTOA_BUFSIZE];
1092    
1093            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1094    
1095            register int divrem;
1096    
1097            if (base < 36 || 2 > base)
1098                    base = 10;
1099    
1100            if (N < 0)
1101            {
1102                    *head++ = '-';
1103                    N = -N;
1104            }
1105    
1106            tail = buf + sizeof(buf);
1107            *--tail = 0;
1108    
1109            do
1110            {
1111                    divrem = N % base;
1112                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1113                    N /= base;
1114            }
1115            while (N);
1116    
1117            strcpy(head, tail);
1118            return ret;
1119    }
1120    
1121    
1122  int  int
1123  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1124  {  {
1125          char path[PATH_MAX];          char *home, *path;
         char *home;  
1126          struct stat st;          struct stat st;
1127          int fd;          int fd, length;
1128    
1129          home = getenv("HOME");          home = getenv("HOME");
1130          if (home == NULL)          if (home == NULL)
1131                  return -1;                  return -1;
1132    
1133          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1134          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1135    
1136          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1137          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 1140  load_licence(unsigned char **data)
1140          if (fstat(fd, &st))          if (fstat(fd, &st))
1141                  return -1;                  return -1;
1142    
1143          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1144          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1145            close(fd);
1146            xfree(path);
1147            return length;
1148  }  }
1149    
1150  void  void
1151  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1152  {  {
1153          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1154          int fd;          int fd;
1155    
1156          home = getenv("HOME");          home = getenv("HOME");
1157          if (home == NULL)          if (home == NULL)
1158                  return;                  return;
1159    
1160          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1161          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
1162          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
1163            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1164            {
1165                    perror(path);
1166                    return;
1167            }
1168    
1169            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1170    
1171          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1172            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1173            strcpy(tmppath, path);
1174            strcat(tmppath, ".new");
1175    
1176          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1177          if (fd == -1)          if (fd == -1)
1178          {          {
1179                  perror("open");                  perror(tmppath);
1180                  return;                  return;
1181          }          }
1182    
1183          write(fd, data, length);          if (write(fd, data, length) != length)
1184            {
1185                    perror(tmppath);
1186                    unlink(tmppath);
1187            }
1188            else if (rename(tmppath, path) == -1)
1189            {
1190                    perror(path);
1191                    unlink(tmppath);
1192            }
1193    
1194            close(fd);
1195            xfree(tmppath);
1196            xfree(path);
1197    }
1198    
1199    /* Create the bitmap cache directory */
1200    BOOL
1201    rd_pstcache_mkdir(void)
1202    {
1203            char *home;
1204            char bmpcache_dir[256];
1205    
1206            home = getenv("HOME");
1207    
1208            if (home == NULL)
1209                    return False;
1210    
1211            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1212    
1213            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1214            {
1215                    perror(bmpcache_dir);
1216                    return False;
1217            }
1218    
1219            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1220    
1221            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1222            {
1223                    perror(bmpcache_dir);
1224                    return False;
1225            }
1226    
1227            return True;
1228    }
1229    
1230    /* open a file in the .rdesktop directory */
1231    int
1232    rd_open_file(char *filename)
1233    {
1234            char *home;
1235            char fn[256];
1236            int fd;
1237    
1238            home = getenv("HOME");
1239            if (home == NULL)
1240                    return -1;
1241            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1242            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1243            if (fd == -1)
1244                    perror(fn);
1245            return fd;
1246    }
1247    
1248    /* close file */
1249    void
1250    rd_close_file(int fd)
1251    {
1252          close(fd);          close(fd);
1253  }  }
1254    
1255    /* read from file*/
1256    int
1257    rd_read_file(int fd, void *ptr, int len)
1258    {
1259            return read(fd, ptr, len);
1260    }
1261    
1262    /* write to file */
1263    int
1264    rd_write_file(int fd, void *ptr, int len)
1265    {
1266            return write(fd, ptr, len);
1267    }
1268    
1269    /* move file pointer */
1270    int
1271    rd_lseek_file(int fd, int offset)
1272    {
1273            return lseek(fd, offset, SEEK_SET);
1274    }
1275    
1276    /* do a write lock on a file */
1277    BOOL
1278    rd_lock_file(int fd, int start, int len)
1279    {
1280            struct flock lock;
1281    
1282            lock.l_type = F_WRLCK;
1283            lock.l_whence = SEEK_SET;
1284            lock.l_start = start;
1285            lock.l_len = len;
1286            if (fcntl(fd, F_SETLK, &lock) == -1)
1287                    return False;
1288            return True;
1289    }

Legend:
Removed from v.79  
changed lines
  Added in v.958

  ViewVC Help
Powered by ViewVC 1.1.26