/[rdesktop]/jpeg/rdesktop/trunk/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /jpeg/rdesktop/trunk/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

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

  ViewVC Help
Powered by ViewVC 1.1.26