/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

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

Legend:
Removed from v.25  
changed lines
  Added in v.309

  ViewVC Help
Powered by ViewVC 1.1.26