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

Legend:
Removed from v.12  
changed lines
  Added in v.1391

  ViewVC Help
Powered by ViewVC 1.1.26