/[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 103 by matthewc, Thu Aug 29 14:18:24 2002 UTC revision 1306 by astrand, Fri Oct 27 12:59:38 2006 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
# Line 18  Line 18 
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 title[32];  #ifdef HAVE_LOCALE_H
34  char username[16];  #include <locale.h>
35  char hostname[16];  #endif
36  char keymapname[16];  #ifdef HAVE_ICONV
37  int keylayout = 0x409;          /* Defaults to US keyboard layout */  #ifdef HAVE_LANGINFO_H
38  int width;  #include <langinfo.h>
39  int height;  #endif
40  int tcp_port_rdp = TCP_PORT_RDP;  #endif
41  BOOL bitmap_compression = True;  
42  BOOL sendmotion = True;  #ifdef EGD_SOCKET
43  BOOL orders = True;  #include <sys/types.h>
44  BOOL licence = True;  #include <sys/socket.h>         /* socket connect */
45  BOOL encryption = True;  #include <sys/un.h>             /* sockaddr_un */
46  BOOL desktop_save = True;  #endif
47  BOOL fullscreen = False;  
48  BOOL grab_keyboard = True;  #include <openssl/md5.h>
49    
50    char g_title[64] = "";
51    char g_username[64];
52    char g_hostname[16];
53    char g_keymapname[PATH_MAX] = "";
54    unsigned int g_keylayout = 0x409;       /* Defaults to US keyboard layout */
55    int g_keyboard_type = 0x4;      /* Defaults to US keyboard layout */
56    int g_keyboard_subtype = 0x0;   /* Defaults to US keyboard layout */
57    int g_keyboard_functionkeys = 0xc;      /* Defaults to US keyboard layout */
58    
59    int g_width = 800;              /* width is special: If 0, the
60                                       geometry will be fetched from
61                                       _NET_WORKAREA. If negative,
62                                       absolute value specifies the
63                                       percent of the whole screen. */
64    int g_height = 600;
65    int g_xpos = 0;
66    int g_ypos = 0;
67    int g_pos = 0;                  /* 0 position unspecified,
68                                       1 specified,
69                                       2 xpos neg,
70                                       4 ypos neg  */
71    extern int g_tcp_port_rdp;
72    int g_server_depth = -1;
73    int g_win_button_size = 0;      /* If zero, disable single app mode */
74    BOOL g_bitmap_compression = True;
75    BOOL g_sendmotion = True;
76    BOOL g_bitmap_cache = True;
77    BOOL g_bitmap_cache_persist_enable = False;
78    BOOL g_bitmap_cache_precache = True;
79    BOOL g_encryption = True;
80    BOOL packet_encryption = True;
81    BOOL g_desktop_save = True;     /* desktop save order */
82    BOOL g_polygon_ellipse_orders = True;   /* polygon / ellipse orders */
83    BOOL g_fullscreen = False;
84    BOOL g_grab_keyboard = True;
85    BOOL g_hide_decorations = False;
86    BOOL g_use_rdp5 = True;
87    BOOL g_rdpclip = True;
88    BOOL g_console_session = False;
89    BOOL g_numlock_sync = False;
90    BOOL lspci_enabled = False;
91    BOOL g_owncolmap = False;
92    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
93    BOOL g_seamless_rdp = False;
94    uint32 g_embed_wnd;
95    uint32 g_rdp5_performanceflags =
96            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
97    /* Session Directory redirection */
98    BOOL g_redirect = False;
99    char g_redirect_server[64];
100    char g_redirect_domain[16];
101    char g_redirect_password[64];
102    char g_redirect_username[64];
103    char g_redirect_cookie[128];
104    uint32 g_redirect_flags = 0;
105    
106    #ifdef WITH_RDPSND
107    BOOL g_rdpsnd = False;
108    #endif
109    
110    #ifdef HAVE_ICONV
111    char g_codepage[16] = "";
112    #endif
113    
114    extern RDPDR_DEVICE g_rdpdr_device[];
115    extern uint32 g_num_devices;
116    extern char *g_rdpdr_clientname;
117    
118    #ifdef RDP2VNC
119    extern int rfb_port;
120    extern int defer_time;
121    void
122    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
123                    char *shell, char *directory);
124    #endif
125  /* Display usage information */  /* Display usage information */
126  static void  static void
127  usage(char *program)  usage(char *program)
128  {  {
129          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
130          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
131          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
132          printf("   -s: shell\n");  
133          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
134          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
135          printf("   -P: askpass-program (autologon)\n");          fprintf(stderr, "   -V: vnc port\n");
136          printf("   -n: client hostname\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
137          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");  #endif
138          printf("   -g: desktop geometry (WxH)\n");          fprintf(stderr, "   -u: user name\n");
139          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -d: domain\n");
140          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -s: shell\n");
141          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -c: working directory\n");
142          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
143          printf("   -l: do not request licence\n");          fprintf(stderr, "   -n: client hostname\n");
144          printf("   -t: rdp tcp port\n");          fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
145          printf("   -K: keep window manager key bindings\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
146            fprintf(stderr, "   -f: full-screen mode\n");
147            fprintf(stderr, "   -b: force bitmap updates\n");
148    #ifdef HAVE_ICONV
149            fprintf(stderr, "   -L: local codepage\n");
150    #endif
151            fprintf(stderr, "   -A: enable SeamlessRDP mode\n");
152            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
153            fprintf(stderr, "   -e: disable encryption (French TS)\n");
154            fprintf(stderr, "   -E: disable encryption from client to server\n");
155            fprintf(stderr, "   -m: do not send motion events\n");
156            fprintf(stderr, "   -C: use private colour map\n");
157            fprintf(stderr, "   -D: hide window manager decorations\n");
158            fprintf(stderr, "   -K: keep window manager key bindings\n");
159            fprintf(stderr, "   -S: caption button size (single application mode)\n");
160            fprintf(stderr, "   -T: window title\n");
161            fprintf(stderr, "   -N: enable numlock syncronization\n");
162            fprintf(stderr, "   -X: embed into another window with a given id.\n");
163            fprintf(stderr, "   -a: connection colour depth\n");
164            fprintf(stderr, "   -z: enable rdp compression\n");
165            fprintf(stderr, "   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
166            fprintf(stderr, "   -P: use persistent bitmap caching\n");
167            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
168            fprintf(stderr,
169                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
170            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
171            fprintf(stderr,
172                    "         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
173            fprintf(stderr, "             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
174            fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
175            fprintf(stderr, "             for redirected disks\n");
176            fprintf(stderr,
177                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
178            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
179            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
180            fprintf(stderr,
181                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
182    #ifdef WITH_RDPSND
183            fprintf(stderr,
184                    "         '-r sound:[local[:driver[:device]]|off|remote]': enable sound redirection\n");
185            fprintf(stderr, "                     remote would leave sound on server\n");
186            fprintf(stderr, "                     available drivers for 'local':\n");
187            rdpsnd_show_help();
188    #endif
189            fprintf(stderr,
190                    "         '-r clipboard:[off|PRIMARYCLIPBOARD|CLIPBOARD]': enable clipboard\n");
191            fprintf(stderr, "                      redirection.\n");
192            fprintf(stderr,
193                    "                      'PRIMARYCLIPBOARD' looks at both PRIMARY and CLIPBOARD\n");
194            fprintf(stderr, "                      when sending data to server.\n");
195            fprintf(stderr, "                      'CLIPBOARD' looks at only CLIPBOARD.\n");
196            fprintf(stderr, "   -0: attach to console\n");
197            fprintf(stderr, "   -4: use RDP version 4\n");
198            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
199    }
200    
201    static void
202    print_disconnect_reason(uint16 reason)
203    {
204            char *text;
205    
206            switch (reason)
207            {
208                    case exDiscReasonNoInfo:
209                            text = "No information available";
210                            break;
211    
212                    case exDiscReasonAPIInitiatedDisconnect:
213                            text = "Server initiated disconnect";
214                            break;
215    
216                    case exDiscReasonAPIInitiatedLogoff:
217                            text = "Server initiated logoff";
218                            break;
219    
220                    case exDiscReasonServerIdleTimeout:
221                            text = "Server idle timeout reached";
222                            break;
223    
224                    case exDiscReasonServerLogonTimeout:
225                            text = "Server logon timeout reached";
226                            break;
227    
228                    case exDiscReasonReplacedByOtherConnection:
229                            text = "The session was replaced";
230                            break;
231    
232                    case exDiscReasonOutOfMemory:
233                            text = "The server is out of memory";
234                            break;
235    
236                    case exDiscReasonServerDeniedConnection:
237                            text = "The server denied the connection";
238                            break;
239    
240                    case exDiscReasonServerDeniedConnectionFips:
241                            text = "The server denied the connection for security reason";
242                            break;
243    
244                    case exDiscReasonLicenseInternal:
245                            text = "Internal licensing error";
246                            break;
247    
248                    case exDiscReasonLicenseNoLicenseServer:
249                            text = "No license server available";
250                            break;
251    
252                    case exDiscReasonLicenseNoLicense:
253                            text = "No valid license available";
254                            break;
255    
256                    case exDiscReasonLicenseErrClientMsg:
257                            text = "Invalid licensing message";
258                            break;
259    
260                    case exDiscReasonLicenseHwidDoesntMatchLicense:
261                            text = "Hardware id doesn't match software license";
262                            break;
263    
264                    case exDiscReasonLicenseErrClientLicense:
265                            text = "Client license error";
266                            break;
267    
268                    case exDiscReasonLicenseCantFinishProtocol:
269                            text = "Network error during licensing protocol";
270                            break;
271    
272                    case exDiscReasonLicenseClientEndedProtocol:
273                            text = "Licensing protocol was not completed";
274                            break;
275    
276                    case exDiscReasonLicenseErrClientEncryption:
277                            text = "Incorrect client license enryption";
278                            break;
279    
280                    case exDiscReasonLicenseCantUpgradeLicense:
281                            text = "Can't upgrade license";
282                            break;
283    
284                    case exDiscReasonLicenseNoRemoteConnections:
285                            text = "The server is not licensed to accept remote connections";
286                            break;
287    
288                    default:
289                            if (reason > 0x1000 && reason < 0x7fff)
290                            {
291                                    text = "Internal protocol error";
292                            }
293                            else
294                            {
295                                    text = "Unknown reason";
296                            }
297            }
298            fprintf(stderr, "disconnect: %s.\n", text);
299    }
300    
301    static void
302    rdesktop_reset_state(void)
303    {
304            rdp_reset_state();
305    }
306    
307    static BOOL
308    read_password(char *password, int size)
309    {
310            struct termios tios;
311            BOOL ret = False;
312            int istty = 0;
313            char *p;
314    
315            if (tcgetattr(STDIN_FILENO, &tios) == 0)
316            {
317                    fprintf(stderr, "Password: ");
318                    tios.c_lflag &= ~ECHO;
319                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
320                    istty = 1;
321            }
322    
323            if (fgets(password, size, stdin) != NULL)
324            {
325                    ret = True;
326    
327                    /* strip final newline */
328                    p = strchr(password, '\n');
329                    if (p != NULL)
330                            *p = 0;
331            }
332    
333            if (istty)
334            {
335                    tios.c_lflag |= ECHO;
336                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
337                    fprintf(stderr, "\n");
338            }
339    
340            return ret;
341    }
342    
343    static void
344    parse_server_and_port(char *server)
345    {
346            char *p;
347    #ifdef IPv6
348            int addr_colons;
349    #endif
350    
351    #ifdef IPv6
352            p = server;
353            addr_colons = 0;
354            while (*p)
355                    if (*p++ == ':')
356                            addr_colons++;
357            if (addr_colons >= 2)
358            {
359                    /* numeric IPv6 style address format - [1:2:3::4]:port */
360                    p = strchr(server, ']');
361                    if (*server == '[' && p != NULL)
362                    {
363                            if (*(p + 1) == ':' && *(p + 2) != '\0')
364                                    g_tcp_port_rdp = strtol(p + 2, NULL, 10);
365                            /* remove the port number and brackets from the address */
366                            *p = '\0';
367                            strncpy(server, server + 1, strlen(server));
368                    }
369            }
370            else
371            {
372                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
373                    p = strchr(server, ':');
374                    if (p != NULL)
375                    {
376                            g_tcp_port_rdp = strtol(p + 1, NULL, 10);
377                            *p = 0;
378                    }
379            }
380    #else /* no IPv6 support */
381            p = strchr(server, ':');
382            if (p != NULL)
383            {
384                    g_tcp_port_rdp = strtol(p + 1, NULL, 10);
385                    *p = 0;
386            }
387    #endif /* IPv6 */
388    
389  }  }
390    
391  /* Client program */  /* Client program */
392  int  int
393  main(int argc, char *argv[])  main(int argc, char *argv[])
394  {  {
395            char server[64];
396          char fullhostname[64];          char fullhostname[64];
397          char domain[16];          char domain[16];
398          char password[16];          char password[64];
399          char *askpass_result;          char shell[256];
400          char shell[32];          char directory[256];
401          char directory[32];          BOOL prompt_password, deactivated;
402          struct passwd *pw;          struct passwd *pw;
403          char *server, *p;          uint32 flags, ext_disc_reason = 0;
404          uint32 flags;          char *p;
405          int c;          int c;
406            char *locale = NULL;
407            int username_option = 0;
408            BOOL geometry_option = False;
409            int run_count = 0;      /* Session Directory support */
410            BOOL continue_connect = True;   /* Session Directory support */
411            char *rdpsnd_optarg = NULL;
412    
413    #ifdef HAVE_LOCALE_H
414            /* Set locale according to environment */
415            locale = setlocale(LC_ALL, "");
416            if (locale)
417            {
418                    locale = xstrdup(locale);
419            }
420    
421          printf("rdesktop: A Remote Desktop Protocol client.\n");  #endif
         printf("Version " VERSION ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("See http://www.rdesktop.org/ for more information.\n\n");  
   
422          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
423            prompt_password = False;
424          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
425          strcpy(keymapname, "us");          g_embed_wnd = 0;
426    
427            g_num_devices = 0;
428    
429          while ((c = getopt(argc, argv, "u:d:s:c:p:P:n:k:g:t:fbemlKh?")) != -1)  #ifdef RDP2VNC
430    #define VNCOPT "V:Q:"
431    #else
432    #define VNCOPT
433    #endif
434    
435            while ((c = getopt(argc, argv,
436                               VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
437          {          {
438                  switch (c)                  switch (c)
439                  {                  {
440    #ifdef RDP2VNC
441                            case 'V':
442                                    rfb_port = strtol(optarg, NULL, 10);
443                                    if (rfb_port < 100)
444                                            rfb_port += 5900;
445                                    break;
446    
447                            case 'Q':
448                                    defer_time = strtol(optarg, NULL, 10);
449                                    if (defer_time < 0)
450                                            defer_time = 0;
451                                    break;
452    #endif
453    
454                            case 'A':
455                                    g_seamless_rdp = True;
456                                    break;
457    
458                          case 'u':                          case 'u':
459                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
460                                    username_option = 1;
461                                    break;
462    
463                            case 'L':
464    #ifdef HAVE_ICONV
465                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
466    #else
467                                    error("iconv support not available\n");
468    #endif
469                                  break;                                  break;
470    
471                          case 'd':                          case 'd':
# Line 113  main(int argc, char *argv[]) Line 481  main(int argc, char *argv[])
481                                  break;                                  break;
482    
483                          case 'p':                          case 'p':
484                                    if ((optarg[0] == '-') && (optarg[1] == 0))
485                                    {
486                                            prompt_password = True;
487                                            break;
488                                    }
489    
490                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
491                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
                                 break;  
492    
493                          case 'P':                                  /* try to overwrite argument so it won't appear in ps */
494                                  askpass_result = askpass(optarg, "Enter password");                                  p = optarg;
495                                  if (askpass_result == NULL)                                  while (*p)
496                                          exit(1);                                          *(p++) = 'X';
   
                                 STRNCPY(password, askpass_result, sizeof(password));  
                                 free(askpass_result);  
                                 flags |= RDP_LOGON_AUTO;  
497                                  break;                                  break;
498    
499                          case 'n':                          case 'n':
500                                  STRNCPY(hostname, optarg, sizeof(hostname));                                  STRNCPY(g_hostname, optarg, sizeof(g_hostname));
501                                  break;                                  break;
502    
503                          case 'k':                          case 'k':
504                                  STRNCPY(keymapname, optarg, sizeof(keymapname));                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
505                                  break;                                  break;
506    
507                          case 'g':                          case 'g':
508                                  width = strtol(optarg, &p, 10);                                  geometry_option = True;
509                                    g_fullscreen = False;
510                                    if (!strcmp(optarg, "workarea"))
511                                    {
512                                            g_width = g_height = 0;
513                                            break;
514                                    }
515    
516                                    g_width = strtol(optarg, &p, 10);
517                                    if (g_width <= 0)
518                                    {
519                                            error("invalid geometry\n");
520                                            return 1;
521                                    }
522    
523                                  if (*p == 'x')                                  if (*p == 'x')
524                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, &p, 10);
525    
526                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
527                                  {                                  {
528                                          error("invalid geometry\n");                                          error("invalid geometry\n");
529                                          return 1;                                          return 1;
530                                  }                                  }
531    
532                                    if (*p == '%')
533                                    {
534                                            g_width = -g_width;
535                                            p++;
536                                    }
537    
538                                    if (*p == '+' || *p == '-')
539                                    {
540                                            g_pos |= (*p == '-') ? 2 : 1;
541                                            g_xpos = strtol(p, &p, 10);
542    
543                                    }
544                                    if (*p == '+' || *p == '-')
545                                    {
546                                            g_pos |= (*p == '-') ? 4 : 1;
547                                            g_ypos = strtol(p, NULL, 10);
548                                    }
549    
550                                  break;                                  break;
551    
552                          case 'f':                          case 'f':
553                                  fullscreen = True;                                  g_fullscreen = True;
554                                  break;                                  break;
555    
556                          case 'b':                          case 'b':
557                                  orders = False;                                  g_bitmap_cache = False;
558                                  break;                                  break;
559    
560                          case 'e':                          case 'B':
561                                  encryption = False;                                  g_ownbackstore = False;
562                                  break;                                  break;
563    
564                            case 'e':
565                                    g_encryption = False;
566                                    break;
567                            case 'E':
568                                    packet_encryption = False;
569                                    break;
570                          case 'm':                          case 'm':
571                                  sendmotion = False;                                  g_sendmotion = False;
572                                  break;                                  break;
573    
574                          case 'l':                          case 'C':
575                                  licence = False;                                  g_owncolmap = True;
576                                  break;                                  break;
577    
578                          case 't':                          case 'D':
579                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_hide_decorations = True;
580                                  break;                                  break;
581    
582                          case 'K':                          case 'K':
583                                  grab_keyboard = False;                                  g_grab_keyboard = False;
584                                    break;
585    
586                            case 'S':
587                                    if (!strcmp(optarg, "standard"))
588                                    {
589                                            g_win_button_size = 18;
590                                            break;
591                                    }
592    
593                                    g_win_button_size = strtol(optarg, &p, 10);
594    
595                                    if (*p)
596                                    {
597                                            error("invalid button size\n");
598                                            return 1;
599                                    }
600    
601                                    break;
602    
603                            case 'T':
604                                    STRNCPY(g_title, optarg, sizeof(g_title));
605                                    break;
606    
607                            case 'N':
608                                    g_numlock_sync = True;
609                                    break;
610    
611                            case 'X':
612                                    g_embed_wnd = strtol(optarg, NULL, 0);
613                                    break;
614    
615                            case 'a':
616                                    g_server_depth = strtol(optarg, NULL, 10);
617                                    if (g_server_depth != 8 &&
618                                        g_server_depth != 16 &&
619                                        g_server_depth != 15 && g_server_depth != 24)
620                                    {
621                                            error("Invalid server colour depth.\n");
622                                            return 1;
623                                    }
624                                    break;
625    
626                            case 'z':
627                                    DEBUG(("rdp compression enabled\n"));
628                                    flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
629                                    break;
630    
631                            case 'x':
632                                    if (str_startswith(optarg, "m"))        /* modem */
633                                    {
634                                            g_rdp5_performanceflags =
635                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
636                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
637                                    }
638                                    else if (str_startswith(optarg, "b"))   /* broadband */
639                                    {
640                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
641                                    }
642                                    else if (str_startswith(optarg, "l"))   /* lan */
643                                    {
644                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
645                                    }
646                                    else
647                                    {
648                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
649                                    }
650                                    break;
651    
652                            case 'P':
653                                    g_bitmap_cache_persist_enable = True;
654                                    break;
655    
656                            case 'r':
657    
658                                    if (str_startswith(optarg, "sound"))
659                                    {
660                                            optarg += 5;
661    
662                                            if (*optarg == ':')
663                                            {
664                                                    optarg++;
665                                                    while ((p = next_arg(optarg, ',')))
666                                                    {
667                                                            if (str_startswith(optarg, "remote"))
668                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
669    
670                                                            if (str_startswith(optarg, "local"))
671    #ifdef WITH_RDPSND
672                                                            {
673                                                                    rdpsnd_optarg =
674                                                                            next_arg(optarg, ':');
675                                                                    g_rdpsnd = True;
676                                                            }
677    
678    #else
679                                                                    warning("Not compiled with sound support\n");
680    #endif
681    
682                                                            if (str_startswith(optarg, "off"))
683    #ifdef WITH_RDPSND
684                                                                    g_rdpsnd = False;
685    #else
686                                                                    warning("Not compiled with sound support\n");
687    #endif
688    
689                                                            optarg = p;
690                                                    }
691                                            }
692                                            else
693                                            {
694    #ifdef WITH_RDPSND
695                                                    g_rdpsnd = True;
696    #else
697                                                    warning("Not compiled with sound support\n");
698    #endif
699                                            }
700                                    }
701                                    else if (str_startswith(optarg, "disk"))
702                                    {
703                                            /* -r disk:h:=/mnt/floppy */
704                                            disk_enum_devices(&g_num_devices, optarg + 4);
705                                    }
706                                    else if (str_startswith(optarg, "comport"))
707                                    {
708                                            serial_enum_devices(&g_num_devices, optarg + 7);
709                                    }
710                                    else if (str_startswith(optarg, "lspci"))
711                                    {
712                                            lspci_enabled = True;
713                                    }
714                                    else if (str_startswith(optarg, "lptport"))
715                                    {
716                                            parallel_enum_devices(&g_num_devices, optarg + 7);
717                                    }
718                                    else if (str_startswith(optarg, "printer"))
719                                    {
720                                            printer_enum_devices(&g_num_devices, optarg + 7);
721                                    }
722                                    else if (str_startswith(optarg, "clientname"))
723                                    {
724                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
725                                            strcpy(g_rdpdr_clientname, optarg + 11);
726                                    }
727                                    else if (str_startswith(optarg, "clipboard"))
728                                    {
729                                            optarg += 9;
730    
731                                            if (*optarg == ':')
732                                            {
733                                                    optarg++;
734    
735                                                    if (str_startswith(optarg, "off"))
736                                                            g_rdpclip = False;
737                                                    else
738                                                            cliprdr_set_mode(optarg);
739                                            }
740                                            else
741                                                    g_rdpclip = True;
742                                    }
743                                    else
744                                    {
745                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard\n");
746                                    }
747                                    break;
748    
749                            case '0':
750                                    g_console_session = True;
751                                    break;
752    
753                            case '4':
754                                    g_use_rdp5 = False;
755                                    break;
756    
757                            case '5':
758                                    g_use_rdp5 = True;
759                                  break;                                  break;
760    
761                          case 'h':                          case 'h':
# Line 183  main(int argc, char *argv[]) Line 766  main(int argc, char *argv[])
766                  }                  }
767          }          }
768    
769          if (argc - optind < 1)          if (argc - optind != 1)
770          {          {
771                  usage(argv[0]);                  usage(argv[0]);
772                  return 1;                  return 1;
773          }          }
774    
775          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
776            parse_server_and_port(server);
777    
778            if (g_seamless_rdp)
779            {
780                    if (g_win_button_size)
781                    {
782                            error("You cannot use -S and -A at the same time\n");
783                            return 1;
784                    }
785                    g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
786                    if (geometry_option)
787                    {
788                            error("You cannot use -g and -A at the same time\n");
789                            return 1;
790                    }
791                    if (g_fullscreen)
792                    {
793                            error("You cannot use -f and -A at the same time\n");
794                            return 1;
795                    }
796                    if (g_hide_decorations)
797                    {
798                            error("You cannot use -D and -A at the same time\n");
799                            return 1;
800                    }
801                    if (g_embed_wnd)
802                    {
803                            error("You cannot use -X and -A at the same time\n");
804                            return 1;
805                    }
806                    if (!g_use_rdp5)
807                    {
808                            error("You cannot use -4 and -A at the same time\n");
809                            return 1;
810                    }
811                    g_width = -100;
812                    g_grab_keyboard = False;
813            }
814    
815          if (username[0] == 0)          if (!username_option)
816          {          {
817                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
818                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 200  main(int argc, char *argv[]) Line 821  main(int argc, char *argv[])
821                          return 1;                          return 1;
822                  }                  }
823    
824                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
825            }
826    
827    #ifdef HAVE_ICONV
828            if (g_codepage[0] == 0)
829            {
830                    if (setlocale(LC_CTYPE, ""))
831                    {
832                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
833                    }
834                    else
835                    {
836                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
837                    }
838          }          }
839    #endif
840    
841          if (hostname[0] == 0)          if (g_hostname[0] == 0)
842          {          {
843                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
844                  {                  {
# Line 215  main(int argc, char *argv[]) Line 850  main(int argc, char *argv[])
850                  if (p != NULL)                  if (p != NULL)
851                          *p = 0;                          *p = 0;
852    
853                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
854          }          }
855    
856          if (!strcmp(password, "-"))          if (g_keymapname[0] == 0)
857          {          {
858                  p = getpass("Password: ");                  if (locale && xkeymap_from_locale(locale))
                 if (p == NULL)  
859                  {                  {
860                          error("failed to read password\n");                          fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
861                          return 0;                  }
862                    else
863                    {
864                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
865                  }                  }
                 STRNCPY(password, p, sizeof(password));  
866          }          }
867            if (locale)
868                    xfree(locale);
869    
870          if ((width == 0) || (height == 0))  
871          {          if (prompt_password && read_password(password, sizeof(password)))
872                  width = 800;                  flags |= RDP_LOGON_AUTO;
873                  height = 600;  
874          }          if (g_title[0] == 0)
         else  
875          {          {
876                  /* make sure width is a multiple of 4 */                  strcpy(g_title, "rdesktop - ");
877                  width = (width + 3) & ~3;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
878          }          }
879    
880          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
881          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
882            return 0;
883    #else
884    
         xkeymap_init1();  
885          if (!ui_init())          if (!ui_init())
886                  return 1;                  return 1;
887    
888          if (!rdp_connect(server, flags, domain, password, shell, directory))  #ifdef WITH_RDPSND
889                  return 1;          if (g_rdpsnd)
890            {
891                    if (!rdpsnd_init(rdpsnd_optarg))
892                    {
893                            warning("Initializing sound-support failed!\n");
894                    }
895            }
896    #endif
897    
898            if (lspci_enabled)
899                    lspci_init();
900    
901            rdpdr_init();
902    
903            while (run_count < 2 && continue_connect)       /* add support for Session Directory; only reconnect once */
904            {
905                    if (run_count == 0)
906                    {
907                            if (!rdp_connect(server, flags, domain, password, shell, directory))
908                                    return 1;
909                    }
910                    else if (!rdp_reconnect
911                             (server, flags, domain, password, shell, directory, g_redirect_cookie))
912                            return 1;
913    
914                    /* By setting encryption to False here, we have an encrypted login
915                       packet but unencrypted transfer of other packets */
916                    if (!packet_encryption)
917                            g_encryption = False;
918    
919    
920                    DEBUG(("Connection successful.\n"));
921                    memset(password, 0, sizeof(password));
922    
923          printf("Connection successful.\n");                  if (run_count == 0)
924                            if (!ui_create_window())
925                                    continue_connect = False;
926    
927          if (ui_create_window())                  if (continue_connect)
928                            rdp_main_loop(&deactivated, &ext_disc_reason);
929    
930                    DEBUG(("Disconnecting...\n"));
931                    rdp_disconnect();
932    
933                    if ((g_redirect == True) && (run_count == 0))   /* Support for Session Directory */
934                    {
935                            /* reset state of major globals */
936                            rdesktop_reset_state();
937    
938                            STRNCPY(domain, g_redirect_domain, sizeof(domain));
939                            STRNCPY(g_username, g_redirect_username, sizeof(g_username));
940                            STRNCPY(password, g_redirect_password, sizeof(password));
941                            STRNCPY(server, g_redirect_server, sizeof(server));
942                            flags |= RDP_LOGON_AUTO;
943    
944                            g_redirect = False;
945                    }
946                    else
947                    {
948                            continue_connect = False;
949                            ui_destroy_window();
950                            break;
951                    }
952    
953                    run_count++;
954            }
955    
956            cache_save_state();
957            ui_deinit();
958    
959            if (ext_disc_reason >= 2)
960                    print_disconnect_reason(ext_disc_reason);
961    
962            if (deactivated)
963          {          {
964                  rdp_main_loop();                  /* clean disconnect */
965                  ui_destroy_window();                  return 0;
966            }
967            else
968            {
969                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
970                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
971                    {
972                            /* not so clean disconnect, but nothing to worry about */
973                            return 0;
974                    }
975                    else
976                    {
977                            /* return error */
978                            return 2;
979                    }
980          }          }
981    
982          printf("Disconnecting...\n");  #endif
983          rdp_disconnect();  
984          return 0;  }
985    
986    #ifdef EGD_SOCKET
987    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
988    static BOOL
989    generate_random_egd(uint8 * buf)
990    {
991            struct sockaddr_un addr;
992            BOOL ret = False;
993            int fd;
994    
995            fd = socket(AF_UNIX, SOCK_STREAM, 0);
996            if (fd == -1)
997                    return False;
998    
999            addr.sun_family = AF_UNIX;
1000            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
1001            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
1002                    goto err;
1003    
1004            /* PRNGD and EGD use a simple communications protocol */
1005            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
1006            buf[1] = 32;            /* Number of requested random bytes */
1007            if (write(fd, buf, 2) != 2)
1008                    goto err;
1009    
1010            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
1011                    goto err;
1012    
1013            if (read(fd, buf, 32) != 32)
1014                    goto err;
1015    
1016            ret = True;
1017    
1018          err:
1019            close(fd);
1020            return ret;
1021  }  }
1022    #endif
1023    
1024  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
1025  void  void
# Line 269  generate_random(uint8 * random) Line 1027  generate_random(uint8 * random)
1027  {  {
1028          struct stat st;          struct stat st;
1029          struct tms tmsbuf;          struct tms tmsbuf;
1030          uint32 *r = (uint32 *) random;          MD5_CTX md5;
1031          int fd;          uint32 *r;
1032            int fd, n;
1033    
1034          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
1035          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
1036              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
1037          {          {
1038                  read(fd, random, 32);                  n = read(fd, random, 32);
1039                  close(fd);                  close(fd);
1040                  return;                  if (n == 32)
1041                            return;
1042          }          }
1043    
1044    #ifdef EGD_SOCKET
1045            /* As a second preference use an EGD */
1046            if (generate_random_egd(random))
1047                    return;
1048    #endif
1049    
1050          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
1051            r = (uint32 *) random;
1052          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
1053          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
1054          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 290  generate_random(uint8 * random) Line 1057  generate_random(uint8 * random)
1057          r[5] = st.st_atime;          r[5] = st.st_atime;
1058          r[6] = st.st_mtime;          r[6] = st.st_mtime;
1059          r[7] = st.st_ctime;          r[7] = st.st_ctime;
1060    
1061            /* Hash both halves with MD5 to obscure possible patterns */
1062            MD5_Init(&md5);
1063            MD5_Update(&md5, random, 16);
1064            MD5_Final(random, &md5);
1065            MD5_Update(&md5, random + 16, 16);
1066            MD5_Final(random + 16, &md5);
1067  }  }
1068    
1069  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 305  xmalloc(int size) Line 1079  xmalloc(int size)
1079          return mem;          return mem;
1080  }  }
1081    
1082    /* Exit on NULL pointer. Use to verify result from XGetImage etc */
1083    void
1084    exit_if_null(void *ptr)
1085    {
1086            if (ptr == NULL)
1087            {
1088                    error("unexpected null pointer. Out of memory?\n");
1089                    exit(1);
1090            }
1091    }
1092    
1093    /* strdup */
1094    char *
1095    xstrdup(const char *s)
1096    {
1097            char *mem = strdup(s);
1098            if (mem == NULL)
1099            {
1100                    perror("strdup");
1101                    exit(1);
1102            }
1103            return mem;
1104    }
1105    
1106  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1107  void *  void *
1108  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
1109  {  {
1110          void *mem = realloc(oldmem, size);          void *mem;
1111    
1112            if (size < 1)
1113                    size = 1;
1114            mem = realloc(oldmem, size);
1115          if (mem == NULL)          if (mem == NULL)
1116          {          {
1117                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 338  error(char *format, ...) Line 1140  error(char *format, ...)
1140          va_end(ap);          va_end(ap);
1141  }  }
1142    
1143    /* report a warning */
1144    void
1145    warning(char *format, ...)
1146    {
1147            va_list ap;
1148    
1149            fprintf(stderr, "WARNING: ");
1150    
1151            va_start(ap, format);
1152            vfprintf(stderr, format, ap);
1153            va_end(ap);
1154    }
1155    
1156  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
1157  void  void
1158  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 356  void Line 1171  void
1171  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
1172  {  {
1173          unsigned char *line = p;          unsigned char *line = p;
1174          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
1175    
1176          while (offset < len)          while (offset < len)
1177          {          {
# Line 381  hexdump(unsigned char *p, unsigned int l Line 1195  hexdump(unsigned char *p, unsigned int l
1195          }          }
1196  }  }
1197    
1198    /*
1199      input: src is the string we look in for needle.
1200             Needle may be escaped by a backslash, in
1201             that case we ignore that particular needle.
1202      return value: returns next src pointer, for
1203            succesive executions, like in a while loop
1204            if retval is 0, then there are no more args.
1205      pitfalls:
1206            src is modified. 0x00 chars are inserted to
1207            terminate strings.
1208            return val, points on the next val chr after ins
1209            0x00
1210    
1211            example usage:
1212            while( (pos = next_arg( optarg, ',')) ){
1213                    printf("%s\n",optarg);
1214                    optarg=pos;
1215            }
1216    
1217    */
1218    char *
1219    next_arg(char *src, char needle)
1220    {
1221            char *nextval;
1222            char *p;
1223            char *mvp = 0;
1224    
1225            /* EOS */
1226            if (*src == (char) 0x00)
1227                    return 0;
1228    
1229            p = src;
1230            /*  skip escaped needles */
1231            while ((nextval = strchr(p, needle)))
1232            {
1233                    mvp = nextval - 1;
1234                    /* found backslashed needle */
1235                    if (*mvp == '\\' && (mvp > src))
1236                    {
1237                            /* move string one to the left */
1238                            while (*(mvp + 1) != (char) 0x00)
1239                            {
1240                                    *mvp = *(mvp + 1);
1241                                    mvp++;
1242                            }
1243                            *mvp = (char) 0x00;
1244                            p = nextval;
1245                    }
1246                    else
1247                    {
1248                            p = nextval + 1;
1249                            break;
1250                    }
1251    
1252            }
1253    
1254            /* more args available */
1255            if (nextval)
1256            {
1257                    *nextval = (char) 0x00;
1258                    return ++nextval;
1259            }
1260    
1261            /* no more args after this, jump to EOS */
1262            nextval = src + strlen(src);
1263            return nextval;
1264    }
1265    
1266    
1267    void
1268    toupper_str(char *p)
1269    {
1270            while (*p)
1271            {
1272                    if ((*p >= 'a') && (*p <= 'z'))
1273                            *p = toupper((int) *p);
1274                    p++;
1275            }
1276    }
1277    
1278    
1279    BOOL
1280    str_startswith(const char *s, const char *prefix)
1281    {
1282            return (strncmp(s, prefix, strlen(prefix)) == 0);
1283    }
1284    
1285    
1286    /* Split input into lines, and call linehandler for each
1287       line. Incomplete lines are saved in the rest variable, which should
1288       initially point to NULL. When linehandler returns False, stop and
1289       return False. Otherwise, return True.  */
1290    BOOL
1291    str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1292    {
1293            char *buf, *p;
1294            char *oldrest;
1295            size_t inputlen;
1296            size_t buflen;
1297            size_t restlen = 0;
1298            BOOL ret = True;
1299    
1300            /* Copy data to buffer */
1301            inputlen = strlen(input);
1302            if (*rest)
1303                    restlen = strlen(*rest);
1304            buflen = restlen + inputlen + 1;
1305            buf = (char *) xmalloc(buflen);
1306            buf[0] = '\0';
1307            if (*rest)
1308                    STRNCPY(buf, *rest, buflen);
1309            strncat(buf, input, inputlen);
1310            p = buf;
1311    
1312            while (1)
1313            {
1314                    char *newline = strchr(p, '\n');
1315                    if (newline)
1316                    {
1317                            *newline = '\0';
1318                            if (!linehandler(p, data))
1319                            {
1320                                    p = newline + 1;
1321                                    ret = False;
1322                                    break;
1323                            }
1324                            p = newline + 1;
1325                    }
1326                    else
1327                    {
1328                            break;
1329    
1330                    }
1331            }
1332    
1333            /* Save in rest */
1334            oldrest = *rest;
1335            restlen = buf + buflen - p;
1336            *rest = (char *) xmalloc(restlen);
1337            STRNCPY((*rest), p, restlen);
1338            xfree(oldrest);
1339    
1340            xfree(buf);
1341            return ret;
1342    }
1343    
1344    /* Execute the program specified by argv. For each line in
1345       stdout/stderr output, call linehandler. Returns false on failure. */
1346    BOOL
1347    subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1348    {
1349            pid_t child;
1350            int fd[2];
1351            int n = 1;
1352            char output[256];
1353            char *rest = NULL;
1354    
1355            if (pipe(fd) < 0)
1356            {
1357                    perror("pipe");
1358                    return False;
1359            }
1360    
1361            if ((child = fork()) < 0)
1362            {
1363                    perror("fork");
1364                    return False;
1365            }
1366    
1367            /* Child */
1368            if (child == 0)
1369            {
1370                    /* Close read end */
1371                    close(fd[0]);
1372    
1373                    /* Redirect stdout and stderr to pipe */
1374                    dup2(fd[1], 1);
1375                    dup2(fd[1], 2);
1376    
1377                    /* Execute */
1378                    execvp(argv[0], argv);
1379                    perror("Error executing child");
1380                    _exit(128);
1381            }
1382    
1383            /* Parent. Close write end. */
1384            close(fd[1]);
1385            while (n > 0)
1386            {
1387                    n = read(fd[0], output, 255);
1388                    output[n] = '\0';
1389                    str_handle_lines(output, &rest, linehandler, data);
1390            }
1391            xfree(rest);
1392    
1393            return True;
1394    }
1395    
1396    
1397    /* not all clibs got ltoa */
1398    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1399    
1400    char *
1401    l_to_a(long N, int base)
1402    {
1403            static char ret[LTOA_BUFSIZE];
1404    
1405            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1406    
1407            register int divrem;
1408    
1409            if (base < 36 || 2 > base)
1410                    base = 10;
1411    
1412            if (N < 0)
1413            {
1414                    *head++ = '-';
1415                    N = -N;
1416            }
1417    
1418            tail = buf + sizeof(buf);
1419            *--tail = 0;
1420    
1421            do
1422            {
1423                    divrem = N % base;
1424                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1425                    N /= base;
1426            }
1427            while (N);
1428    
1429            strcpy(head, tail);
1430            return ret;
1431    }
1432    
1433    
1434  int  int
1435  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1436  {  {
1437          char path[PATH_MAX];          char *home, *path;
         char *home;  
1438          struct stat st;          struct stat st;
1439          int fd;          int fd, length;
1440    
1441          home = getenv("HOME");          home = getenv("HOME");
1442          if (home == NULL)          if (home == NULL)
1443                  return -1;                  return -1;
1444    
1445          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1446          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1447    
1448          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1449          if (fd == -1)          if (fd == -1)
# Line 403  load_licence(unsigned char **data) Line 1452  load_licence(unsigned char **data)
1452          if (fstat(fd, &st))          if (fstat(fd, &st))
1453                  return -1;                  return -1;
1454    
1455          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1456          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1457            close(fd);
1458            xfree(path);
1459            return length;
1460  }  }
1461    
1462  void  void
1463  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1464  {  {
1465          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1466          int fd;          int fd;
1467    
1468          home = getenv("HOME");          home = getenv("HOME");
1469          if (home == NULL)          if (home == NULL)
1470                  return;                  return;
1471    
1472          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
         strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
         mkdir(path, 0700);  
1473    
1474          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop", home);
1475            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1476            {
1477                    perror(path);
1478                    return;
1479            }
1480    
1481            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1482    
1483          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1484            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1485            strcpy(tmppath, path);
1486            strcat(tmppath, ".new");
1487    
1488            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1489          if (fd == -1)          if (fd == -1)
1490          {          {
1491                  perror("open");                  perror(tmppath);
1492                  return;                  return;
1493          }          }
1494    
1495          write(fd, data, length);          if (write(fd, data, length) != length)
1496            {
1497                    perror(tmppath);
1498                    unlink(tmppath);
1499            }
1500            else if (rename(tmppath, path) == -1)
1501            {
1502                    perror(path);
1503                    unlink(tmppath);
1504            }
1505    
1506            close(fd);
1507            xfree(tmppath);
1508            xfree(path);
1509    }
1510    
1511    /* Create the bitmap cache directory */
1512    BOOL
1513    rd_pstcache_mkdir(void)
1514    {
1515            char *home;
1516            char bmpcache_dir[256];
1517    
1518            home = getenv("HOME");
1519    
1520            if (home == NULL)
1521                    return False;
1522    
1523            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1524    
1525            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1526            {
1527                    perror(bmpcache_dir);
1528                    return False;
1529            }
1530    
1531            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1532    
1533            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1534            {
1535                    perror(bmpcache_dir);
1536                    return False;
1537            }
1538    
1539            return True;
1540    }
1541    
1542    /* open a file in the .rdesktop directory */
1543    int
1544    rd_open_file(char *filename)
1545    {
1546            char *home;
1547            char fn[256];
1548            int fd;
1549    
1550            home = getenv("HOME");
1551            if (home == NULL)
1552                    return -1;
1553            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1554            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1555            if (fd == -1)
1556                    perror(fn);
1557            return fd;
1558    }
1559    
1560    /* close file */
1561    void
1562    rd_close_file(int fd)
1563    {
1564          close(fd);          close(fd);
1565  }  }
1566    
1567    /* read from file*/
1568    int
1569    rd_read_file(int fd, void *ptr, int len)
1570    {
1571            return read(fd, ptr, len);
1572    }
1573    
1574    /* write to file */
1575    int
1576    rd_write_file(int fd, void *ptr, int len)
1577    {
1578            return write(fd, ptr, len);
1579    }
1580    
1581    /* move file pointer */
1582    int
1583    rd_lseek_file(int fd, int offset)
1584    {
1585            return lseek(fd, offset, SEEK_SET);
1586    }
1587    
1588    /* do a write lock on a file */
1589    BOOL
1590    rd_lock_file(int fd, int start, int len)
1591    {
1592            struct flock lock;
1593    
1594            lock.l_type = F_WRLCK;
1595            lock.l_whence = SEEK_SET;
1596            lock.l_start = start;
1597            lock.l_len = len;
1598            if (fcntl(fd, F_SETLK, &lock) == -1)
1599                    return False;
1600            return True;
1601    }

Legend:
Removed from v.103  
changed lines
  Added in v.1306

  ViewVC Help
Powered by ViewVC 1.1.26