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

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

  ViewVC Help
Powered by ViewVC 1.1.26