/[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 10 by matty, Tue Aug 15 10:23:24 2000 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-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 <getopt.h>     /* getopt */  #include <pwd.h>                /* getpwuid */
25  #include <pwd.h>        /* getpwuid */  #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>   /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>   /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>  /* times */  #include <sys/times.h>          /* times */
29    #include <errno.h>
30  #include "rdesktop.h"  #include "rdesktop.h"
31    
32    #ifdef EGD_SOCKET
33    #include <sys/socket.h>         /* socket connect */
34    #include <sys/un.h>             /* sockaddr_un */
35    #endif
36    
37    #ifdef WITH_OPENSSL
38    #include <openssl/md5.h>
39    #else
40    #include "crypto/md5.h"
41    #endif
42    
43    char title[32] = "";
44  char username[16];  char username[16];
45  char hostname[16];  char hostname[16];
46  int width = 800;  char keymapname[16];
47    int keylayout = 0x409;          /* Defaults to US keyboard layout */
48    int width = 800;                /* If width or height are reset to zero, the geometry will
49                                       be fetched from _NET_WORKAREA */
50  int height = 600;  int height = 600;
51  int keylayout = 0x409;  int tcp_port_rdp = TCP_PORT_RDP;
52  BOOL motion = False;  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            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
78            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
79            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
80    
81            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
82    #ifdef RDP2VNC
83            fprintf(stderr, "   -V: vnc port\n");
84            fprintf(stderr, "   -E: defer time (ms)\n");
85    #endif
86            fprintf(stderr, "   -u: user name\n");
87            fprintf(stderr, "   -d: domain\n");
88            fprintf(stderr, "   -s: shell\n");
89            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          STATUS("Usage: %s [options] server\n", program);          struct termios tios;
112          STATUS("   -u: user name\n");          BOOL ret = False;
113          STATUS("   -n: client hostname\n");          int istty = 0;
114          STATUS("   -w: desktop width\n");          char *p;
115          STATUS("   -h: desktop height\n");  
116          STATUS("   -k: keyboard layout (hex)\n");          if (tcgetattr(STDIN_FILENO, &tios) == 0)
117          STATUS("   -m: send motion events\n");          {
118          STATUS("   -b: force bitmap updates\n");                  fprintf(stderr, "Password: ");
119          STATUS("   -l: do not request licence\n\n");                  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            char server[64];
149            char fullhostname[64];
150            char domain[16];
151            char password[16];
152            char shell[128];
153            char directory[32];
154            BOOL prompt_password, rdp_retval = False;
155          struct passwd *pw;          struct passwd *pw;
156          char *server;          uint32 flags;
157          char title[32];          char *p;
158          int c;          int c;
159            int username_option = 0;
160    
161          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          flags = RDP_LOGON_NORMAL;
162          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n\n");          prompt_password = False;
163            domain[0] = password[0] = shell[0] = directory[0] = 0;
164            strcpy(keymapname, "en-us");
165    
166    #ifdef RDP2VNC
167    #define VNCOPT "V:E:"
168    #else
169    #define VNCOPT
170    #endif
171    
172          while ((c = getopt(argc, argv, "u:n:w:h:k:mbl?")) != -1)          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 'n':                          case 'd':
196                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(domain, optarg, sizeof(domain));
197                                  break;                                  break;
198    
199                          case 'w':                          case 's':
200                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
201                                  break;                                  break;
202    
203                          case 'h':                          case 'S':
204                                  height = strtol(optarg, NULL, 10);                                  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':
221                                    STRNCPY(directory, optarg, sizeof(directory));
222                                    break;
223    
224                            case 'p':
225                                    if ((optarg[0] == '-') && (optarg[1] == 0))
226                                    {
227                                            prompt_password = True;
228                                            break;
229                                    }
230    
231                                    STRNCPY(password, optarg, sizeof(password));
232                                    flags |= RDP_LOGON_AUTO;
233    
234                                    /* try to overwrite argument so it won't appear in ps */
235                                    p = optarg;
236                                    while (*p)
237                                            *(p++) = 'X';
238                                    break;
239    
240                            case 'n':
241                                    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 = True;                                  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;
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;                                  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 111  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 (!rdp_connect(server))          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;                  return 1;
378    
379          STATUS("Connection successful.\n");          /* rdpsnd_init(); */
380            /* rdpdr_init(); */
381    
382            if (!rdp_connect(server, flags, domain, password, shell, directory))
383                    return 1;
384    
385          snprintf(title, sizeof(title), "rdesktop - %s", server);          /* By setting encryption to False here, we have an encrypted login
386          if (ui_create_window(title))             packet but unencrypted transfer of other packets */
387            if (!packet_encryption)
388                    encryption = False;
389    
390    
391            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            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  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
414  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
419          uint32 *r = (uint32 *)random;          BOOL ret = False;
420          int fd;          int fd;
421    
422          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
423          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          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. */
452    void
453    generate_random(uint8 * random)
454    {
455            struct stat st;
456            struct tms tmsbuf;
457            MD5_CTX md5;
458            uint32 *r;
459            int fd, n;
460    
461            /* If we have a kernel random device, try that first */
462            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
463                || ((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(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
482          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
483          stat("/tmp", &st);          stat("/tmp", &st);
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 */
497  void *xmalloc(int size)  void *
498    xmalloc(int size)
499  {  {
500          void *mem = malloc(size);          void *mem = malloc(size);
501          if (mem == NULL)          if (mem == NULL)
502          {          {
503                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
504                  exit(1);                  exit(1);
505          }          }
506          return mem;          return mem;
507  }  }
508    
509  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
510  void *xrealloc(void *oldmem, int size)  void *
511    xrealloc(void *oldmem, int size)
512  {  {
513          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
514          if (mem == NULL)          if (mem == NULL)
515          {          {
516                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
517                  exit(1);                  exit(1);
518          }          }
519          return mem;          return mem;
520  }  }
521    
522  /* free */  /* free */
523  void xfree(void *mem)  void
524    xfree(void *mem)
525  {  {
526          free(mem);          free(mem);
527  }  }
528    
529  /* Produce a hex dump */  /* report an error */
530  void hexdump(unsigned char *p, unsigned int len)  void
531    error(char *format, ...)
532    {
533            va_list ap;
534    
535            fprintf(stderr, "ERROR: ");
536    
537            va_start(ap, format);
538            vfprintf(stderr, format, ap);
539            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 */
556    void
557    unimpl(char *format, ...)
558    {
559            va_list ap;
560    
561            fprintf(stderr, "NOT IMPLEMENTED: ");
562    
563            va_start(ap, format);
564            vfprintf(stderr, format, ap);
565            va_end(ap);
566    }
567    
568    /* produce a hex dump */
569    void
570    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          {          {
577                  STATUS("%04x ", offset);                  printf("%04x ", offset);
578                  thisline = len - offset;                  thisline = len - offset;
579                  if (thisline > 16)                  if (thisline > 16)
580                          thisline = 16;                          thisline = 16;
581    
582                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
583                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
584    
585                  for (; i < 16; i++)                  for (; i < 16; i++)
586                          STATUS("   ");                          printf("   ");
587    
588                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
589                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
590    
591                  STATUS("\n");                  printf("\n");
592                  offset += thisline;                  offset += thisline;
593                  line += thisline;                  line += thisline;
594          }          }
595  }  }
596    
597    
598    int
599    load_licence(unsigned char **data)
600    {
601            char *home, *path;
602            struct stat st;
603            int fd, length;
604    
605            home = getenv("HOME");
606            if (home == NULL)
607                    return -1;
608    
609            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
610            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
611    
612            fd = open(path, O_RDONLY);
613            if (fd == -1)
614                    return -1;
615    
616            if (fstat(fd, &st))
617                    return -1;
618    
619            *data = (uint8 *) xmalloc(st.st_size);
620            length = read(fd, *data, st.st_size);
621            close(fd);
622            xfree(path);
623            return length;
624    }
625    
626    void
627    save_licence(unsigned char *data, int length)
628    {
629            char *home, *path, *tmppath;
630            int fd;
631    
632            home = getenv("HOME");
633            if (home == NULL)
634                    return;
635    
636            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
637    
638            sprintf(path, "%s/.rdesktop", home);
639            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
640            {
641                    perror(path);
642                    return;
643            }
644    
645            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
646    
647            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)
654            {
655                    perror(tmppath);
656                    return;
657            }
658    
659            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);
671            xfree(tmppath);
672            xfree(path);
673    }

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

  ViewVC Help
Powered by ViewVC 1.1.26