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

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

  ViewVC Help
Powered by ViewVC 1.1.26