/[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 21 by matty, Mon Oct 16 08:44:48 2000 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 <sys/stat.h>   /* stat */  #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/time.h>   /* gettimeofday */  #include <sys/stat.h>           /* stat */
27  #include <sys/times.h>  /* times */  #include <sys/time.h>           /* gettimeofday */
28    #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  BOOL motion = True;  int server_bpp = 8;
53    int win_button_size = 0;        /* If zero, disable single app mode */
54    BOOL bitmap_compression = True;
55    BOOL sendmotion = True;
56  BOOL orders = True;  BOOL orders = True;
57  BOOL licence = True;  BOOL encryption = True;
58    BOOL packet_encryption = True;
59    BOOL desktop_save = True;
60    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 usage(char *program)  static void
75    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 main(int argc, char *argv[])  int
146    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:w:h:k:bml?")) != -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;                                  break;
223    
224                          case 'n':                          case 'p':
225                                  strncpy(hostname, optarg, sizeof(hostname));                                  if ((optarg[0] == '-') && (optarg[1] == 0))
226                                  break;                                  {
227                                            prompt_password = True;
228                                            break;
229                                    }
230    
231                                    STRNCPY(password, optarg, sizeof(password));
232                                    flags |= RDP_LOGON_AUTO;
233    
234                          case 'w':                                  /* try to overwrite argument so it won't appear in ps */
235                                  width = strtol(optarg, NULL, 10);                                  p = optarg;
236                                    while (*p)
237                                            *(p++) = 'X';
238                                  break;                                  break;
239    
240                          case 'h':                          case 'n':
241                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(hostname, optarg, sizeof(hostname));
242                                  break;                                  break;
243    
244                          case 'k':                          case 'k':
245                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
246                                  break;                                  break;
247    
248                          case 'm':                          case 'g':
249                                  motion = False;                                  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                                            error("invalid geometry\n");
262                                            return 1;
263                                    }
264                                    break;
265    
266                            case 'f':
267                                    fullscreen = True;
268                                  break;                                  break;
269    
270                          case 'b':                          case 'b':
271                                  orders = False;                                  orders = False;
272                                  break;                                  break;
273    
274                          case 'l':                          case 'e':
275                                  licence = False;                                  encryption = False;
276                                    break;
277                            case 'E':
278                                    packet_encryption = False;
279                                    break;
280                            case 'm':
281                                    sendmotion = False;
282                                    break;
283    
284                            case 'C':
285                                    owncolmap = True;
286                                  break;                                  break;
287    
288                            case 'K':
289                                    grab_keyboard = False;
290                                    break;
291    
292                            case 'T':
293                                    STRNCPY(title, optarg, sizeof(title));
294                                    break;
295    
296                            case 'D':
297                                    hide_decorations = True;
298                                    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':
314                          case '?':                          case '?':
315                          default:                          default:
316                                  usage(argv[0]);                                  usage(argv[0]);
# Line 140  int main(int argc, char *argv[]) Line 324  int 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            if (prompt_password && read_password(password, sizeof(password)))
363                    flags |= RDP_LOGON_AUTO;
364    
365            if (title[0] == 0)
366            {
367                    strcpy(title, "rdesktop - ");
368                    strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
369            }
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))          if (!rdp_connect(server, flags, domain, password, shell, directory))
385                  return 1;                  return 1;
386    
387          STATUS("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
388               packet but unencrypted transfer of other packets */
389            if (!packet_encryption)
390                    encryption = False;
391    
         strcpy(title, "rdesktop - ");  
         strncat(title, server, sizeof(title));  
392    
393          if (ui_create_window(title))          DEBUG(("Connection successful.\n"));
394            memset(password, 0, sizeof(password));
395    
396            if (ui_create_window())
397          {          {
398                  rdp_main_loop();                  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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
416  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
421          uint32 *r = (uint32 *)random;          BOOL ret = False;
422          int fd;          int fd;
423    
424          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
425          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
454    void
455    generate_random(uint8 * random)
456    {
457            struct stat st;
458            struct tms tmsbuf;
459            MD5_CTX md5;
460            uint32 *r;
461            int fd, n;
462    
463            /* 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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
484          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
485          stat("/tmp", &st);          stat("/tmp", &st);
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 */
499  void *xmalloc(int size)  void *
500    xmalloc(int size)
501  {  {
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;
509  }  }
510    
511  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
512  void *xrealloc(void *oldmem, int size)  void *
513    xrealloc(void *oldmem, int size)
514  {  {
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;
522  }  }
523    
524  /* free */  /* free */
525  void xfree(void *mem)  void
526    xfree(void *mem)
527  {  {
528          free(mem);          free(mem);
529  }  }
530    
531  /* Produce a hex dump */  /* report an error */
532  void hexdump(unsigned char *p, unsigned int len)  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
546    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])                          printf("%02x ", line[i]);
586    
587                  for (; i < 16; i++)                  for (; i < 16; i++)
588                          STATUS("   ");                          printf("   ");
589    
590                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
591                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (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.21  
changed lines
  Added in v.427

  ViewVC Help
Powered by ViewVC 1.1.26