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

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

  ViewVC Help
Powered by ViewVC 1.1.26