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

Diff of /jpeg/rdesktop/trunk/rdesktop.c

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

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

Legend:
Removed from v.223  
changed lines
  Added in v.1479

  ViewVC Help
Powered by ViewVC 1.1.26