/[rdesktop]/sourceforge.net/trunk/rdesktop/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 /sourceforge.net/trunk/rdesktop/rdesktop.c

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

revision 76 by astrand, Mon Jul 29 20:16:22 2002 UTC revision 474 by matthewc, Tue Sep 30 09:11:08 2003 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-2003
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 <errno.h>
30  #include "rdesktop.h"  #include "rdesktop.h"
31    
32  char username[16];  #ifdef EGD_SOCKET
33    #include <sys/socket.h>         /* socket connect */
34    #include <sys/un.h>             /* sockaddr_un */
35    #endif
36    
37    #ifdef WITH_OPENSSL
38    #include <openssl/md5.h>
39    #else
40    #include "crypto/md5.h"
41    #endif
42    
43    char g_title[32] = "";
44    char g_username[16];
45  char hostname[16];  char hostname[16];
46  char keymapname[16];  char keymapname[16];
47  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
48  int width;  int g_width = 800;              /* If width or height are reset to zero, the geometry will
49  int height;                                     be fetched from _NET_WORKAREA */
50    int g_height = 600;
51  int tcp_port_rdp = TCP_PORT_RDP;  int tcp_port_rdp = TCP_PORT_RDP;
52  BOOL bitmap_compression = True;  int g_server_bpp = 8;
53  BOOL sendmotion = True;  int g_win_button_size = 0;      /* If zero, disable single app mode */
54  BOOL orders = True;  BOOL g_bitmap_compression = True;
55  BOOL licence = True;  BOOL g_sendmotion = True;
56  BOOL encryption = True;  BOOL g_orders = True;
57  BOOL desktop_save = True;  BOOL g_encryption = True;
58  BOOL fullscreen = False;  BOOL packet_encryption = True;
59  BOOL grab_keyboard = True;  BOOL g_desktop_save = True;
60    BOOL g_fullscreen = False;
61    BOOL g_grab_keyboard = True;
62    BOOL g_hide_decorations = False;
63    BOOL g_use_rdp5 = True;
64    extern BOOL g_owncolmap;
65    
66    #ifdef RDP2VNC
67    extern int rfb_port;
68    extern int defer_time;
69    void
70    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
71                    char *shell, char *directory);
72    #endif
73  /* Display usage information */  /* Display usage information */
74  static void  static void
75  usage(char *program)  usage(char *program)
76  {  {
77          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
78          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
79          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
80          printf("   -s: shell\n");  
81          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
82          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
83          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
84          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
85          printf("   -g: desktop geometry (WxH)\n");  #endif
86          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
87          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
88          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
89          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -S: caption button size (single application mode)\n");
90          printf("   -l: do not request licence\n");          fprintf(stderr, "   -c: working directory\n");
91          printf("   -t: rdp tcp port\n\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
92          printf("   -K: keep window manager key bindings\n");          fprintf(stderr, "   -n: client hostname\n");
93            fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
94            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
95            fprintf(stderr, "   -f: full-screen mode\n");
96            fprintf(stderr, "   -b: force bitmap updates\n");
97            fprintf(stderr, "   -e: disable encryption (French TS)\n");
98            fprintf(stderr, "   -E: disable encryption from client to server\n");
99            fprintf(stderr, "   -m: do not send motion events\n");
100            fprintf(stderr, "   -C: use private colour map\n");
101            fprintf(stderr, "   -K: keep window manager key bindings\n");
102            fprintf(stderr, "   -T: window title\n");
103            fprintf(stderr, "   -D: hide window manager decorations\n");
104            fprintf(stderr, "   -a: server bpp\n");
105            fprintf(stderr, "   -4: Use RDP version 4\n");
106            fprintf(stderr, "   -5: Use RDP version 5 (default)\n");
107    }
108    
109    static BOOL
110    read_password(char *password, int size)
111    {
112            struct termios tios;
113            BOOL ret = False;
114            int istty = 0;
115            char *p;
116    
117            if (tcgetattr(STDIN_FILENO, &tios) == 0)
118            {
119                    fprintf(stderr, "Password: ");
120                    tios.c_lflag &= ~ECHO;
121                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
122                    istty = 1;
123            }
124    
125            if (fgets(password, size, stdin) != NULL)
126            {
127                    ret = True;
128    
129                    /* strip final newline */
130                    p = strchr(password, '\n');
131                    if (p != NULL)
132                            *p = 0;
133            }
134    
135            if (istty)
136            {
137                    tios.c_lflag |= ECHO;
138                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
139                    fprintf(stderr, "\n");
140            }
141    
142            return ret;
143    }
144    
145    static void
146    parse_server_and_port(char *server)
147    {
148            char *p;
149    #ifdef IPv6
150            int addr_colons;
151    #endif
152    
153    #ifdef IPv6
154            p = server;
155            addr_colons = 0;
156            while (*p)
157                    if (*p++ == ':')
158                            addr_colons++;
159            if (addr_colons >= 2)
160            {
161                    /* numeric IPv6 style address format - [1:2:3::4]:port */
162                    p = strchr(server, ']');
163                    if (*server == '[' && p != NULL)
164                    {
165                            if (*(p + 1) == ':' && *(p + 2) != '\0')
166                                    tcp_port_rdp = strtol(p + 2, NULL, 10);
167                            /* remove the port number and brackets from the address */
168                            *p = '\0';
169                            strncpy(server, server + 1, strlen(server));
170                    }
171            }
172            else
173            {
174                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
175                    p = strchr(server, ':');
176                    if (p != NULL)
177                    {
178                            tcp_port_rdp = strtol(p + 1, NULL, 10);
179                            *p = 0;
180                    }
181            }
182    #else /* no IPv6 support */
183            p = strchr(server, ':');
184            if (p != NULL)
185            {
186                    tcp_port_rdp = strtol(p + 1, NULL, 10);
187                    *p = 0;
188            }
189    #endif /* IPv6 */
190    
191  }  }
192    
193  /* Client program */  /* Client program */
194  int  int
195  main(int argc, char *argv[])  main(int argc, char *argv[])
196  {  {
197            char server[64];
198          char fullhostname[64];          char fullhostname[64];
199          char domain[16];          char domain[16];
200          char password[16];          char password[16];
201          char shell[32];          char shell[128];
202          char directory[32];          char directory[32];
203          char title[32];          BOOL prompt_password, rdp_retval = False;
204          struct passwd *pw;          struct passwd *pw;
         char *server, *p;  
205          uint32 flags;          uint32 flags;
206            char *p;
207          int c;          int c;
208            int username_option = 0;
         printf("rdesktop: A Remote Desktop Protocol client.\n");  
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("See http://www.rdesktop.org/ for more information.\n\n");  
209    
210          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
211            prompt_password = False;
212          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
213          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
214    
215          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -1)  #ifdef RDP2VNC
216    #define VNCOPT "V:Q:"
217    #else
218    #define VNCOPT
219    #endif
220    
221            while ((c = getopt(argc, argv, VNCOPT "u:d:s:S:c:p:n:k:g:a:fbeEmCKT:Dh?54")) != -1)
222          {          {
223                  switch (c)                  switch (c)
224                  {                  {
225    #ifdef RDP2VNC
226                            case 'V':
227                                    rfb_port = strtol(optarg, NULL, 10);
228                                    if (rfb_port < 100)
229                                            rfb_port += 5900;
230                                    break;
231    
232                            case 'Q':
233                                    defer_time = strtol(optarg, NULL, 10);
234                                    if (defer_time < 0)
235                                            defer_time = 0;
236                                    break;
237    #endif
238    
239                          case 'u':                          case 'u':
240                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
241                                    username_option = 1;
242                                  break;                                  break;
243    
244                          case 'd':                          case 'd':
# Line 107  main(int argc, char *argv[]) Line 249  main(int argc, char *argv[])
249                                  STRNCPY(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
250                                  break;                                  break;
251    
252                            case 'S':
253                                    if (!strcmp(optarg, "standard"))
254                                    {
255                                            g_win_button_size = 18;
256                                            break;
257                                    }
258    
259                                    g_win_button_size = strtol(optarg, &p, 10);
260    
261                                    if (*p)
262                                    {
263                                            error("invalid button size\n");
264                                            return 1;
265                                    }
266    
267                                    break;
268    
269                          case 'c':                          case 'c':
270                                  STRNCPY(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
271                                  break;                                  break;
272    
273                          case 'p':                          case 'p':
274                                    if ((optarg[0] == '-') && (optarg[1] == 0))
275                                    {
276                                            prompt_password = True;
277                                            break;
278                                    }
279    
280                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
281                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
282    
283                                    /* try to overwrite argument so it won't appear in ps */
284                                    p = optarg;
285                                    while (*p)
286                                            *(p++) = 'X';
287                                  break;                                  break;
288    
289                          case 'n':                          case 'n':
# Line 121  main(int argc, char *argv[]) Line 291  main(int argc, char *argv[])
291                                  break;                                  break;
292    
293                          case 'k':                          case 'k':
294                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
295                                  break;                                  break;
296    
297                          case 'g':                          case 'g':
298                                  width = strtol(optarg, &p, 10);                                  if (!strcmp(optarg, "workarea"))
299                                    {
300                                            g_width = g_height = 0;
301                                            break;
302                                    }
303    
304                                    g_width = strtol(optarg, &p, 10);
305                                  if (*p == 'x')                                  if (*p == 'x')
306                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, NULL, 10);
307    
308                                  if ((width == 0) || (height == 0))                                  if ((g_width == 0) || (g_height == 0))
309                                  {                                  {
310                                          error("invalid geometry\n");                                          error("invalid geometry\n");
311                                          return 1;                                          return 1;
# Line 138  main(int argc, char *argv[]) Line 313  main(int argc, char *argv[])
313                                  break;                                  break;
314    
315                          case 'f':                          case 'f':
316                                  fullscreen = True;                                  g_fullscreen = True;
317                                  break;                                  break;
318    
319                          case 'b':                          case 'b':
320                                  orders = False;                                  g_orders = False;
321                                  break;                                  break;
322    
323                          case 'e':                          case 'e':
324                                  encryption = False;                                  g_encryption = False;
325                                    break;
326                            case 'E':
327                                    packet_encryption = False;
328                                  break;                                  break;
   
329                          case 'm':                          case 'm':
330                                  sendmotion = False;                                  g_sendmotion = False;
331                                  break;                                  break;
332    
333                          case 'l':                          case 'C':
334                                  licence = False;                                  g_owncolmap = True;
335                                  break;                                  break;
336    
337                          case 't':                          case 'K':
338                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_grab_keyboard = False;
339                                  break;                                  break;
340    
341                          case 'K':                          case 'T':
342                                  grab_keyboard = False;                                  STRNCPY(g_title, optarg, sizeof(g_title));
343                                    break;
344    
345                            case 'D':
346                                    g_hide_decorations = True;
347                                    break;
348    
349                            case 'a':
350                                    g_server_bpp = strtol(optarg, NULL, 10);
351                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
352                                        && g_server_bpp != 24)
353                                    {
354                                            error("invalid server bpp\n");
355                                            return 1;
356                                    }
357                                    break;
358    
359                            case '4':
360                                    g_use_rdp5 = False;
361                                    break;
362    
363                            case '5':
364                                    g_use_rdp5 = True;
365                                  break;                                  break;
366    
367                          case 'h':                          case 'h':
# Line 179  main(int argc, char *argv[]) Line 378  main(int argc, char *argv[])
378                  return 1;                  return 1;
379          }          }
380    
381          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
382            parse_server_and_port(server);
383    
384          if (username[0] == 0)          if (!username_option)
385          {          {
386                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
387                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 190  main(int argc, char *argv[]) Line 390  main(int argc, char *argv[])
390                          return 1;                          return 1;
391                  }                  }
392    
393                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
394          }          }
395    
396          if (hostname[0] == 0)          if (hostname[0] == 0)
# Line 208  main(int argc, char *argv[]) Line 408  main(int argc, char *argv[])
408                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
409          }          }
410    
411          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
412          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
413    
414          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
415          {          {
416                  width = 800;                  strcpy(g_title, "rdesktop - ");
417                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
418          }          }
419    
420          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
421          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
422            return 0;
423    #else
424    
425            if (!ui_init())
426                    return 1;
427    
428          xkeymap_init1();  #ifdef WITH_RDPSND
429            rdpsnd_init();
430    #endif
431            /* rdpdr_init(); */
432    
433          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
434                  return 1;                  return 1;
435    
436          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
437               packet but unencrypted transfer of other packets */
438            if (!packet_encryption)
439                    g_encryption = False;
440    
441    
442          if (ui_create_window(title))          DEBUG(("Connection successful.\n"));
443            memset(password, 0, sizeof(password));
444    
445            if (ui_create_window())
446          {          {
447                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
448                  ui_destroy_window();                  ui_destroy_window();
449          }          }
450    
451          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
452          rdp_disconnect();          rdp_disconnect();
453          return 0;          ui_deinit();
454    
455            if (True == rdp_retval)
456                    return 0;
457            else
458                    return 2;
459    
460    #endif
461    
462    }
463    
464    #ifdef EGD_SOCKET
465    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
466    static BOOL
467    generate_random_egd(uint8 * buf)
468    {
469            struct sockaddr_un addr;
470            BOOL ret = False;
471            int fd;
472    
473            fd = socket(AF_UNIX, SOCK_STREAM, 0);
474            if (fd == -1)
475                    return False;
476    
477            addr.sun_family = AF_UNIX;
478            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
479            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
480                    goto err;
481    
482            /* PRNGD and EGD use a simple communications protocol */
483            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
484            buf[1] = 32;            /* Number of requested random bytes */
485            if (write(fd, buf, 2) != 2)
486                    goto err;
487    
488            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
489                    goto err;
490    
491            if (read(fd, buf, 32) != 32)
492                    goto err;
493    
494            ret = True;
495    
496          err:
497            close(fd);
498            return ret;
499  }  }
500    #endif
501    
502  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
503  void  void
# Line 252  generate_random(uint8 * random) Line 505  generate_random(uint8 * random)
505  {  {
506          struct stat st;          struct stat st;
507          struct tms tmsbuf;          struct tms tmsbuf;
508          uint32 *r = (uint32 *) random;          MD5_CTX md5;
509          int fd;          uint32 *r;
510            int fd, n;
511    
512          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
513          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
514              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
515          {          {
516                  read(fd, random, 32);                  n = read(fd, random, 32);
517                  close(fd);                  close(fd);
518                  return;                  if (n == 32)
519                            return;
520          }          }
521    
522    #ifdef EGD_SOCKET
523            /* As a second preference use an EGD */
524            if (generate_random_egd(random))
525                    return;
526    #endif
527    
528          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
529            r = (uint32 *) random;
530          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
531          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
532          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 535  generate_random(uint8 * random)
535          r[5] = st.st_atime;          r[5] = st.st_atime;
536          r[6] = st.st_mtime;          r[6] = st.st_mtime;
537          r[7] = st.st_ctime;          r[7] = st.st_ctime;
538    
539            /* Hash both halves with MD5 to obscure possible patterns */
540            MD5_Init(&md5);
541            MD5_Update(&md5, random, 16);
542            MD5_Final(random, &md5);
543            MD5_Update(&md5, random + 16, 16);
544            MD5_Final(random + 16, &md5);
545  }  }
546    
547  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 321  error(char *format, ...) Line 590  error(char *format, ...)
590          va_end(ap);          va_end(ap);
591  }  }
592    
593    /* report a warning */
594    void
595    warning(char *format, ...)
596    {
597            va_list ap;
598    
599            fprintf(stderr, "WARNING: ");
600    
601            va_start(ap, format);
602            vfprintf(stderr, format, ap);
603            va_end(ap);
604    }
605    
606  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
607  void  void
608  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 336  unimpl(char *format, ...) Line 618  unimpl(char *format, ...)
618    
619  /* produce a hex dump */  /* produce a hex dump */
620  void  void
621  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, int len)
622  {  {
623          unsigned char *line = p;          unsigned char *line = p;
624          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
625    
626          while (offset < len)          while (offset < len)
627          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 637  hexdump(unsigned char *p, unsigned int l
637                          printf("   ");                          printf("   ");
638    
639                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
640                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
641    
642                  printf("\n");                  printf("\n");
643                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 645  hexdump(unsigned char *p, unsigned int l
645          }          }
646  }  }
647    
648    
649  int  int
650  load_licence(unsigned char **data)  load_licence(unsigned char **data)
651  {  {
652          char path[PATH_MAX];          char *home, *path;
         char *home;  
653          struct stat st;          struct stat st;
654          int fd;          int fd, length;
655    
656          home = getenv("HOME");          home = getenv("HOME");
657          if (home == NULL)          if (home == NULL)
658                  return -1;                  return -1;
659    
660          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
661          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
662    
663          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
664          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 667  load_licence(unsigned char **data)
667          if (fstat(fd, &st))          if (fstat(fd, &st))
668                  return -1;                  return -1;
669    
670          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
671          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
672            close(fd);
673            xfree(path);
674            return length;
675  }  }
676    
677  void  void
678  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
679  {  {
680          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
681          int fd;          int fd;
682    
683          home = getenv("HOME");          home = getenv("HOME");
684          if (home == NULL)          if (home == NULL)
685                  return;                  return;
686    
687          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
         strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
         mkdir(path, 0700);  
688    
689          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop", home);
690            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
691            {
692                    perror(path);
693                    return;
694            }
695    
696          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
697    
698            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
699            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
700            strcpy(tmppath, path);
701            strcat(tmppath, ".new");
702    
703            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
704          if (fd == -1)          if (fd == -1)
705          {          {
706                  perror("open");                  perror(tmppath);
707                  return;                  return;
708          }          }
709    
710          write(fd, data, length);          if (write(fd, data, length) != length)
711            {
712                    perror(tmppath);
713                    unlink(tmppath);
714            }
715            else if (rename(tmppath, path) == -1)
716            {
717                    perror(path);
718                    unlink(tmppath);
719            }
720    
721          close(fd);          close(fd);
722            xfree(tmppath);
723            xfree(path);
724  }  }

Legend:
Removed from v.76  
changed lines
  Added in v.474

  ViewVC Help
Powered by ViewVC 1.1.26