/[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

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

Legend:
Removed from v.122  
changed lines
  Added in v.1089

  ViewVC Help
Powered by ViewVC 1.1.26