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

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

  ViewVC Help
Powered by ViewVC 1.1.26