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

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

  ViewVC Help
Powered by ViewVC 1.1.26