/[rdesktop]/sourceforge.net/trunk/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/trunk/rdesktop/rdesktop.c

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

revision 76 by astrand, Mon Jul 29 20:16:22 2002 UTC revision 435 by astrand, Wed Jul 9 09:18:20 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\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          xkeymap_init1();          /* rdpsnd_init(); */
380            /* rdpdr_init(); */
381    
382          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
383                  return 1;                  return 1;
384    
385          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
386               packet but unencrypted transfer of other packets */
387            if (!packet_encryption)
388                    encryption = False;
389    
390    
391          if (ui_create_window(title))          DEBUG(("Connection successful.\n"));
392            memset(password, 0, sizeof(password));
393    
394            if (ui_create_window())
395          {          {
396                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
397                  ui_destroy_window();                  ui_destroy_window();
398          }          }
399    
400          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
401          rdp_disconnect();          rdp_disconnect();
402          return 0;          ui_deinit();
403    
404            if (True == rdp_retval)
405                    return 0;
406            else
407                    return 2;
408    
409    #endif
410    
411  }  }
412    
413    #ifdef EGD_SOCKET
414    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
415    static BOOL
416    generate_random_egd(uint8 * buf)
417    {
418            struct sockaddr_un addr;
419            BOOL ret = False;
420            int fd;
421    
422            fd = socket(AF_UNIX, SOCK_STREAM, 0);
423            if (fd == -1)
424                    return False;
425    
426            addr.sun_family = AF_UNIX;
427            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
428            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
429                    goto err;
430    
431            /* PRNGD and EGD use a simple communications protocol */
432            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
433            buf[1] = 32;            /* Number of requested random bytes */
434            if (write(fd, buf, 2) != 2)
435                    goto err;
436    
437            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
438                    goto err;
439    
440            if (read(fd, buf, 32) != 32)
441                    goto err;
442    
443            ret = True;
444    
445          err:
446            close(fd);
447            return ret;
448    }
449    #endif
450    
451  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
452  void  void
453  generate_random(uint8 * random)  generate_random(uint8 * random)
454  {  {
455          struct stat st;          struct stat st;
456          struct tms tmsbuf;          struct tms tmsbuf;
457          uint32 *r = (uint32 *) random;          MD5_CTX md5;
458          int fd;          uint32 *r;
459            int fd, n;
460    
461          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
462          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
463              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
464          {          {
465                  read(fd, random, 32);                  n = read(fd, random, 32);
466                  close(fd);                  close(fd);
467                  return;                  if (n == 32)
468                            return;
469          }          }
470    
471    #ifdef EGD_SOCKET
472            /* As a second preference use an EGD */
473            if (generate_random_egd(random))
474                    return;
475    #endif
476    
477          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
478            r = (uint32 *) random;
479          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
480          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
481          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 484  generate_random(uint8 * random)
484          r[5] = st.st_atime;          r[5] = st.st_atime;
485          r[6] = st.st_mtime;          r[6] = st.st_mtime;
486          r[7] = st.st_ctime;          r[7] = st.st_ctime;
487    
488            /* Hash both halves with MD5 to obscure possible patterns */
489            MD5_Init(&md5);
490            MD5_Update(&md5, random, 16);
491            MD5_Final(random, &md5);
492            MD5_Update(&md5, random + 16, 16);
493            MD5_Final(random + 16, &md5);
494  }  }
495    
496  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 321  error(char *format, ...) Line 539  error(char *format, ...)
539          va_end(ap);          va_end(ap);
540  }  }
541    
542    /* report a warning */
543    void
544    warning(char *format, ...)
545    {
546            va_list ap;
547    
548            fprintf(stderr, "WARNING: ");
549    
550            va_start(ap, format);
551            vfprintf(stderr, format, ap);
552            va_end(ap);
553    }
554    
555  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
556  void  void
557  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 336  unimpl(char *format, ...) Line 567  unimpl(char *format, ...)
567    
568  /* produce a hex dump */  /* produce a hex dump */
569  void  void
570  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, int len)
571  {  {
572          unsigned char *line = p;          unsigned char *line = p;
573          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
574    
575          while (offset < len)          while (offset < len)
576          {          {
# Line 356  hexdump(unsigned char *p, unsigned int l Line 586  hexdump(unsigned char *p, unsigned int l
586                          printf("   ");                          printf("   ");
587    
588                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
589                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
590    
591                  printf("\n");                  printf("\n");
592                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 594  hexdump(unsigned char *p, unsigned int l
594          }          }
595  }  }
596    
597    
598  int  int
599  load_licence(unsigned char **data)  load_licence(unsigned char **data)
600  {  {
601          char path[PATH_MAX];          char *home, *path;
         char *home;  
602          struct stat st;          struct stat st;
603          int fd;          int fd, length;
604    
605          home = getenv("HOME");          home = getenv("HOME");
606          if (home == NULL)          if (home == NULL)
607                  return -1;                  return -1;
608    
609          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
610          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
611    
612          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
613          if (fd == -1)          if (fd == -1)
# Line 388  load_licence(unsigned char **data) Line 616  load_licence(unsigned char **data)
616          if (fstat(fd, &st))          if (fstat(fd, &st))
617                  return -1;                  return -1;
618    
619          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
620          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
621            close(fd);
622            xfree(path);
623            return length;
624  }  }
625    
626  void  void
627  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
628  {  {
629          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
630          int fd;          int fd;
631    
632          home = getenv("HOME");          home = getenv("HOME");
633          if (home == NULL)          if (home == NULL)
634                  return;                  return;
635    
636          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
637          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
638          mkdir(path, 0700);          sprintf(path, "%s/.rdesktop", home);
639            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
640            {
641                    perror(path);
642                    return;
643            }
644    
645          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
646    
647          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
648            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
649            strcpy(tmppath, path);
650            strcat(tmppath, ".new");
651    
652            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
653          if (fd == -1)          if (fd == -1)
654          {          {
655                  perror("open");                  perror(tmppath);
656                  return;                  return;
657          }          }
658    
659          write(fd, data, length);          if (write(fd, data, length) != length)
660            {
661                    perror(tmppath);
662                    unlink(tmppath);
663            }
664            else if (rename(tmppath, path) == -1)
665            {
666                    perror(path);
667                    unlink(tmppath);
668            }
669    
670          close(fd);          close(fd);
671            xfree(tmppath);
672            xfree(path);
673  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26