/[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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26