/[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 53 by matthewc, Tue May 28 11:48:55 2002 UTC revision 1309 by stargo, Wed Nov 1 20:52:01 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;  #ifdef HAVE_ICONV
37  int width;  #ifdef HAVE_LANGINFO_H
38  int height;  #include <langinfo.h>
39  BOOL bitmap_compression = True;  #endif
40  BOOL sendmotion = True;  #endif
41  BOOL orders = True;  
42  BOOL licence = True;  #ifdef EGD_SOCKET
43  BOOL encryption = True;  #include <sys/types.h>
44  BOOL desktop_save = True;  #include <sys/socket.h>         /* socket connect */
45  BOOL fullscreen = False;  #include <sys/un.h>             /* sockaddr_un */
46    #endif
47    
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\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\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
143            fprintf(stderr, "   -n: client hostname\n");
144            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    #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 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 BOOL
323    read_password(char *password, int size)
324    {
325            struct termios tios;
326            BOOL ret = False;
327            int istty = 0;
328            char *p;
329    
330            if (tcgetattr(STDIN_FILENO, &tios) == 0)
331            {
332                    fprintf(stderr, "Password: ");
333                    tios.c_lflag &= ~ECHO;
334                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
335                    istty = 1;
336            }
337    
338            if (fgets(password, size, stdin) != NULL)
339            {
340                    ret = True;
341    
342                    /* strip final newline */
343                    p = strchr(password, '\n');
344                    if (p != NULL)
345                            *p = 0;
346            }
347    
348            if (istty)
349            {
350                    tios.c_lflag |= ECHO;
351                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
352                    fprintf(stderr, "\n");
353            }
354    
355            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[])
409  {  {
410            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          char title[32];          BOOL prompt_password, deactivated;
417          struct passwd *pw;          struct passwd *pw;
418          char *server, *p;          uint32 flags, ext_disc_reason = 0;
419          uint32 flags;          char *p;
420          int c;          int c;
421            char *locale = NULL;
422            int username_option = 0;
423            BOOL geometry_option = False;
424            int run_count = 0;      /* Session Directory support */
425            BOOL continue_connect = True;   /* Session Directory support */
426            char *rdpsnd_optarg = NULL;
427    
428    #ifdef HAVE_LOCALE_H
429            /* Set locale according to environment */
430            locale = setlocale(LC_ALL, "");
431            if (locale)
432            {
433                    locale = xstrdup(locale);
434            }
435    
436          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");  
   
437          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
438            prompt_password = False;
439          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
440          strcpy(keymapname, "us");          g_embed_wnd = 0;
441    
442            g_num_devices = 0;
443    
444          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:fbemlh?")) != -1)  #ifdef RDP2VNC
445    #define VNCOPT "V:Q:"
446    #else
447    #define VNCOPT
448    #endif
449    
450            while ((c = getopt(argc, argv,
451                               VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
452          {          {
453                  switch (c)                  switch (c)
454                  {                  {
455    #ifdef RDP2VNC
456                            case 'V':
457                                    rfb_port = strtol(optarg, NULL, 10);
458                                    if (rfb_port < 100)
459                                            rfb_port += 5900;
460                                    break;
461    
462                            case 'Q':
463                                    defer_time = strtol(optarg, NULL, 10);
464                                    if (defer_time < 0)
465                                            defer_time = 0;
466                                    break;
467    #endif
468    
469                            case 'A':
470                                    g_seamless_rdp = True;
471                                    break;
472    
473                          case 'u':                          case 'u':
474                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
475                                    username_option = 1;
476                                    break;
477    
478                            case 'L':
479    #ifdef HAVE_ICONV
480                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
481    #else
482                                    error("iconv support not available\n");
483    #endif
484                                  break;                                  break;
485    
486                          case 'd':                          case 'd':
# Line 107  main(int argc, char *argv[]) Line 496  main(int argc, char *argv[])
496                                  break;                                  break;
497    
498                          case 'p':                          case 'p':
499                                    if ((optarg[0] == '-') && (optarg[1] == 0))
500                                    {
501                                            prompt_password = True;
502                                            break;
503                                    }
504    
505                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
506                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
507    
508                                    /* try to overwrite argument so it won't appear in ps */
509                                    p = optarg;
510                                    while (*p)
511                                            *(p++) = 'X';
512                                  break;                                  break;
513    
514                          case 'n':                          case 'n':
515                                  STRNCPY(hostname, optarg, sizeof(hostname));                                  STRNCPY(g_hostname, optarg, sizeof(g_hostname));
516                                  break;                                  break;
517    
518                          case 'k':                          case 'k':
519                                  STRNCPY(keymapname, optarg, sizeof(keymapname));                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
520                                  break;                                  break;
521    
522                          case 'g':                          case 'g':
523                                  width = strtol(optarg, &p, 10);                                  geometry_option = True;
524                                    g_fullscreen = False;
525                                    if (!strcmp(optarg, "workarea"))
526                                    {
527                                            g_width = g_height = 0;
528                                            break;
529                                    }
530    
531                                    g_width = strtol(optarg, &p, 10);
532                                    if (g_width <= 0)
533                                    {
534                                            error("invalid geometry\n");
535                                            return 1;
536                                    }
537    
538                                  if (*p == 'x')                                  if (*p == 'x')
539                                          height = strtol(p+1, NULL, 10);                                          g_height = strtol(p + 1, &p, 10);
540    
541                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
542                                  {                                  {
543                                          error("invalid geometry\n");                                          error("invalid geometry\n");
544                                          return 1;                                          return 1;
545                                  }                                  }
546    
547                                    if (*p == '%')
548                                    {
549                                            g_width = -g_width;
550                                            p++;
551                                    }
552    
553                                    if (*p == '+' || *p == '-')
554                                    {
555                                            g_pos |= (*p == '-') ? 2 : 1;
556                                            g_xpos = strtol(p, &p, 10);
557    
558                                    }
559                                    if (*p == '+' || *p == '-')
560                                    {
561                                            g_pos |= (*p == '-') ? 4 : 1;
562                                            g_ypos = strtol(p, NULL, 10);
563                                    }
564    
565                                  break;                                  break;
566    
567                          case 'f':                          case 'f':
568                                  fullscreen = True;                                  g_fullscreen = True;
569                                  break;                                  break;
570    
571                          case 'b':                          case 'b':
572                                  orders = False;                                  g_bitmap_cache = False;
573                                  break;                                  break;
574    
575                          case 'e':                          case 'B':
576                                  encryption = False;                                  g_ownbackstore = False;
577                                  break;                                  break;
578    
579                            case 'e':
580                                    g_encryption = False;
581                                    break;
582                            case 'E':
583                                    packet_encryption = False;
584                                    break;
585                          case 'm':                          case 'm':
586                                  sendmotion = False;                                  g_sendmotion = False;
587                                    break;
588    
589                            case 'C':
590                                    g_owncolmap = True;
591                                    break;
592    
593                            case 'D':
594                                    g_hide_decorations = True;
595                                    break;
596    
597                            case 'K':
598                                    g_grab_keyboard = False;
599                                    break;
600    
601                            case 'S':
602                                    if (!strcmp(optarg, "standard"))
603                                    {
604                                            g_win_button_size = 18;
605                                            break;
606                                    }
607    
608                                    g_win_button_size = strtol(optarg, &p, 10);
609    
610                                    if (*p)
611                                    {
612                                            error("invalid button size\n");
613                                            return 1;
614                                    }
615    
616                                    break;
617    
618                            case 'T':
619                                    STRNCPY(g_title, optarg, sizeof(g_title));
620                                    break;
621    
622                            case 'N':
623                                    g_numlock_sync = True;
624                                    break;
625    
626                            case 'X':
627                                    g_embed_wnd = strtol(optarg, NULL, 0);
628                                    break;
629    
630                            case 'a':
631                                    g_server_depth = strtol(optarg, NULL, 10);
632                                    if (g_server_depth != 8 &&
633                                        g_server_depth != 16 &&
634                                        g_server_depth != 15 && g_server_depth != 24)
635                                    {
636                                            error("Invalid server colour depth.\n");
637                                            return 1;
638                                    }
639                                    break;
640    
641                            case 'z':
642                                    DEBUG(("rdp compression enabled\n"));
643                                    flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
644                                    break;
645    
646                            case 'x':
647                                    if (str_startswith(optarg, "m"))        /* modem */
648                                    {
649                                            g_rdp5_performanceflags =
650                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
651                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
652                                    }
653                                    else if (str_startswith(optarg, "b"))   /* broadband */
654                                    {
655                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
656                                    }
657                                    else if (str_startswith(optarg, "l"))   /* lan */
658                                    {
659                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
660                                    }
661                                    else
662                                    {
663                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
664                                    }
665                                    break;
666    
667                            case 'P':
668                                    g_bitmap_cache_persist_enable = True;
669                                    break;
670    
671                            case 'r':
672    
673                                    if (str_startswith(optarg, "sound"))
674                                    {
675                                            optarg += 5;
676    
677                                            if (*optarg == ':')
678                                            {
679                                                    optarg++;
680                                                    while ((p = next_arg(optarg, ',')))
681                                                    {
682                                                            if (str_startswith(optarg, "remote"))
683                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
684    
685                                                            if (str_startswith(optarg, "local"))
686    #ifdef WITH_RDPSND
687                                                            {
688                                                                    rdpsnd_optarg =
689                                                                            next_arg(optarg, ':');
690                                                                    g_rdpsnd = True;
691                                                            }
692    
693    #else
694                                                                    warning("Not compiled with sound support\n");
695    #endif
696    
697                                                            if (str_startswith(optarg, "off"))
698    #ifdef WITH_RDPSND
699                                                                    g_rdpsnd = False;
700    #else
701                                                                    warning("Not compiled with sound support\n");
702    #endif
703    
704                                                            optarg = p;
705                                                    }
706                                            }
707                                            else
708                                            {
709    #ifdef WITH_RDPSND
710                                                    g_rdpsnd = True;
711    #else
712                                                    warning("Not compiled with sound support\n");
713    #endif
714                                            }
715                                    }
716                                    else if (str_startswith(optarg, "disk"))
717                                    {
718                                            /* -r disk:h:=/mnt/floppy */
719                                            disk_enum_devices(&g_num_devices, optarg + 4);
720                                    }
721                                    else if (str_startswith(optarg, "comport"))
722                                    {
723                                            serial_enum_devices(&g_num_devices, optarg + 7);
724                                    }
725                                    else if (str_startswith(optarg, "lspci"))
726                                    {
727                                            lspci_enabled = True;
728                                    }
729                                    else if (str_startswith(optarg, "lptport"))
730                                    {
731                                            parallel_enum_devices(&g_num_devices, optarg + 7);
732                                    }
733                                    else if (str_startswith(optarg, "printer"))
734                                    {
735                                            printer_enum_devices(&g_num_devices, optarg + 7);
736                                    }
737                                    else if (str_startswith(optarg, "clientname"))
738                                    {
739                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
740                                            strcpy(g_rdpdr_clientname, optarg + 11);
741                                    }
742                                    else if (str_startswith(optarg, "clipboard"))
743                                    {
744                                            optarg += 9;
745    
746                                            if (*optarg == ':')
747                                            {
748                                                    optarg++;
749    
750                                                    if (str_startswith(optarg, "off"))
751                                                            g_rdpclip = False;
752                                                    else
753                                                            cliprdr_set_mode(optarg);
754                                            }
755                                            else
756                                                    g_rdpclip = True;
757                                    }
758                                    else if (strncmp("scard", optarg, 5) == 0)
759                                    {
760    #ifdef WITH_SCARD
761                                            scard_enum_devices(&g_num_devices, optarg + 5);
762    #else
763                                            warning("Not compiled with smartcard support\n");
764    #endif
765                                    }
766                                    else
767                                    {
768                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard, scard\n");
769                                    }
770                                    break;
771    
772                            case '0':
773                                    g_console_session = True;
774                                    break;
775    
776                            case '4':
777                                    g_use_rdp5 = False;
778                                  break;                                  break;
779    
780                          case 'l':                          case '5':
781                                  licence = False;                                  g_use_rdp5 = True;
782                                  break;                                  break;
783    
784                          case 'h':                          case 'h':
# Line 159  main(int argc, char *argv[]) Line 789  main(int argc, char *argv[])
789                  }                  }
790          }          }
791    
792          if (argc - optind < 1)          if (argc - optind != 1)
793          {          {
794                  usage(argv[0]);                  usage(argv[0]);
795                  return 1;                  return 1;
796          }          }
797    
798          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
799            parse_server_and_port(server);
800    
801            if (g_seamless_rdp)
802            {
803                    if (g_win_button_size)
804                    {
805                            error("You cannot use -S and -A at the same time\n");
806                            return 1;
807                    }
808                    g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
809                    if (geometry_option)
810                    {
811                            error("You cannot use -g and -A at the same time\n");
812                            return 1;
813                    }
814                    if (g_fullscreen)
815                    {
816                            error("You cannot use -f and -A at the same time\n");
817                            return 1;
818                    }
819                    if (g_hide_decorations)
820                    {
821                            error("You cannot use -D and -A at the same time\n");
822                            return 1;
823                    }
824                    if (g_embed_wnd)
825                    {
826                            error("You cannot use -X and -A at the same time\n");
827                            return 1;
828                    }
829                    if (!g_use_rdp5)
830                    {
831                            error("You cannot use -4 and -A at the same time\n");
832                            return 1;
833                    }
834                    g_width = -100;
835                    g_grab_keyboard = False;
836            }
837    
838          if (username[0] == 0)          if (!username_option)
839          {          {
840                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
841                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 176  main(int argc, char *argv[]) Line 844  main(int argc, char *argv[])
844                          return 1;                          return 1;
845                  }                  }
846    
847                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
848            }
849    
850    #ifdef HAVE_ICONV
851            if (g_codepage[0] == 0)
852            {
853                    if (setlocale(LC_CTYPE, ""))
854                    {
855                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
856                    }
857                    else
858                    {
859                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
860                    }
861          }          }
862    #endif
863    
864          if (hostname[0] == 0)          if (g_hostname[0] == 0)
865          {          {
866                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
867                  {                  {
# Line 191  main(int argc, char *argv[]) Line 873  main(int argc, char *argv[])
873                  if (p != NULL)                  if (p != NULL)
874                          *p = 0;                          *p = 0;
875    
876                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
877          }          }
878    
879          if (!strcmp(password, "-"))          if (g_keymapname[0] == 0)
880          {          {
881                  p = getpass("Password: ");                  if (locale && xkeymap_from_locale(locale))
                 if (p == NULL)  
882                  {                  {
883                          error("failed to read password\n");                          fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
884                          return 0;                  }
885                    else
886                    {
887                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
888                  }                  }
                 STRNCPY(password, p, sizeof(password));  
889          }          }
890            if (locale)
891                    xfree(locale);
892    
893    
894            if (prompt_password && read_password(password, sizeof(password)))
895                    flags |= RDP_LOGON_AUTO;
896    
897          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
898          {          {
899                  width = 800;                  strcpy(g_title, "rdesktop - ");
900                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
901          }          }
902    
903          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
904          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
905            return 0;
906    #else
907    
908          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!ui_init())
909                  return 1;                  return 1;
910    
911          printf("Connection successful.\n");  #ifdef WITH_RDPSND
912            if (g_rdpsnd)
913            {
914                    if (!rdpsnd_init(rdpsnd_optarg))
915                    {
916                            warning("Initializing sound-support failed!\n");
917                    }
918            }
919    #endif
920    
921            if (lspci_enabled)
922                    lspci_init();
923    
924            rdpdr_init();
925    
926          if (ui_create_window(title))          while (run_count < 2 && continue_connect)       /* add support for Session Directory; only reconnect once */
927          {          {
928                  rdp_main_loop();                  if (run_count == 0)
929                  ui_destroy_window();                  {
930                            if (!rdp_connect(server, flags, domain, password, shell, directory))
931                                    return 1;
932                    }
933                    else if (!rdp_reconnect
934                             (server, flags, domain, password, shell, directory, g_redirect_cookie))
935                            return 1;
936    
937                    /* By setting encryption to False here, we have an encrypted login
938                       packet but unencrypted transfer of other packets */
939                    if (!packet_encryption)
940                            g_encryption = False;
941    
942    
943                    DEBUG(("Connection successful.\n"));
944                    memset(password, 0, sizeof(password));
945    
946                    if (run_count == 0)
947                            if (!ui_create_window())
948                                    continue_connect = False;
949    
950                    if (continue_connect)
951                            rdp_main_loop(&deactivated, &ext_disc_reason);
952    
953                    DEBUG(("Disconnecting...\n"));
954                    rdp_disconnect();
955    
956                    if ((g_redirect == True) && (run_count == 0))   /* Support for Session Directory */
957                    {
958                            /* reset state of major globals */
959                            rdesktop_reset_state();
960    
961                            STRNCPY(domain, g_redirect_domain, sizeof(domain));
962                            STRNCPY(g_username, g_redirect_username, sizeof(g_username));
963                            STRNCPY(password, g_redirect_password, sizeof(password));
964                            STRNCPY(server, g_redirect_server, sizeof(server));
965                            flags |= RDP_LOGON_AUTO;
966    
967                            g_redirect = False;
968                    }
969                    else
970                    {
971                            continue_connect = False;
972                            ui_destroy_window();
973                            break;
974                    }
975    
976                    run_count++;
977          }          }
978    
979          printf("Disconnecting...\n");          cache_save_state();
980          rdp_disconnect();          ui_deinit();
981          return 0;  
982            if (ext_disc_reason >= 2)
983                    print_disconnect_reason(ext_disc_reason);
984    
985            if (deactivated)
986            {
987                    /* clean disconnect */
988                    return 0;
989            }
990            else
991            {
992                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
993                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
994                    {
995                            /* not so clean disconnect, but nothing to worry about */
996                            return 0;
997                    }
998                    else
999                    {
1000                            /* return error */
1001                            return 2;
1002                    }
1003            }
1004    
1005    #endif
1006    
1007    }
1008    
1009    #ifdef EGD_SOCKET
1010    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
1011    static BOOL
1012    generate_random_egd(uint8 * buf)
1013    {
1014            struct sockaddr_un addr;
1015            BOOL ret = False;
1016            int fd;
1017    
1018            fd = socket(AF_UNIX, SOCK_STREAM, 0);
1019            if (fd == -1)
1020                    return False;
1021    
1022            addr.sun_family = AF_UNIX;
1023            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
1024            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
1025                    goto err;
1026    
1027            /* PRNGD and EGD use a simple communications protocol */
1028            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
1029            buf[1] = 32;            /* Number of requested random bytes */
1030            if (write(fd, buf, 2) != 2)
1031                    goto err;
1032    
1033            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
1034                    goto err;
1035    
1036            if (read(fd, buf, 32) != 32)
1037                    goto err;
1038    
1039            ret = True;
1040    
1041          err:
1042            close(fd);
1043            return ret;
1044  }  }
1045    #endif
1046    
1047  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
1048  void  void
1049  generate_random(uint8 *random)  generate_random(uint8 * random)
1050  {  {
1051          struct stat st;          struct stat st;
1052          struct tms tmsbuf;          struct tms tmsbuf;
1053          uint32 *r = (uint32 *) random;          MD5_CTX md5;
1054          int fd;          uint32 *r;
1055            int fd, n;
1056    
1057          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
1058          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
1059              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
1060          {          {
1061                  read(fd, random, 32);                  n = read(fd, random, 32);
1062                  close(fd);                  close(fd);
1063                  return;                  if (n == 32)
1064                            return;
1065          }          }
1066    
1067    #ifdef EGD_SOCKET
1068            /* As a second preference use an EGD */
1069            if (generate_random_egd(random))
1070                    return;
1071    #endif
1072    
1073          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
1074            r = (uint32 *) random;
1075          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
1076          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
1077          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 257  generate_random(uint8 *random) Line 1080  generate_random(uint8 *random)
1080          r[5] = st.st_atime;          r[5] = st.st_atime;
1081          r[6] = st.st_mtime;          r[6] = st.st_mtime;
1082          r[7] = st.st_ctime;          r[7] = st.st_ctime;
1083    
1084            /* Hash both halves with MD5 to obscure possible patterns */
1085            MD5_Init(&md5);
1086            MD5_Update(&md5, random, 16);
1087            MD5_Final(random, &md5);
1088            MD5_Update(&md5, random + 16, 16);
1089            MD5_Final(random + 16, &md5);
1090  }  }
1091    
1092  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 272  xmalloc(int size) Line 1102  xmalloc(int size)
1102          return mem;          return mem;
1103  }  }
1104    
1105    /* Exit on NULL pointer. Use to verify result from XGetImage etc */
1106    void
1107    exit_if_null(void *ptr)
1108    {
1109            if (ptr == NULL)
1110            {
1111                    error("unexpected null pointer. Out of memory?\n");
1112                    exit(1);
1113            }
1114    }
1115    
1116    /* strdup */
1117    char *
1118    xstrdup(const char *s)
1119    {
1120            char *mem = strdup(s);
1121            if (mem == NULL)
1122            {
1123                    perror("strdup");
1124                    exit(1);
1125            }
1126            return mem;
1127    }
1128    
1129  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1130  void *  void *
1131  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
1132  {  {
1133          void *mem = realloc(oldmem, size);          void *mem;
1134    
1135            if (size < 1)
1136                    size = 1;
1137            mem = realloc(oldmem, size);
1138          if (mem == NULL)          if (mem == NULL)
1139          {          {
1140                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 305  error(char *format, ...) Line 1163  error(char *format, ...)
1163          va_end(ap);          va_end(ap);
1164  }  }
1165    
1166    /* report a warning */
1167    void
1168    warning(char *format, ...)
1169    {
1170            va_list ap;
1171    
1172            fprintf(stderr, "WARNING: ");
1173    
1174            va_start(ap, format);
1175            vfprintf(stderr, format, ap);
1176            va_end(ap);
1177    }
1178    
1179  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
1180  void  void
1181  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 323  void Line 1194  void
1194  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, unsigned int len)
1195  {  {
1196          unsigned char *line = p;          unsigned char *line = p;
1197          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
1198    
1199          while (offset < len)          while (offset < len)
1200          {          {
# Line 337  hexdump(unsigned char *p, unsigned int l Line 1207  hexdump(unsigned char *p, unsigned int l
1207                          printf("%02x ", line[i]);                          printf("%02x ", line[i]);
1208    
1209                  for (; i < 16; i++)                  for (; i < 16; i++)
1210                                  printf("   ");                          printf("   ");
1211    
1212                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1213                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
1214    
1215                  printf("\n");                  printf("\n");
1216                  offset += thisline;                  offset += thisline;
# Line 350  hexdump(unsigned char *p, unsigned int l Line 1218  hexdump(unsigned char *p, unsigned int l
1218          }          }
1219  }  }
1220    
1221    /*
1222      input: src is the string we look in for needle.
1223             Needle may be escaped by a backslash, in
1224             that case we ignore that particular needle.
1225      return value: returns next src pointer, for
1226            succesive executions, like in a while loop
1227            if retval is 0, then there are no more args.
1228      pitfalls:
1229            src is modified. 0x00 chars are inserted to
1230            terminate strings.
1231            return val, points on the next val chr after ins
1232            0x00
1233    
1234            example usage:
1235            while( (pos = next_arg( optarg, ',')) ){
1236                    printf("%s\n",optarg);
1237                    optarg=pos;
1238            }
1239    
1240    */
1241    char *
1242    next_arg(char *src, char needle)
1243    {
1244            char *nextval;
1245            char *p;
1246            char *mvp = 0;
1247    
1248            /* EOS */
1249            if (*src == (char) 0x00)
1250                    return 0;
1251    
1252            p = src;
1253            /*  skip escaped needles */
1254            while ((nextval = strchr(p, needle)))
1255            {
1256                    mvp = nextval - 1;
1257                    /* found backslashed needle */
1258                    if (*mvp == '\\' && (mvp > src))
1259                    {
1260                            /* move string one to the left */
1261                            while (*(mvp + 1) != (char) 0x00)
1262                            {
1263                                    *mvp = *(mvp + 1);
1264                                    mvp++;
1265                            }
1266                            *mvp = (char) 0x00;
1267                            p = nextval;
1268                    }
1269                    else
1270                    {
1271                            p = nextval + 1;
1272                            break;
1273                    }
1274    
1275            }
1276    
1277            /* more args available */
1278            if (nextval)
1279            {
1280                    *nextval = (char) 0x00;
1281                    return ++nextval;
1282            }
1283    
1284            /* no more args after this, jump to EOS */
1285            nextval = src + strlen(src);
1286            return nextval;
1287    }
1288    
1289    
1290    void
1291    toupper_str(char *p)
1292    {
1293            while (*p)
1294            {
1295                    if ((*p >= 'a') && (*p <= 'z'))
1296                            *p = toupper((int) *p);
1297                    p++;
1298            }
1299    }
1300    
1301    
1302    BOOL
1303    str_startswith(const char *s, const char *prefix)
1304    {
1305            return (strncmp(s, prefix, strlen(prefix)) == 0);
1306    }
1307    
1308    
1309    /* Split input into lines, and call linehandler for each
1310       line. Incomplete lines are saved in the rest variable, which should
1311       initially point to NULL. When linehandler returns False, stop and
1312       return False. Otherwise, return True.  */
1313    BOOL
1314    str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1315    {
1316            char *buf, *p;
1317            char *oldrest;
1318            size_t inputlen;
1319            size_t buflen;
1320            size_t restlen = 0;
1321            BOOL ret = True;
1322    
1323            /* Copy data to buffer */
1324            inputlen = strlen(input);
1325            if (*rest)
1326                    restlen = strlen(*rest);
1327            buflen = restlen + inputlen + 1;
1328            buf = (char *) xmalloc(buflen);
1329            buf[0] = '\0';
1330            if (*rest)
1331                    STRNCPY(buf, *rest, buflen);
1332            strncat(buf, input, inputlen);
1333            p = buf;
1334    
1335            while (1)
1336            {
1337                    char *newline = strchr(p, '\n');
1338                    if (newline)
1339                    {
1340                            *newline = '\0';
1341                            if (!linehandler(p, data))
1342                            {
1343                                    p = newline + 1;
1344                                    ret = False;
1345                                    break;
1346                            }
1347                            p = newline + 1;
1348                    }
1349                    else
1350                    {
1351                            break;
1352    
1353                    }
1354            }
1355    
1356            /* Save in rest */
1357            oldrest = *rest;
1358            restlen = buf + buflen - p;
1359            *rest = (char *) xmalloc(restlen);
1360            STRNCPY((*rest), p, restlen);
1361            xfree(oldrest);
1362    
1363            xfree(buf);
1364            return ret;
1365    }
1366    
1367    /* Execute the program specified by argv. For each line in
1368       stdout/stderr output, call linehandler. Returns false on failure. */
1369    BOOL
1370    subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1371    {
1372            pid_t child;
1373            int fd[2];
1374            int n = 1;
1375            char output[256];
1376            char *rest = NULL;
1377    
1378            if (pipe(fd) < 0)
1379            {
1380                    perror("pipe");
1381                    return False;
1382            }
1383    
1384            if ((child = fork()) < 0)
1385            {
1386                    perror("fork");
1387                    return False;
1388            }
1389    
1390            /* Child */
1391            if (child == 0)
1392            {
1393                    /* Close read end */
1394                    close(fd[0]);
1395    
1396                    /* Redirect stdout and stderr to pipe */
1397                    dup2(fd[1], 1);
1398                    dup2(fd[1], 2);
1399    
1400                    /* Execute */
1401                    execvp(argv[0], argv);
1402                    perror("Error executing child");
1403                    _exit(128);
1404            }
1405    
1406            /* Parent. Close write end. */
1407            close(fd[1]);
1408            while (n > 0)
1409            {
1410                    n = read(fd[0], output, 255);
1411                    output[n] = '\0';
1412                    str_handle_lines(output, &rest, linehandler, data);
1413            }
1414            xfree(rest);
1415    
1416            return True;
1417    }
1418    
1419    
1420    /* not all clibs got ltoa */
1421    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1422    
1423    char *
1424    l_to_a(long N, int base)
1425    {
1426            static char ret[LTOA_BUFSIZE];
1427    
1428            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1429    
1430            register int divrem;
1431    
1432            if (base < 36 || 2 > base)
1433                    base = 10;
1434    
1435            if (N < 0)
1436            {
1437                    *head++ = '-';
1438                    N = -N;
1439            }
1440    
1441            tail = buf + sizeof(buf);
1442            *--tail = 0;
1443    
1444            do
1445            {
1446                    divrem = N % base;
1447                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1448                    N /= base;
1449            }
1450            while (N);
1451    
1452            strcpy(head, tail);
1453            return ret;
1454    }
1455    
1456    
1457  int  int
1458  load_licence(unsigned char **data)  load_licence(unsigned char **data)
1459  {  {
1460          char path[PATH_MAX];          char *home, *path;
         char *home;  
1461          struct stat st;          struct stat st;
1462          int fd;          int fd, length;
1463    
1464          home = getenv("HOME");          home = getenv("HOME");
1465          if (home == NULL)          if (home == NULL)
1466                  return -1;                  return -1;
1467    
1468          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1469          strncat(path, "/.rdesktop/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1470    
1471          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1472          if (fd == -1)          if (fd == -1)
# Line 372  load_licence(unsigned char **data) Line 1475  load_licence(unsigned char **data)
1475          if (fstat(fd, &st))          if (fstat(fd, &st))
1476                  return -1;                  return -1;
1477    
1478          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1479          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1480            close(fd);
1481            xfree(path);
1482            return length;
1483  }  }
1484    
1485  void  void
1486  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
1487  {  {
1488          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
1489          int fd;          int fd;
1490    
1491          home = getenv("HOME");          home = getenv("HOME");
1492          if (home == NULL)          if (home == NULL)
1493                  return;                  return;
1494    
1495          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
         strncat(path, "/.rdesktop", sizeof(path)-strlen(path)-1);  
         mkdir(path, 0700);  
1496    
1497          strncat(path, "/licence", sizeof(path)-strlen(path)-1);          sprintf(path, "%s/.rdesktop", home);
1498            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1499            {
1500                    perror(path);
1501                    return;
1502            }
1503    
1504            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1505    
1506          fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0600);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1507            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1508            strcpy(tmppath, path);
1509            strcat(tmppath, ".new");
1510    
1511            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1512          if (fd == -1)          if (fd == -1)
1513          {          {
1514                  perror("open");                  perror(tmppath);
1515                  return;                  return;
1516          }          }
1517    
1518          write(fd, data, length);          if (write(fd, data, length) != length)
1519            {
1520                    perror(tmppath);
1521                    unlink(tmppath);
1522            }
1523            else if (rename(tmppath, path) == -1)
1524            {
1525                    perror(path);
1526                    unlink(tmppath);
1527            }
1528    
1529          close(fd);          close(fd);
1530            xfree(tmppath);
1531            xfree(path);
1532    }
1533    
1534    /* Create the bitmap cache directory */
1535    BOOL
1536    rd_pstcache_mkdir(void)
1537    {
1538            char *home;
1539            char bmpcache_dir[256];
1540    
1541            home = getenv("HOME");
1542    
1543            if (home == NULL)
1544                    return False;
1545    
1546            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1547    
1548            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1549            {
1550                    perror(bmpcache_dir);
1551                    return False;
1552            }
1553    
1554            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1555    
1556            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1557            {
1558                    perror(bmpcache_dir);
1559                    return False;
1560            }
1561    
1562            return True;
1563  }  }
1564    
1565    /* open a file in the .rdesktop directory */
1566    int
1567    rd_open_file(char *filename)
1568    {
1569            char *home;
1570            char fn[256];
1571            int fd;
1572    
1573            home = getenv("HOME");
1574            if (home == NULL)
1575                    return -1;
1576            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1577            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1578            if (fd == -1)
1579                    perror(fn);
1580            return fd;
1581    }
1582    
1583    /* close file */
1584    void
1585    rd_close_file(int fd)
1586    {
1587            close(fd);
1588    }
1589    
1590    /* read from file*/
1591    int
1592    rd_read_file(int fd, void *ptr, int len)
1593    {
1594            return read(fd, ptr, len);
1595    }
1596    
1597    /* write to file */
1598    int
1599    rd_write_file(int fd, void *ptr, int len)
1600    {
1601            return write(fd, ptr, len);
1602    }
1603    
1604    /* move file pointer */
1605    int
1606    rd_lseek_file(int fd, int offset)
1607    {
1608            return lseek(fd, offset, SEEK_SET);
1609    }
1610    
1611    /* do a write lock on a file */
1612    BOOL
1613    rd_lock_file(int fd, int start, int len)
1614    {
1615            struct flock lock;
1616    
1617            lock.l_type = F_WRLCK;
1618            lock.l_whence = SEEK_SET;
1619            lock.l_start = start;
1620            lock.l_len = len;
1621            if (fcntl(fd, F_SETLK, &lock) == -1)
1622                    return False;
1623            return True;
1624    }

Legend:
Removed from v.53  
changed lines
  Added in v.1309

  ViewVC Help
Powered by ViewVC 1.1.26