/[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 66 by astrand, Thu Jul 18 18:28:12 2002 UTC revision 325 by astrand, Tue Feb 11 11:31:04 2003 UTC
# Line 1  Line 1 
1  /*  /*
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions     Entrypoint and utility functions
4     Copyright (C) Matthew Chapman 1999-2001     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    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #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 <limits.h>             /* PATH_MAX */  #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  char keymapname[16];  char keymapname[16];
47  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
48  int width;  int width = 800;                /* If width or height are reset to zero, the geometry will
49  int height;                                     be fetched from _NET_WORKAREA */
50    int height = 600;
51  int tcp_port_rdp = TCP_PORT_RDP;  int tcp_port_rdp = TCP_PORT_RDP;
52    int server_bpp = 8;
53  BOOL bitmap_compression = True;  BOOL bitmap_compression = True;
54  BOOL sendmotion = True;  BOOL sendmotion = True;
55  BOOL orders = True;  BOOL orders = True;
 BOOL licence = True;  
56  BOOL encryption = True;  BOOL encryption = True;
57  BOOL desktop_save = True;  BOOL desktop_save = True;
58  BOOL fullscreen = False;  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          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
68          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
69          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
70          printf("   -s: shell\n");  
71          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
72          printf("   -p: password (autologon)\n");          fprintf(stderr, "   -u: user name\n");
73          printf("   -n: client hostname\n");          fprintf(stderr, "   -d: domain\n");
74          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -s: shell\n");
75          printf("   -g: desktop geometry (WxH)\n");          fprintf(stderr, "   -c: working directory\n");
76          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
77          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -n: client hostname\n");
78          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");
79          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
80          printf("   -l: do not request licence\n");          fprintf(stderr, "   -f: full-screen mode\n");
81          printf("   -t: rdp tcp port\n\n");          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            char server[64];
132          char fullhostname[64];          char fullhostname[64];
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;          struct passwd *pw;
         char *server, *p;  
139          uint32 flags;          uint32 flags;
140            char *p;
141          int c;          int c;
142            int username_option = 0;
         printf("rdesktop: A Remote Desktop Protocol client.\n");  
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("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, "us");          strcpy(keymapname, "en-us");
148    
149          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlh?")) != -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':
# Line 110  main(int argc, char *argv[]) Line 168  main(int argc, char *argv[])
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));                                  STRNCPY(password, optarg, sizeof(password));
178                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
179    
180                                    /* try to overwrite argument so it won't appear in ps */
181                                    p = optarg;
182                                    while (*p)
183                                            *(p++) = 'X';
184                                  break;                                  break;
185    
186                          case 'n':                          case 'n':
# Line 119  main(int argc, char *argv[]) Line 188  main(int argc, char *argv[])
188                                  break;                                  break;
189    
190                          case 'k':                          case 'k':
191                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
192                                  break;                                  break;
193    
194                          case 'g':                          case 'g':
195                                    if (!strcmp(optarg, "workarea"))
196                                    {
197                                            width = height = 0;
198                                            break;
199                                    }
200    
201                                  width = strtol(optarg, &p, 10);                                  width = strtol(optarg, &p, 10);
202                                  if (*p == 'x')                                  if (*p == 'x')
203                                          height = strtol(p + 1, NULL, 10);                                          height = strtol(p + 1, NULL, 10);
# Line 151  main(int argc, char *argv[]) Line 225  main(int argc, char *argv[])
225                                  sendmotion = False;                                  sendmotion = False;
226                                  break;                                  break;
227    
228                          case 'l':                          case 'C':
229                                  licence = False;                                  owncolmap = True;
230                                    break;
231    
232                            case 'K':
233                                    grab_keyboard = False;
234                                  break;                                  break;
235    
236                          case 't':                          case 'T':
237                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  STRNCPY(title, optarg, sizeof(title));
238                                    break;
239    
240                            case 'D':
241                                    hide_decorations = True;
242                                    break;
243    
244                            case 'a':
245                                    server_bpp = strtol(optarg, NULL, 10);
246                                    if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15
247                                        && server_bpp != 24)
248                                    {
249                                            error("invalid server bpp\n");
250                                            return 1;
251                                    }
252                                  break;                                  break;
253    
254                          case 'h':                          case 'h':
# Line 173  main(int argc, char *argv[]) Line 265  main(int argc, char *argv[])
265                  return 1;                  return 1;
266          }          }
267    
268          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
269            p = strchr(server, ':');
270            if (p != NULL)
271            {
272                    tcp_port_rdp = strtol(p + 1, NULL, 10);
273                    *p = 0;
274            }
275    
276          if (username[0] == 0)          if (!username_option)
277          {          {
278                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
279                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 202  main(int argc, char *argv[]) Line 300  main(int argc, char *argv[])
300                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
301          }          }
302    
303          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
304          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
305    
306          if ((width == 0) || (height == 0))          if (title[0] == 0)
307          {          {
308                  width = 800;                  strcpy(title, "rdesktop - ");
309                  height = 600;                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
310          }          }
311    
312          strcpy(title, "rdesktop - ");          if (!ui_init())
313          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));                  return 1;
   
         xkeymap_init1();  
314    
315          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
316                  return 1;                  return 1;
317    
318          printf("Connection successful.\n");          DEBUG(("Connection successful.\n"));
319            memset(password, 0, sizeof(password));
320    
321          if (ui_create_window(title))          if (ui_create_window())
322          {          {
323                  rdp_main_loop();                  rdp_main_loop();
324                  ui_destroy_window();                  ui_destroy_window();
325          }          }
326    
327          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
328          rdp_disconnect();          rdp_disconnect();
329            ui_deinit();
330          return 0;          return 0;
331  }  }
332    
333    #ifdef EGD_SOCKET
334    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
335    static BOOL
336    generate_random_egd(uint8 * buf)
337    {
338            struct sockaddr_un addr;
339            BOOL ret = False;
340            int fd;
341    
342            fd = socket(AF_UNIX, SOCK_STREAM, 0);
343            if (fd == -1)
344                    return False;
345    
346            addr.sun_family = AF_UNIX;
347            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
348            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
349                    goto err;
350    
351            /* PRNGD and EGD use a simple communications protocol */
352            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
353            buf[1] = 32;            /* Number of requested random bytes */
354            if (write(fd, buf, 2) != 2)
355                    goto err;
356    
357            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
358                    goto err;
359    
360            if (read(fd, buf, 32) != 32)
361                    goto err;
362    
363            ret = True;
364    
365          err:
366            close(fd);
367            return ret;
368    }
369    #endif
370    
371  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
372  void  void
373  generate_random(uint8 * random)  generate_random(uint8 * random)
374  {  {
375          struct stat st;          struct stat st;
376          struct tms tmsbuf;          struct tms tmsbuf;
377          uint32 *r = (uint32 *) random;          MD5_CTX md5;
378          int fd;          uint32 *r;
379            int fd, n;
380    
381          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
382          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
383              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
384          {          {
385                  read(fd, random, 32);                  n = read(fd, random, 32);
386                  close(fd);                  close(fd);
387                  return;                  if (n == 32)
388                            return;
389          }          }
390    
391    #ifdef EGD_SOCKET
392            /* As a second preference use an EGD */
393            if (generate_random_egd(random))
394                    return;
395    #endif
396    
397          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
398            r = (uint32 *) random;
399          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
400          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
401          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 267  generate_random(uint8 * random) Line 404  generate_random(uint8 * random)
404          r[5] = st.st_atime;          r[5] = st.st_atime;
405          r[6] = st.st_mtime;          r[6] = st.st_mtime;
406          r[7] = st.st_ctime;          r[7] = st.st_ctime;
407    
408            /* Hash both halves with MD5 to obscure possible patterns */
409            MD5_Init(&md5);
410            MD5_Update(&md5, random, 16);
411            MD5_Final(random, &md5);
412            MD5_Update(&md5, random + 16, 16);
413            MD5_Final(random + 16, &md5);
414  }  }
415    
416  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 315  error(char *format, ...) Line 459  error(char *format, ...)
459          va_end(ap);          va_end(ap);
460  }  }
461    
462    /* report a warning */
463    void
464    warning(char *format, ...)
465    {
466            va_list ap;
467    
468            fprintf(stderr, "WARNING: ");
469    
470            va_start(ap, format);
471            vfprintf(stderr, format, ap);
472            va_end(ap);
473    }
474    
475  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
476  void  void
477  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 350  hexdump(unsigned char *p, unsigned int l Line 507  hexdump(unsigned char *p, unsigned int l
507                          printf("   ");                          printf("   ");
508    
509                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
510                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
511    
512                  printf("\n");                  printf("\n");
513                  offset += thisline;                  offset += thisline;
# Line 360  hexdump(unsigned char *p, unsigned int l Line 515  hexdump(unsigned char *p, unsigned int l
515          }          }
516  }  }
517    
518    
519  int  int
520  load_licence(unsigned char **data)  load_licence(unsigned char **data)
521  {  {
522          char path[PATH_MAX];          char *path;
523          char *home;          char *home;
524          struct stat st;          struct stat st;
525          int fd;          int fd;
# Line 372  load_licence(unsigned char **data) Line 528  load_licence(unsigned char **data)
528          if (home == NULL)          if (home == NULL)
529                  return -1;                  return -1;
530    
531          STRNCPY(path, home, sizeof(path));          path = xmalloc(strlen(home) + strlen(hostname) + 20);
532          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
533    
534          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
535          if (fd == -1)          if (fd == -1)
# Line 389  load_licence(unsigned char **data) Line 545  load_licence(unsigned char **data)
545  void  void
546  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
547  {  {
548          char path[PATH_MAX];          char *fpath;            /* file path for licence */
549            char *fname, *fnamewrk; /* file name for licence .inkl path. */
550          char *home;          char *home;
551          int fd;          uint32 y;
552            struct flock fnfl;
553            int fnfd, fnwrkfd, i, wlen;
554            struct stream s, *s_ptr;
555            uint32 len;
556    
557            /* Construct a stream, so that we can use macros to extract the
558             * licence.
559             */
560            s_ptr = &s;
561            s_ptr->p = data;
562            /* Skip first two bytes */
563            in_uint16(s_ptr, len);
564    
565            /* Skip three strings */
566            for (i = 0; i < 3; i++)
567            {
568                    in_uint32(s_ptr, len);
569                    s_ptr->p += len;
570                    /* Make sure that we won't be past the end of data after
571                     * reading the next length value
572                     */
573                    if ((s_ptr->p) + 4 > data + length)
574                    {
575                            printf("Error in parsing licence key.\n");
576                            printf("Strings %d end value %x > supplied length (%x)\n", i,
577                                   (unsigned int) s_ptr->p, (unsigned int) data + length);
578                            return;
579                    }
580            }
581            in_uint32(s_ptr, len);
582            if (s_ptr->p + len > data + length)
583            {
584                    printf("Error in parsing licence key.\n");
585                    printf("End of licence %x > supplied length (%x)\n",
586                           (unsigned int) s_ptr->p + len, (unsigned int) data + length);
587                    return;
588            }
589    
590          home = getenv("HOME");          home = getenv("HOME");
591          if (home == NULL)          if (home == NULL)
592                  return;                  return;
593    
594          STRNCPY(path, home, sizeof(path));          /* set and create the directory -- if it doesn't exist. */
595          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);          fpath = xmalloc(strlen(home) + 11);
596          mkdir(path, 0700);          STRNCPY(fpath, home, strlen(home) + 1);
597    
598          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(fpath, "%s/.rdesktop", fpath);
599            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
600            {
601                    perror("mkdir");
602                    exit(1);
603            }
604    
605          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          /* set the real licence filename, and put a write lock on it. */
606          if (fd == -1)          fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
607            sprintf(fname, "%s/licence.%s", fpath, hostname);
608            fnfd = open(fname, O_RDONLY);
609            if (fnfd != -1)
610            {
611                    fnfl.l_type = F_WRLCK;
612                    fnfl.l_whence = SEEK_SET;
613                    fnfl.l_start = 0;
614                    fnfl.l_len = 1;
615                    fcntl(fnfd, F_SETLK, &fnfl);
616            }
617    
618            /* create a temporary licence file */
619            fnamewrk = xmalloc(strlen(fname) + 12);
620            for (y = 0;; y++)
621            {
622                    sprintf(fnamewrk, "%s.%lu", fname, (long unsigned int) y);
623                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
624                    if (fnwrkfd == -1)
625                    {
626                            if (errno == EINTR || errno == EEXIST)
627                                    continue;
628                            perror("create");
629                            exit(1);
630                    }
631                    break;
632            }
633            /* write to the licence file */
634            for (y = 0; y < len;)
635          {          {
636                  perror("open");                  do
637                  return;                  {
638                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
639                    }
640                    while (wlen == -1 && errno == EINTR);
641                    if (wlen < 1)
642                    {
643                            perror("write");
644                            unlink(fnamewrk);
645                            exit(1);
646                    }
647                    y += wlen;
648            }
649    
650            /* close the file and rename it to fname */
651            if (close(fnwrkfd) == -1)
652            {
653                    perror("close");
654                    unlink(fnamewrk);
655                    exit(1);
656            }
657            if (rename(fnamewrk, fname) == -1)
658            {
659                    perror("rename");
660                    unlink(fnamewrk);
661                    exit(1);
662            }
663            /* close the file lock on fname */
664            if (fnfd != -1)
665            {
666                    fnfl.l_type = F_UNLCK;
667                    fnfl.l_whence = SEEK_SET;
668                    fnfl.l_start = 0;
669                    fnfl.l_len = 1;
670                    fcntl(fnfd, F_SETLK, &fnfl);
671                    close(fnfd);
672          }          }
673    
         write(fd, data, length);  
         close(fd);  
674  }  }

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

  ViewVC Help
Powered by ViewVC 1.1.26