/[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 29 by matty, Fri Sep 14 03:38:39 2001 UTC revision 427 by forsberg, Thu Jun 19 11:51:18 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-2000     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    
21  #include <stdlib.h>             /* malloc realloc free */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25    #include <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    #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 title[32] = "";
44  char username[16];  char username[16];
45  char hostname[16];  char hostname[16];
46  int width = 800;  char keymapname[16];
47    int keylayout = 0x409;          /* Defaults to US keyboard layout */
48    int width = 800;                /* If width or height are reset to zero, the geometry will
49                                       be fetched from _NET_WORKAREA */
50  int height = 600;  int height = 600;
51  int keylayout = 0x409;  int tcp_port_rdp = TCP_PORT_RDP;
52    int server_bpp = 8;
53    int win_button_size = 0;        /* If zero, disable single app mode */
54  BOOL bitmap_compression = True;  BOOL bitmap_compression = True;
55  BOOL sendmotion = True;  BOOL sendmotion = True;
56  BOOL orders = True;  BOOL orders = True;
57  BOOL licence = True;  BOOL encryption = True;
58  BOOL use_encryption = True;  BOOL packet_encryption = True;
59  BOOL desktop_save = True;  BOOL desktop_save = True;
60  BOOL fullscreen = False;  BOOL fullscreen = False;
61    BOOL grab_keyboard = True;
62    BOOL hide_decorations = False;
63    BOOL use_rdp5 = False;
64    extern BOOL 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          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
78          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
79          STATUS("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
80          STATUS("   -s: shell\n");  
81          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
82          STATUS("   -p: password (autologon)\n");  #ifdef RDP2VNC
83          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
84          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -E: defer time (ms)\n");
85          STATUS("   -h: desktop height\n");  #endif
86          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -u: user name\n");
87          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
88          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -s: shell\n");
89          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -S: caption button size (single application mode)\n");
90            fprintf(stderr, "   -c: working directory\n");
91            fprintf(stderr, "   -p: password (- to prompt)\n");
92            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 of everything but the logon packet\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, "   -5: Use RDP5 (EXPERIMENTAL!)\n");
106    }
107    
108    static BOOL
109    read_password(char *password, int size)
110    {
111            struct termios tios;
112            BOOL ret = False;
113            int istty = 0;
114            char *p;
115    
116            if (tcgetattr(STDIN_FILENO, &tios) == 0)
117            {
118                    fprintf(stderr, "Password: ");
119                    tios.c_lflag &= ~ECHO;
120                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
121                    istty = 1;
122            }
123    
124            if (fgets(password, size, stdin) != NULL)
125            {
126                    ret = True;
127    
128                    /* strip final newline */
129                    p = strchr(password, '\n');
130                    if (p != NULL)
131                            *p = 0;
132            }
133    
134            if (istty)
135            {
136                    tios.c_lflag |= ECHO;
137                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
138                    fprintf(stderr, "\n");
139            }
140    
141            return ret;
142  }  }
143    
144  /* Client program */  /* Client program */
145  int  int
146  main(int argc, char *argv[])  main(int argc, char *argv[])
147  {  {
148          struct passwd *pw;          char server[64];
149          char *server;          char fullhostname[64];
         uint32 flags;  
150          char domain[16];          char domain[16];
151          char password[16];          char password[16];
152          char shell[32];          char shell[128];
153          char directory[32];          char directory[32];
154          char title[32];          BOOL prompt_password, rdp_retval = False;
155            struct passwd *pw;
156            uint32 flags;
157            char *p;
158          int c;          int c;
159            int username_option = 0;
         STATUS("rdesktop: A Remote Desktop Protocol client.\n");  
         STATUS("Version " VERSION  
                ". Copyright (C) 1999-2000 Matt Chapman.\n");  
         STATUS("See http://www.rdesktop.org/ for more information.\n\n");  
160    
161          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
162            prompt_password = False;
163          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
164            strcpy(keymapname, "en-us");
165    
166          while ((c = getopt(argc, argv, "u:d:s:c:p:n:g:k:mbleKFVh?")) != -1)  #ifdef RDP2VNC
167    #define VNCOPT "V:E:"
168    #else
169    #define VNCOPT
170    #endif
171    
172            while ((c = getopt(argc, argv, VNCOPT "u:d:s:S:c:p:n:k:g:a:fbeEmCKT:Dh?54")) != -1)
173          {          {
174                  switch (c)                  switch (c)
175                  {                  {
176    #ifdef RDP2VNC
177                            case 'V':
178                                    rfb_port = strtol(optarg, NULL, 10);
179                                    if (rfb_port < 100)
180                                            rfb_port += 5900;
181                                    break;
182    
183                            case 'E':
184                                    defer_time = strtol(optarg, NULL, 10);
185                                    if (defer_time < 0)
186                                            defer_time = 0;
187                                    break;
188    #endif
189    
190                          case 'u':                          case 'u':
191                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(username, optarg, sizeof(username));
192                                    username_option = 1;
193                                  break;                                  break;
194    
195                          case 'd':                          case 'd':
196                                  strncpy(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
197                                  break;                                  break;
198    
199                          case 'p':                          case 's':
200                                  flags |= RDP_LOGON_AUTO;                                  STRNCPY(shell, optarg, sizeof(shell));
                                 strncpy(password, optarg, sizeof(password));  
201                                  break;                                  break;
202    
203                          case 's':                          case 'S':
204                                  strncpy(shell, optarg, sizeof(shell));                                  if (!strcmp(optarg, "standard"))
205                                    {
206                                            win_button_size = 18;
207                                            break;
208                                    }
209    
210                                    win_button_size = strtol(optarg, &p, 10);
211    
212                                    if (*p)
213                                    {
214                                            error("invalid button size\n");
215                                            return 1;
216                                    }
217    
218                                  break;                                  break;
219    
220                          case 'c':                          case 'c':
221                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
222                                    break;
223    
224                            case 'p':
225                                    if ((optarg[0] == '-') && (optarg[1] == 0))
226                                    {
227                                            prompt_password = True;
228                                            break;
229                                    }
230    
231                                    STRNCPY(password, optarg, sizeof(password));
232                                    flags |= RDP_LOGON_AUTO;
233    
234                                    /* try to overwrite argument so it won't appear in ps */
235                                    p = optarg;
236                                    while (*p)
237                                            *(p++) = 'X';
238                                  break;                                  break;
239    
240                          case 'n':                          case 'n':
241                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(hostname, optarg, sizeof(hostname));
242                                    break;
243    
244                            case 'k':
245                                    STRNCPY(keymapname, optarg, sizeof(keymapname));
246                                  break;                                  break;
247    
248                          case 'g':                          case 'g':
249                                    if (!strcmp(optarg, "workarea"))
250                                    {
251                                            width = height = 0;
252                                            break;
253                                    }
254    
255                                    width = strtol(optarg, &p, 10);
256                                    if (*p == 'x')
257                                            height = strtol(p + 1, NULL, 10);
258    
259                                    if ((width == 0) || (height == 0))
260                                  {                                  {
261                                          char *tgem = 0;                                          error("invalid geometry\n");
262                                          width = strtol(optarg, NULL, 10);                                          return 1;
                                         tgem = strchr(optarg, 'x');  
                                         if ((tgem == 0) || (strlen(tgem) < 2))  
                                         {  
                                                 ERROR  
                                                         ("-g: invalid parameter. Syntax example: -g 1024x768\n");  
                                                 exit(1);  
                                         }  
                                         height = strtol(tgem + 1, NULL, 10);  
263                                  }                                  }
264                                  break;                                  break;
265    
266                          case 'k':                          case 'f':
267                                  keylayout = strtol(optarg, NULL, 16);                                  fullscreen = True;
                                 /* keylayout = find_keyb_code(optarg); */  
                                 if (keylayout == 0)  
                                         return 0;  
268                                  break;                                  break;
269    
270                            case 'b':
271                                    orders = False;
272                                    break;
273    
274                            case 'e':
275                                    encryption = False;
276                                    break;
277                            case 'E':
278                                    packet_encryption = False;
279                                    break;
280                          case 'm':                          case 'm':
281                                  sendmotion = False;                                  sendmotion = False;
282                                  break;                                  break;
283    
284                          case 'b':                          case 'C':
285                                  orders = False;                                  owncolmap = True;
286                                  break;                                  break;
287    
288                          case 'l':                          case 'K':
289                                  licence = False;                                  grab_keyboard = False;
290                                  break;                                  break;
291    
292                          case 'e':                          case 'T':
293                                  use_encryption = False;                                  STRNCPY(title, optarg, sizeof(title));
294                                  break;                                  break;
295    
296                          case 'F':                          case 'D':
297                                  fullscreen = True;                                  hide_decorations = True;
298                                  break;                                  break;
299    
300                            case 'a':
301                                    server_bpp = strtol(optarg, NULL, 10);
302                                    if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15
303                                        && server_bpp != 24)
304                                    {
305                                            error("invalid server bpp\n");
306                                            return 1;
307                                    }
308                                    break;
309    
310                            case '5':
311                                    use_rdp5 = True;
312                                    break;
313                          case 'h':                          case 'h':
314                          case '?':                          case '?':
315                          default:                          default:
# Line 165  main(int argc, char *argv[]) Line 324  main(int argc, char *argv[])
324                  return 1;                  return 1;
325          }          }
326    
327          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
328            p = strchr(server, ':');
329            if (p != NULL)
330            {
331                    tcp_port_rdp = strtol(p + 1, NULL, 10);
332                    *p = 0;
333            }
334    
335          if (username[0] == 0)          if (!username_option)
336          {          {
337                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
338                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
339                  {                  {
340                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
341                          return 1;                          return 1;
342                  }                  }
343    
344                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(username, pw->pw_name, sizeof(username));
345          }          }
346    
347          if (hostname[0] == 0)          if (hostname[0] == 0)
348          {          {
349                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
350                  {                  {
351                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
352                          return 1;                          return 1;
353                  }                  }
354    
355                    p = strchr(fullhostname, '.');
356                    if (p != NULL)
357                            *p = 0;
358    
359                    STRNCPY(hostname, fullhostname, sizeof(hostname));
360          }          }
361    
362          strcpy(title, "rdesktop - ");          if (prompt_password && read_password(password, sizeof(password)))
363          strncat(title, server, sizeof(title));                  flags |= RDP_LOGON_AUTO;
364    
365          if (ui_create_window(title))          if (title[0] == 0)
366          {          {
367                  if (!rdp_connect(server, flags, domain, password, shell,                  strcpy(title, "rdesktop - ");
368                                   directory))                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
369                          return 1;          }
370    
371    #ifdef RDP2VNC
372            rdp2vnc_connect(server, flags, domain, password, shell, directory);
373            return 0;
374    #else
375    
376            if (!ui_init())
377                    return 1;
378    
379            ipc_init();             // Must be run after ui_init, we need X to be setup.
380    
381            if (use_rdp5)
382                    cliprdr_init(); // FIXME: Should perhaps be integrated into the channel management code?
383    
384            if (!rdp_connect(server, flags, domain, password, shell, directory))
385                    return 1;
386    
387                  STATUS("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
388                  rdp_main_loop();             packet but unencrypted transfer of other packets */
389            if (!packet_encryption)
390                    encryption = False;
391    
392    
393            DEBUG(("Connection successful.\n"));
394            memset(password, 0, sizeof(password));
395    
396            if (ui_create_window())
397            {
398                    rdp_retval = rdp_main_loop();
399                  ui_destroy_window();                  ui_destroy_window();
400          }          }
401    
402            DEBUG(("Disconnecting...\n"));
403          rdp_disconnect();          rdp_disconnect();
404          return 0;          ui_deinit();
405    
406            if (True == rdp_retval)
407                    return 0;
408            else
409                    return 2;
410    
411    #endif
412    
413    }
414    
415    #ifdef EGD_SOCKET
416    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
417    static BOOL
418    generate_random_egd(uint8 * buf)
419    {
420            struct sockaddr_un addr;
421            BOOL ret = False;
422            int fd;
423    
424            fd = socket(AF_UNIX, SOCK_STREAM, 0);
425            if (fd == -1)
426                    return False;
427    
428            addr.sun_family = AF_UNIX;
429            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
430            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
431                    goto err;
432    
433            /* PRNGD and EGD use a simple communications protocol */
434            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
435            buf[1] = 32;            /* Number of requested random bytes */
436            if (write(fd, buf, 2) != 2)
437                    goto err;
438    
439            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
440                    goto err;
441    
442            if (read(fd, buf, 32) != 32)
443                    goto err;
444    
445            ret = True;
446    
447          err:
448            close(fd);
449            return ret;
450  }  }
451    #endif
452    
453  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
454  void  void
455  generate_random(uint8 *random)  generate_random(uint8 * random)
456  {  {
457          struct stat st;          struct stat st;
458          struct tms tmsbuf;          struct tms tmsbuf;
459          uint32 *r = (uint32 *) random;          MD5_CTX md5;
460          int fd;          uint32 *r;
461            int fd, n;
462          /* If we have a kernel random device, use it. */  
463          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
464            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
465                || ((fd = open("/dev/random", O_RDONLY)) != -1))
466          {          {
467                  read(fd, random, 32);                  n = read(fd, random, 32);
468                  close(fd);                  close(fd);
469                  return;                  if (n == 32)
470                            return;
471          }          }
472    
473    #ifdef EGD_SOCKET
474            /* As a second preference use an EGD */
475            if (generate_random_egd(random))
476                    return;
477    #endif
478    
479          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
480            r = (uint32 *) random;
481          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
482          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
483          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 232  generate_random(uint8 *random) Line 486  generate_random(uint8 *random)
486          r[5] = st.st_atime;          r[5] = st.st_atime;
487          r[6] = st.st_mtime;          r[6] = st.st_mtime;
488          r[7] = st.st_ctime;          r[7] = st.st_ctime;
489    
490            /* Hash both halves with MD5 to obscure possible patterns */
491            MD5_Init(&md5);
492            MD5_Update(&md5, random, 16);
493            MD5_Final(random, &md5);
494            MD5_Update(&md5, random + 16, 16);
495            MD5_Final(random + 16, &md5);
496  }  }
497    
498  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 241  xmalloc(int size) Line 502  xmalloc(int size)
502          void *mem = malloc(size);          void *mem = malloc(size);
503          if (mem == NULL)          if (mem == NULL)
504          {          {
505                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
506                  exit(1);                  exit(1);
507          }          }
508          return mem;          return mem;
# Line 254  xrealloc(void *oldmem, int size) Line 515  xrealloc(void *oldmem, int size)
515          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
516          if (mem == NULL)          if (mem == NULL)
517          {          {
518                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
519                  exit(1);                  exit(1);
520          }          }
521          return mem;          return mem;
# Line 267  xfree(void *mem) Line 528  xfree(void *mem)
528          free(mem);          free(mem);
529  }  }
530    
531  /* Produce a hex dump */  /* report an error */
532    void
533    error(char *format, ...)
534    {
535            va_list ap;
536    
537            fprintf(stderr, "ERROR: ");
538    
539            va_start(ap, format);
540            vfprintf(stderr, format, ap);
541            va_end(ap);
542    }
543    
544    /* report a warning */
545  void  void
546  hexdump(unsigned char *p, unsigned int len)  warning(char *format, ...)
547    {
548            va_list ap;
549    
550            fprintf(stderr, "WARNING: ");
551    
552            va_start(ap, format);
553            vfprintf(stderr, format, ap);
554            va_end(ap);
555    }
556    
557    /* report an unimplemented protocol feature */
558    void
559    unimpl(char *format, ...)
560    {
561            va_list ap;
562    
563            fprintf(stderr, "NOT IMPLEMENTED: ");
564    
565            va_start(ap, format);
566            vfprintf(stderr, format, ap);
567            va_end(ap);
568    }
569    
570    /* produce a hex dump */
571    void
572    hexdump(unsigned char *p, int len)
573  {  {
574          unsigned char *line = p;          unsigned char *line = p;
575          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
576    
577          while (offset < len)          while (offset < len)
578          {          {
579                  STATUS("%04x ", offset);                  printf("%04x ", offset);
580                  thisline = len - offset;                  thisline = len - offset;
581                  if (thisline > 16)                  if (thisline > 16)
582                          thisline = 16;                          thisline = 16;
583    
584                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
585                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
586                                  STATUS("   ");  
587                    for (; i < 16; i++)
588                            printf("   ");
589    
590                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
591                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
592    
593                  STATUS("\n");                  printf("\n");
594                  offset += thisline;                  offset += thisline;
595                  line += thisline;                  line += thisline;
596          }          }
597  }  }
598    
599    
600    int
601    load_licence(unsigned char **data)
602    {
603            char *home, *path;
604            struct stat st;
605            int fd, length;
606    
607            home = getenv("HOME");
608            if (home == NULL)
609                    return -1;
610    
611            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
612            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
613    
614            fd = open(path, O_RDONLY);
615            if (fd == -1)
616                    return -1;
617    
618            if (fstat(fd, &st))
619                    return -1;
620    
621            *data = (uint8 *) xmalloc(st.st_size);
622            length = read(fd, *data, st.st_size);
623            close(fd);
624            xfree(path);
625            return length;
626    }
627    
628    void
629    save_licence(unsigned char *data, int length)
630    {
631            char *home, *path, *tmppath;
632            int fd;
633    
634            home = getenv("HOME");
635            if (home == NULL)
636                    return;
637    
638            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
639    
640            sprintf(path, "%s/.rdesktop", home);
641            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
642            {
643                    perror(path);
644                    return;
645            }
646    
647            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
648    
649            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
650            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
651            strcpy(tmppath, path);
652            strcat(tmppath, ".new");
653    
654            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
655            if (fd == -1)
656            {
657                    perror(tmppath);
658                    return;
659            }
660    
661            if (write(fd, data, length) != length)
662            {
663                    perror(tmppath);
664                    unlink(tmppath);
665            }
666            else if (rename(tmppath, path) == -1)
667            {
668                    perror(path);
669                    unlink(tmppath);
670            }
671    
672            close(fd);
673            xfree(tmppath);
674            xfree(path);
675    }

Legend:
Removed from v.29  
changed lines
  Added in v.427

  ViewVC Help
Powered by ViewVC 1.1.26