/[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 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 1271 by stargo, Mon Sep 18 21:42: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-2000     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    
21  #include <stdlib.h>     /* malloc realloc free */  #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 <getopt.h>     /* getopt */  #include <pwd.h>                /* getpwuid */
25  #include <pwd.h>        /* getpwuid */  #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  int width = 800;  #endif
36  int height = 600;  #ifdef HAVE_ICONV
37  int keylayout = 0x409;  #ifdef HAVE_LANGINFO_H
38  BOOL motion = False;  #include <langinfo.h>
39  BOOL orders = True;  #endif
40  BOOL licence = True;  #endif
41    
42    #ifdef EGD_SOCKET
43    #include <sys/types.h>
44    #include <sys/socket.h>         /* socket connect */
45    #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 usage(char *program)  static void
127    usage(char *program)
128    {
129            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
130            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
131            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
132    
133            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
134    #ifdef RDP2VNC
135            fprintf(stderr, "   -V: vnc port\n");
136            fprintf(stderr, "   -Q: defer time (ms)\n");
137    #endif
138            fprintf(stderr, "   -u: user name\n");
139            fprintf(stderr, "   -d: domain\n");
140            fprintf(stderr, "   -s: shell\n");
141            fprintf(stderr, "   -c: working directory\n");
142            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            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          STATUS("Usage: %s [options] server\n", program);          char *text;
205          STATUS("   -u: user name\n");  
206          STATUS("   -n: client hostname\n");          switch (reason)
207          STATUS("   -w: desktop width\n");          {
208          STATUS("   -h: desktop height\n");                  case exDiscReasonNoInfo:
209          STATUS("   -k: keyboard layout (hex)\n");                          text = "No information available";
210          STATUS("   -m: send motion events\n");                          break;
211          STATUS("   -b: force bitmap updates\n");  
212          STATUS("   -l: do not request licence\n\n");                  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 main(int argc, char *argv[])  int
393    main(int argc, char *argv[])
394  {  {
395            char server[64];
396            char fullhostname[64];
397            char domain[16];
398            char password[64];
399            char shell[256];
400            char directory[256];
401            BOOL prompt_password, deactivated;
402          struct passwd *pw;          struct passwd *pw;
403          char *server;          uint32 flags, ext_disc_reason = 0;
404          char title[32];          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          STATUS("rdesktop: A Remote Desktop Protocol client.\n");  #endif
421          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n\n");          flags = RDP_LOGON_NORMAL;
422            prompt_password = False;
423            domain[0] = password[0] = shell[0] = directory[0] = 0;
424            g_embed_wnd = 0;
425    
426            g_num_devices = 0;
427    
428    #ifdef RDP2VNC
429    #define VNCOPT "V:Q:"
430    #else
431    #define VNCOPT
432    #endif
433    
434          while ((c = getopt(argc, argv, "u:n:w:h:k:mbl?")) != -1)          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;                                  break;
461    
462                          case 'n':                          case 'L':
463                                  strncpy(hostname, optarg, sizeof(hostname));  #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 'w':                          case 'd':
471                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(domain, optarg, sizeof(domain));
472                                  break;                                  break;
473    
474                          case 'h':                          case 's':
475                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
476                                    break;
477    
478                            case 'c':
479                                    STRNCPY(directory, optarg, sizeof(directory));
480                                    break;
481    
482                            case 'p':
483                                    if ((optarg[0] == '-') && (optarg[1] == 0))
484                                    {
485                                            prompt_password = True;
486                                            break;
487                                    }
488    
489                                    STRNCPY(password, optarg, sizeof(password));
490                                    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;
497    
498                            case 'n':
499                                    STRNCPY(g_hostname, optarg, sizeof(g_hostname));
500                                  break;                                  break;
501    
502                          case 'k':                          case 'k':
503                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
504                                  break;                                  break;
505    
506                          case 'm':                          case 'g':
507                                  motion = True;                                  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')
523                                            g_height = strtol(p + 1, &p, 10);
524    
525                                    if (g_height <= 0)
526                                    {
527                                            error("invalid geometry\n");
528                                            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;
550    
551                            case 'f':
552                                    g_fullscreen = True;
553                                  break;                                  break;
554    
555                          case 'b':                          case 'b':
556                                  orders = False;                                  g_bitmap_cache = False;
557                                    break;
558    
559                            case 'B':
560                                    g_ownbackstore = False;
561                                    break;
562    
563                            case 'e':
564                                    g_encryption = False;
565                                    break;
566                            case 'E':
567                                    packet_encryption = False;
568                                    break;
569                            case 'm':
570                                    g_sendmotion = False;
571                                    break;
572    
573                            case 'C':
574                                    g_owncolmap = True;
575                                    break;
576    
577                            case 'D':
578                                    g_hide_decorations = True;
579                                    break;
580    
581                            case 'K':
582                                    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;                                  break;
629    
630                          case 'l':                          case 'x':
631                                  licence = False;                                  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;                                  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                                                                    if (!rdpsnd_select_driver
694                                                                        (driver, options))
695                                                                    {
696                                                                            warning("Driver not available\n");
697                                                                    }
698                                                                    else
699                                                                    {
700                                                                            g_rdpsnd = True;
701                                                                    }
702                                                            }
703    
704    #else
705                                                                    warning("Not compiled with sound support\n");
706    #endif
707    
708                                                            if (str_startswith(optarg, "off"))
709    #ifdef WITH_RDPSND
710                                                                    g_rdpsnd = False;
711    #else
712                                                                    warning("Not compiled with sound support\n");
713    #endif
714    
715                                                            optarg = p;
716                                                    }
717                                            }
718                                            else
719                                            {
720    #ifdef WITH_RDPSND
721                                                    if (!rdpsnd_select_driver(NULL, NULL))
722                                                    {
723                                                            warning("No sound-driver available\n");
724                                                    }
725                                                    else
726                                                    {
727                                                            g_rdpsnd = True;
728                                                    }
729    #else
730                                                    warning("Not compiled with sound support\n");
731    #endif
732                                            }
733                                    }
734                                    else if (str_startswith(optarg, "disk"))
735                                    {
736                                            /* -r disk:h:=/mnt/floppy */
737                                            disk_enum_devices(&g_num_devices, optarg + 4);
738                                    }
739                                    else if (str_startswith(optarg, "comport"))
740                                    {
741                                            serial_enum_devices(&g_num_devices, optarg + 7);
742                                    }
743                                    else if (str_startswith(optarg, "lspci"))
744                                    {
745                                            lspci_enabled = True;
746                                    }
747                                    else if (str_startswith(optarg, "lptport"))
748                                    {
749                                            parallel_enum_devices(&g_num_devices, optarg + 7);
750                                    }
751                                    else if (str_startswith(optarg, "printer"))
752                                    {
753                                            printer_enum_devices(&g_num_devices, optarg + 7);
754                                    }
755                                    else if (str_startswith(optarg, "clientname"))
756                                    {
757                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
758                                            strcpy(g_rdpdr_clientname, optarg + 11);
759                                    }
760                                    else if (str_startswith(optarg, "clipboard"))
761                                    {
762                                            optarg += 9;
763    
764                                            if (*optarg == ':')
765                                            {
766                                                    optarg++;
767    
768                                                    if (str_startswith(optarg, "off"))
769                                                            g_rdpclip = False;
770                                                    else
771                                                            cliprdr_set_mode(optarg);
772                                            }
773                                            else
774                                                    g_rdpclip = True;
775                                    }
776                                    else
777                                    {
778                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard\n");
779                                    }
780                                    break;
781    
782                            case '0':
783                                    g_console_session = True;
784                                    break;
785    
786                            case '4':
787                                    g_use_rdp5 = False;
788                                    break;
789    
790                            case '5':
791                                    g_use_rdp5 = True;
792                                    break;
793    
794                            case 'h':
795                          case '?':                          case '?':
796                          default:                          default:
797                                  usage(argv[0]);                                  usage(argv[0]);
# Line 105  int main(int argc, char *argv[]) Line 799  int main(int argc, char *argv[])
799                  }                  }
800          }          }
801    
802          if (argc - optind < 1)          if (argc - optind != 1)
803          {          {
804                  usage(argv[0]);                  usage(argv[0]);
805                  return 1;                  return 1;
806          }          }
807    
808          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
809            parse_server_and_port(server);
810    
811            if (g_seamless_rdp)
812            {
813                    if (g_win_button_size)
814                    {
815                            error("You cannot use -S and -A at the same time\n");
816                            return 1;
817                    }
818                    g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
819                    if (geometry_option)
820                    {
821                            error("You cannot use -g and -A at the same time\n");
822                            return 1;
823                    }
824                    if (g_fullscreen)
825                    {
826                            error("You cannot use -f and -A at the same time\n");
827                            return 1;
828                    }
829                    if (g_hide_decorations)
830                    {
831                            error("You cannot use -D and -A at the same time\n");
832                            return 1;
833                    }
834                    if (g_embed_wnd)
835                    {
836                            error("You cannot use -X and -A at the same time\n");
837                            return 1;
838                    }
839                    if (!g_use_rdp5)
840                    {
841                            error("You cannot use -4 and -A at the same time\n");
842                            return 1;
843                    }
844                    g_width = -100;
845                    g_grab_keyboard = False;
846            }
847    
848          if (username[0] == 0)          if (!username_option)
849          {          {
850                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
851                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
852                  {                  {
853                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
854                          return 1;                          return 1;
855                  }                  }
856    
857                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
858          }          }
859    
860          if (hostname[0] == 0)  #ifdef HAVE_ICONV
861            if (g_codepage[0] == 0)
862          {          {
863                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (setlocale(LC_CTYPE, ""))
864                  {                  {
865                          STATUS("Could not determine host name.\n");                          STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
866                    }
867                    else
868                    {
869                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
870                    }
871            }
872    #endif
873    
874            if (g_hostname[0] == 0)
875            {
876                    if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
877                    {
878                            error("could not determine local hostname, use -n\n");
879                          return 1;                          return 1;
880                  }                  }
881    
882                    p = strchr(fullhostname, '.');
883                    if (p != NULL)
884                            *p = 0;
885    
886                    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
887          }          }
888    
889          if (!rdp_connect(server))          if (g_keymapname[0] == 0)
890                  return 1;          {
891                    if (locale && xkeymap_from_locale(locale))
892                    {
893                            fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
894                    }
895                    else
896                    {
897                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
898                    }
899            }
900            if (locale)
901                    xfree(locale);
902    
903    
904          STATUS("Connection successful.\n");          if (prompt_password && read_password(password, sizeof(password)))
905                    flags |= RDP_LOGON_AUTO;
906    
907          snprintf(title, sizeof(title), "rdesktop - %s", server);          if (g_title[0] == 0)
         if (ui_create_window(title))  
908          {          {
909                  rdp_main_loop();                  strcpy(g_title, "rdesktop - ");
910                  ui_destroy_window();                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
911          }          }
912    
913          rdp_disconnect();  #ifdef RDP2VNC
914            rdp2vnc_connect(server, flags, domain, password, shell, directory);
915          return 0;          return 0;
916    #else
917    
918            if (!ui_init())
919                    return 1;
920    
921    #ifdef WITH_RDPSND
922            if (g_rdpsnd)
923                    rdpsnd_init();
924    #endif
925    
926            if (lspci_enabled)
927                    lspci_init();
928    
929            rdpdr_init();
930    
931            while (run_count < 2 && continue_connect)       /* add support for Session Directory; only reconnect once */
932            {
933                    if (run_count == 0)
934                    {
935                            if (!rdp_connect(server, flags, domain, password, shell, directory))
936                                    return 1;
937                    }
938                    else if (!rdp_reconnect
939                             (server, flags, domain, password, shell, directory, g_redirect_cookie))
940                            return 1;
941    
942                    /* By setting encryption to False here, we have an encrypted login
943                       packet but unencrypted transfer of other packets */
944                    if (!packet_encryption)
945                            g_encryption = False;
946    
947    
948                    DEBUG(("Connection successful.\n"));
949                    memset(password, 0, sizeof(password));
950    
951                    if (run_count == 0)
952                            if (!ui_create_window())
953                                    continue_connect = False;
954    
955                    if (continue_connect)
956                            rdp_main_loop(&deactivated, &ext_disc_reason);
957    
958                    DEBUG(("Disconnecting...\n"));
959                    rdp_disconnect();
960    
961                    if ((g_redirect == True) && (run_count == 0))   /* Support for Session Directory */
962                    {
963                            /* reset state of major globals */
964                            rdesktop_reset_state();
965    
966                            STRNCPY(domain, g_redirect_domain, sizeof(domain));
967                            STRNCPY(g_username, g_redirect_username, sizeof(g_username));
968                            STRNCPY(password, g_redirect_password, sizeof(password));
969                            STRNCPY(server, g_redirect_server, sizeof(server));
970                            flags |= RDP_LOGON_AUTO;
971    
972                            g_redirect = False;
973                    }
974                    else
975                    {
976                            continue_connect = False;
977                            ui_destroy_window();
978                            break;
979                    }
980    
981                    run_count++;
982            }
983    
984            cache_save_state();
985            ui_deinit();
986    
987            if (ext_disc_reason >= 2)
988                    print_disconnect_reason(ext_disc_reason);
989    
990            if (deactivated)
991            {
992                    /* clean disconnect */
993                    return 0;
994            }
995            else
996            {
997                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
998                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
999                    {
1000                            /* not so clean disconnect, but nothing to worry about */
1001                            return 0;
1002                    }
1003                    else
1004                    {
1005                            /* return error */
1006                            return 2;
1007                    }
1008            }
1009    
1010    #endif
1011    
1012  }  }
1013    
1014  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
1015  void generate_random(uint8 *random)  /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
1016    static BOOL
1017    generate_random_egd(uint8 * buf)
1018  {  {
1019          struct stat st;          struct sockaddr_un addr;
1020          uint32 *r = (uint32 *)random;          BOOL ret = False;
1021          int fd;          int fd;
1022    
1023          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
1024          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (fd == -1)
1025                    return False;
1026    
1027            addr.sun_family = AF_UNIX;
1028            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
1029            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
1030                    goto err;
1031    
1032            /* PRNGD and EGD use a simple communications protocol */
1033            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
1034            buf[1] = 32;            /* Number of requested random bytes */
1035            if (write(fd, buf, 2) != 2)
1036                    goto err;
1037    
1038            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
1039                    goto err;
1040    
1041            if (read(fd, buf, 32) != 32)
1042                    goto err;
1043    
1044            ret = True;
1045    
1046          err:
1047            close(fd);
1048            return ret;
1049    }
1050    #endif
1051    
1052    /* Generate a 32-byte random for the secure transport code. */
1053    void
1054    generate_random(uint8 * random)
1055    {
1056            struct stat st;
1057            struct tms tmsbuf;
1058            MD5_CTX md5;
1059            uint32 *r;
1060            int fd, n;
1061    
1062            /* If we have a kernel random device, try that first */
1063            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
1064                || ((fd = open("/dev/random", O_RDONLY)) != -1))
1065          {          {
1066                  read(fd, random, 32);                  n = read(fd, random, 32);
1067                  close(fd);                  close(fd);
1068                  return;                  if (n == 32)
1069                            return;
1070          }          }
1071    
1072    #ifdef EGD_SOCKET
1073            /* As a second preference use an EGD */
1074            if (generate_random_egd(random))
1075                    return;
1076    #endif
1077    
1078          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
1079            r = (uint32 *) random;
1080          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
1081          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
1082          r[2] = times(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
1083          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
1084          stat("/tmp", &st);          stat("/tmp", &st);
1085          r[5] = st.st_atime;          r[5] = st.st_atime;
1086          r[6] = st.st_mtime;          r[6] = st.st_mtime;
1087          r[7] = st.st_ctime;          r[7] = st.st_ctime;
1088    
1089            /* Hash both halves with MD5 to obscure possible patterns */
1090            MD5_Init(&md5);
1091            MD5_Update(&md5, random, 16);
1092            MD5_Final(random, &md5);
1093            MD5_Update(&md5, random + 16, 16);
1094            MD5_Final(random + 16, &md5);
1095  }  }
1096    
1097  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
1098  void *xmalloc(int size)  void *
1099    xmalloc(int size)
1100  {  {
1101          void *mem = malloc(size);          void *mem = malloc(size);
1102          if (mem == NULL)          if (mem == NULL)
1103          {          {
1104                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
1105                    exit(1);
1106            }
1107            return mem;
1108    }
1109    
1110    /* strdup */
1111    char *
1112    xstrdup(const char *s)
1113    {
1114            char *mem = strdup(s);
1115            if (mem == NULL)
1116            {
1117                    perror("strdup");
1118                  exit(1);                  exit(1);
1119          }          }
1120          return mem;          return mem;
1121  }  }
1122    
1123  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1124  void *xrealloc(void *oldmem, int size)  void *
1125    xrealloc(void *oldmem, int size)
1126  {  {
1127          void *mem = realloc(oldmem, size);          void *mem;
1128    
1129            if (size < 1)
1130                    size = 1;
1131            mem = realloc(oldmem, size);
1132          if (mem == NULL)          if (mem == NULL)
1133          {          {
1134                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
1135                  exit(1);                  exit(1);
1136          }          }
1137          return mem;          return mem;
1138  }  }
1139    
1140  /* free */  /* free */
1141  void xfree(void *mem)  void
1142    xfree(void *mem)
1143  {  {
1144          free(mem);          free(mem);
1145  }  }
1146    
1147  /* Produce a hex dump */  /* report an error */
1148  void hexdump(unsigned char *p, unsigned int len)  void
1149    error(char *format, ...)
1150    {
1151            va_list ap;
1152    
1153            fprintf(stderr, "ERROR: ");
1154    
1155            va_start(ap, format);
1156            vfprintf(stderr, format, ap);
1157            va_end(ap);
1158    }
1159    
1160    /* report a warning */
1161    void
1162    warning(char *format, ...)
1163    {
1164            va_list ap;
1165    
1166            fprintf(stderr, "WARNING: ");
1167    
1168            va_start(ap, format);
1169            vfprintf(stderr, format, ap);
1170            va_end(ap);
1171    }
1172    
1173    /* report an unimplemented protocol feature */
1174    void
1175    unimpl(char *format, ...)
1176    {
1177            va_list ap;
1178    
1179            fprintf(stderr, "NOT IMPLEMENTED: ");
1180    
1181            va_start(ap, format);
1182            vfprintf(stderr, format, ap);
1183            va_end(ap);
1184    }
1185    
1186    /* produce a hex dump */
1187    void
1188    hexdump(unsigned char *p, unsigned int len)
1189  {  {
1190          unsigned char *line = p;          unsigned char *line = p;
1191          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
1192    
1193          while (offset < len)          while (offset < len)
1194          {          {
1195                  STATUS("%04x ", offset);                  printf("%04x ", offset);
1196                  thisline = len - offset;                  thisline = len - offset;
1197                  if (thisline > 16)                  if (thisline > 16)
1198                          thisline = 16;                          thisline = 16;
1199    
1200                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1201                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
1202    
1203                  for (; i < 16; i++)                  for (; i < 16; i++)
1204                          STATUS("   ");                          printf("   ");
1205    
1206                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1207                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1208    
1209                  STATUS("\n");                  printf("\n");
1210                  offset += thisline;                  offset += thisline;
1211                  line += thisline;                  line += thisline;
1212          }          }
1213  }  }
1214    
1215    /*
1216      input: src is the string we look in for needle.
1217             Needle may be escaped by a backslash, in
1218             that case we ignore that particular needle.
1219      return value: returns next src pointer, for
1220            succesive executions, like in a while loop
1221            if retval is 0, then there are no more args.
1222      pitfalls:
1223            src is modified. 0x00 chars are inserted to
1224            terminate strings.
1225            return val, points on the next val chr after ins
1226            0x00
1227    
1228            example usage:
1229            while( (pos = next_arg( optarg, ',')) ){
1230                    printf("%s\n",optarg);
1231                    optarg=pos;
1232            }
1233    
1234    */
1235    char *
1236    next_arg(char *src, char needle)
1237    {
1238            char *nextval;
1239            char *p;
1240            char *mvp = 0;
1241    
1242            /* EOS */
1243            if (*src == (char) 0x00)
1244                    return 0;
1245    
1246            p = src;
1247            /*  skip escaped needles */
1248            while ((nextval = strchr(p, needle)))
1249            {
1250                    mvp = nextval - 1;
1251                    /* found backslashed needle */
1252                    if (*mvp == '\\' && (mvp > src))
1253                    {
1254                            /* move string one to the left */
1255                            while (*(mvp + 1) != (char) 0x00)
1256                            {
1257                                    *mvp = *(mvp + 1);
1258                                    mvp++;
1259                            }
1260                            *mvp = (char) 0x00;
1261                            p = nextval;
1262                    }
1263                    else
1264                    {
1265                            p = nextval + 1;
1266                            break;
1267                    }
1268    
1269            }
1270    
1271            /* more args available */
1272            if (nextval)
1273            {
1274                    *nextval = (char) 0x00;
1275                    return ++nextval;
1276            }
1277    
1278            /* no more args after this, jump to EOS */
1279            nextval = src + strlen(src);
1280            return nextval;
1281    }
1282    
1283    
1284    void
1285    toupper_str(char *p)
1286    {
1287            while (*p)
1288            {
1289                    if ((*p >= 'a') && (*p <= 'z'))
1290                            *p = toupper((int) *p);
1291                    p++;
1292            }
1293    }
1294    
1295    
1296    BOOL
1297    str_startswith(const char *s, const char *prefix)
1298    {
1299            return (strncmp(s, prefix, strlen(prefix)) == 0);
1300    }
1301    
1302    
1303    /* Split input into lines, and call linehandler for each
1304       line. Incomplete lines are saved in the rest variable, which should
1305       initially point to NULL. When linehandler returns False, stop and
1306       return False. Otherwise, return True.  */
1307    BOOL
1308    str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1309    {
1310            char *buf, *p;
1311            char *oldrest;
1312            size_t inputlen;
1313            size_t buflen;
1314            size_t restlen = 0;
1315            BOOL ret = True;
1316    
1317            /* Copy data to buffer */
1318            inputlen = strlen(input);
1319            if (*rest)
1320                    restlen = strlen(*rest);
1321            buflen = restlen + inputlen + 1;
1322            buf = (char *) xmalloc(buflen);
1323            buf[0] = '\0';
1324            if (*rest)
1325                    STRNCPY(buf, *rest, buflen);
1326            strncat(buf, input, inputlen);
1327            p = buf;
1328    
1329            while (1)
1330            {
1331                    char *newline = strchr(p, '\n');
1332                    if (newline)
1333                    {
1334                            *newline = '\0';
1335                            if (!linehandler(p, data))
1336                            {
1337                                    p = newline + 1;
1338                                    ret = False;
1339                                    break;
1340                            }
1341                            p = newline + 1;
1342                    }
1343                    else
1344                    {
1345                            break;
1346    
1347                    }
1348            }
1349    
1350            /* Save in rest */
1351            oldrest = *rest;
1352            restlen = buf + buflen - p;
1353            *rest = (char *) xmalloc(restlen);
1354            STRNCPY((*rest), p, restlen);
1355            xfree(oldrest);
1356    
1357            xfree(buf);
1358            return ret;
1359    }
1360    
1361    /* Execute the program specified by argv. For each line in
1362       stdout/stderr output, call linehandler. Returns false on failure. */
1363    BOOL
1364    subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1365    {
1366            pid_t child;
1367            int fd[2];
1368            int n = 1;
1369            char output[256];
1370            char *rest = NULL;
1371    
1372            if (pipe(fd) < 0)
1373            {
1374                    perror("pipe");
1375                    return False;
1376            }
1377    
1378            if ((child = fork()) < 0)
1379            {
1380                    perror("fork");
1381                    return False;
1382            }
1383    
1384            /* Child */
1385            if (child == 0)
1386            {
1387                    /* Close read end */
1388                    close(fd[0]);
1389    
1390                    /* Redirect stdout and stderr to pipe */
1391                    dup2(fd[1], 1);
1392                    dup2(fd[1], 2);
1393    
1394                    /* Execute */
1395                    execvp(argv[0], argv);
1396                    perror("Error executing child");
1397                    _exit(128);
1398            }
1399    
1400            /* Parent. Close write end. */
1401            close(fd[1]);
1402            while (n > 0)
1403            {
1404                    n = read(fd[0], output, 255);
1405                    output[n] = '\0';
1406                    str_handle_lines(output, &rest, linehandler, data);
1407            }
1408            xfree(rest);
1409    
1410            return True;
1411    }
1412    
1413    
1414    /* not all clibs got ltoa */
1415    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1416    
1417    char *
1418    l_to_a(long N, int base)
1419    {
1420            static char ret[LTOA_BUFSIZE];
1421    
1422            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1423    
1424            register int divrem;
1425    
1426            if (base < 36 || 2 > base)
1427                    base = 10;
1428    
1429            if (N < 0)
1430            {
1431                    *head++ = '-';
1432                    N = -N;
1433            }
1434    
1435            tail = buf + sizeof(buf);
1436            *--tail = 0;
1437    
1438            do
1439            {
1440                    divrem = N % base;
1441                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1442                    N /= base;
1443            }
1444            while (N);
1445    
1446            strcpy(head, tail);
1447            return ret;
1448    }
1449    
1450    
1451    int
1452    load_licence(unsigned char **data)
1453    {
1454            char *home, *path;
1455            struct stat st;
1456            int fd, length;
1457    
1458            home = getenv("HOME");
1459            if (home == NULL)
1460                    return -1;
1461    
1462            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1463            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1464    
1465            fd = open(path, O_RDONLY);
1466            if (fd == -1)
1467                    return -1;
1468    
1469            if (fstat(fd, &st))
1470                    return -1;
1471    
1472            *data = (uint8 *) xmalloc(st.st_size);
1473            length = read(fd, *data, st.st_size);
1474            close(fd);
1475            xfree(path);
1476            return length;
1477    }
1478    
1479    void
1480    save_licence(unsigned char *data, int length)
1481    {
1482            char *home, *path, *tmppath;
1483            int fd;
1484    
1485            home = getenv("HOME");
1486            if (home == NULL)
1487                    return;
1488    
1489            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1490    
1491            sprintf(path, "%s/.rdesktop", home);
1492            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1493            {
1494                    perror(path);
1495                    return;
1496            }
1497    
1498            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1499    
1500            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1501            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1502            strcpy(tmppath, path);
1503            strcat(tmppath, ".new");
1504    
1505            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1506            if (fd == -1)
1507            {
1508                    perror(tmppath);
1509                    return;
1510            }
1511    
1512            if (write(fd, data, length) != length)
1513            {
1514                    perror(tmppath);
1515                    unlink(tmppath);
1516            }
1517            else if (rename(tmppath, path) == -1)
1518            {
1519                    perror(path);
1520                    unlink(tmppath);
1521            }
1522    
1523            close(fd);
1524            xfree(tmppath);
1525            xfree(path);
1526    }
1527    
1528    /* Create the bitmap cache directory */
1529    BOOL
1530    rd_pstcache_mkdir(void)
1531    {
1532            char *home;
1533            char bmpcache_dir[256];
1534    
1535            home = getenv("HOME");
1536    
1537            if (home == NULL)
1538                    return False;
1539    
1540            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1541    
1542            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1543            {
1544                    perror(bmpcache_dir);
1545                    return False;
1546            }
1547    
1548            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1549    
1550            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1551            {
1552                    perror(bmpcache_dir);
1553                    return False;
1554            }
1555    
1556            return True;
1557    }
1558    
1559    /* open a file in the .rdesktop directory */
1560    int
1561    rd_open_file(char *filename)
1562    {
1563            char *home;
1564            char fn[256];
1565            int fd;
1566    
1567            home = getenv("HOME");
1568            if (home == NULL)
1569                    return -1;
1570            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1571            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1572            if (fd == -1)
1573                    perror(fn);
1574            return fd;
1575    }
1576    
1577    /* close file */
1578    void
1579    rd_close_file(int fd)
1580    {
1581            close(fd);
1582    }
1583    
1584    /* read from file*/
1585    int
1586    rd_read_file(int fd, void *ptr, int len)
1587    {
1588            return read(fd, ptr, len);
1589    }
1590    
1591    /* write to file */
1592    int
1593    rd_write_file(int fd, void *ptr, int len)
1594    {
1595            return write(fd, ptr, len);
1596    }
1597    
1598    /* move file pointer */
1599    int
1600    rd_lseek_file(int fd, int offset)
1601    {
1602            return lseek(fd, offset, SEEK_SET);
1603    }
1604    
1605    /* do a write lock on a file */
1606    BOOL
1607    rd_lock_file(int fd, int start, int len)
1608    {
1609            struct flock lock;
1610    
1611            lock.l_type = F_WRLCK;
1612            lock.l_whence = SEEK_SET;
1613            lock.l_start = start;
1614            lock.l_len = len;
1615            if (fcntl(fd, F_SETLK, &lock) == -1)
1616                    return False;
1617            return True;
1618    }

Legend:
Removed from v.10  
changed lines
  Added in v.1271

  ViewVC Help
Powered by ViewVC 1.1.26