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

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

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26