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

Legend:
Removed from v.17  
changed lines
  Added in v.416

  ViewVC Help
Powered by ViewVC 1.1.26