/[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 79 by astrand, Mon Jul 29 20:35:13 2002 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-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    #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  char keymapname[16];  char keymapname[16];
47  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
48  int width;  int width = 800;                /* If width or height are reset to zero, the geometry will
49  int height;                                     be fetched from _NET_WORKAREA */
50    int height = 600;
51  int tcp_port_rdp = TCP_PORT_RDP;  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;
 BOOL licence = True;  
57  BOOL encryption = True;  BOOL encryption = True;
58    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;  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          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
78          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
79          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
80          printf("   -s: shell\n");  
81          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
82          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
83          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
84          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -E: defer time (ms)\n");
85          printf("   -g: desktop geometry (WxH)\n");  #endif
86          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
87          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
88          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
89          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -S: caption button size (single application mode)\n");
90          printf("   -l: do not request licence\n");          fprintf(stderr, "   -c: working directory\n");
91          printf("   -t: rdp tcp port\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
92          printf("   -K: keep window manager key bindings\n");          fprintf(stderr, "   -n: client hostname\n");
93            fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
94            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
95            fprintf(stderr, "   -f: full-screen mode\n");
96            fprintf(stderr, "   -b: force bitmap updates\n");
97            fprintf(stderr, "   -e: disable encryption (French TS)\n");
98            fprintf(stderr, "   -E: disable encryption 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            char server[64];
149          char fullhostname[64];          char fullhostname[64];
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;          struct passwd *pw;
         char *server, *p;  
156          uint32 flags;          uint32 flags;
157            char *p;
158          int c;          int c;
159            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");  
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, "us");          strcpy(keymapname, "en-us");
165    
166          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlKh?")) != -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':
# Line 107  main(int argc, char *argv[]) Line 200  main(int argc, char *argv[])
200                                  STRNCPY(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
201                                  break;                                  break;
202    
203                            case 'S':
204                                    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;
219    
220                          case 'c':                          case 'c':
221                                  STRNCPY(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
222                                  break;                                  break;
223    
224                          case 'p':                          case 'p':
225                                    if ((optarg[0] == '-') && (optarg[1] == 0))
226                                    {
227                                            prompt_password = True;
228                                            break;
229                                    }
230    
231                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
232                                  flags |= RDP_LOGON_AUTO;                                  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':
# Line 121  main(int argc, char *argv[]) Line 242  main(int argc, char *argv[])
242                                  break;                                  break;
243    
244                          case 'k':                          case 'k':
245                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         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);                                  width = strtol(optarg, &p, 10);
256                                  if (*p == 'x')                                  if (*p == 'x')
257                                          height = strtol(p + 1, NULL, 10);                                          height = strtol(p + 1, NULL, 10);
# Line 148  main(int argc, char *argv[]) Line 274  main(int argc, char *argv[])
274                          case 'e':                          case 'e':
275                                  encryption = False;                                  encryption = False;
276                                  break;                                  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 'l':                          case 'C':
285                                  licence = False;                                  owncolmap = True;
                                 break;  
   
                         case 't':  
                                 tcp_port_rdp = strtol(optarg, NULL, 10);  
286                                  break;                                  break;
287    
288                          case 'K':                          case 'K':
289                                  grab_keyboard = False;                                  grab_keyboard = False;
290                                  break;                                  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':                          case 'h':
314                          case '?':                          case '?':
315                          default:                          default:
# Line 179  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))
# Line 208  main(int argc, char *argv[]) Line 359  main(int argc, char *argv[])
359                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
360          }          }
361    
362          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
363          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
364    
365          if ((width == 0) || (height == 0))          if (title[0] == 0)
366          {          {
367                  width = 800;                  strcpy(title, "rdesktop - ");
368                  height = 600;                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
369          }          }
370    
371          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
372          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          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          xkeymap_init1();          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          printf("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    
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          printf("Disconnecting...\n");          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    
463          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
464          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
465              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((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 273  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 321  error(char *format, ...) Line 541  error(char *format, ...)
541          va_end(ap);          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 */  /* report an unimplemented protocol feature */
558  void  void
559  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 336  unimpl(char *format, ...) Line 569  unimpl(char *format, ...)
569    
570  /* produce a hex dump */  /* produce a hex dump */
571  void  void
572  hexdump(unsigned char *p, unsigned int len)  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          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 588  hexdump(unsigned char *p, unsigned int l
588                          printf("   ");                          printf("   ");
589    
590                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
591                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
592    
593                  printf("\n");                  printf("\n");
594                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 596  hexdump(unsigned char *p, unsigned int l
596          }          }
597  }  }
598    
599    
600  int  int
601  load_licence(unsigned char **data)  load_licence(unsigned char **data)
602  {  {
603          char path[PATH_MAX];          char *home, *path;
         char *home;  
604          struct stat st;          struct stat st;
605          int fd;          int fd, length;
606    
607          home = getenv("HOME");          home = getenv("HOME");
608          if (home == NULL)          if (home == NULL)
609                  return -1;                  return -1;
610    
611          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
612          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
613    
614          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
615          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 618  load_licence(unsigned char **data)
618          if (fstat(fd, &st))          if (fstat(fd, &st))
619                  return -1;                  return -1;
620    
621          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
622          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
623            close(fd);
624            xfree(path);
625            return length;
626  }  }
627    
628  void  void
629  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
630  {  {
631          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
632          int fd;          int fd;
633    
634          home = getenv("HOME");          home = getenv("HOME");
635          if (home == NULL)          if (home == NULL)
636                  return;                  return;
637    
638          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
639          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
640          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
641            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
642            {
643                    perror(path);
644                    return;
645            }
646    
647          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
648    
649          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          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)          if (fd == -1)
656          {          {
657                  perror("open");                  perror(tmppath);
658                  return;                  return;
659          }          }
660    
661          write(fd, data, length);          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);          close(fd);
673            xfree(tmppath);
674            xfree(path);
675  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26