/[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 79 by astrand, Mon Jul 29 20:35:13 2002 UTC revision 315 by jsorg71, Sun Feb 9 01:38:07 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 <errno.h>              /* save licence uses it. */
25  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
26  #include <limits.h>             /* PATH_MAX */  #include <termios.h>            /* tcgetattr tcsetattr */
27  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
28  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
29  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
30  #include "rdesktop.h"  #include "rdesktop.h"
31    
32    #ifdef EGD_SOCKET
33    #include <sys/socket.h>         /* socket connect */
34    #include <sys/un.h>             /* sockaddr_un */
35    #endif
36    
37    #ifdef WITH_OPENSSL
38    #include <openssl/md5.h>
39    #else
40    #include "crypto/md5.h"
41    #endif
42    
43    char title[32] = "";
44  char username[16];  char username[16];
45  char hostname[16];  char hostname[16];
46  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;  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");          fprintf(stderr, "   -b: force bitmap updates\n");
82          printf("   -K: keep window manager key bindings\n");          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:fbemlKh?")) != -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 112  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 121  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 153  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;
                                 break;  
   
                         case 't':  
                                 tcp_port_rdp = strtol(optarg, NULL, 10);  
230                                  break;                                  break;
231    
232                          case 'K':                          case 'K':
233                                  grab_keyboard = False;                                  grab_keyboard = False;
234                                  break;                                  break;
235    
236                            case 'T':
237                                    STRNCPY(title, optarg, sizeof(title));
238                                    break;
239    
240                            case 'D':
241                                    hide_decorations = True;
242                                    break;
243    
244                            case 'a':
245                                    server_bpp = strtol(optarg, NULL, 10);
246                                    if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15 && server_bpp != 24)
247                                    {
248                                            error("invalid server bpp\n");
249                                            return 1;
250                                    }
251                                    break;
252    
253                          case 'h':                          case 'h':
254                          case '?':                          case '?':
255                          default:                          default:
# Line 179  main(int argc, char *argv[]) Line 264  main(int argc, char *argv[])
264                  return 1;                  return 1;
265          }          }
266    
267          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
268            p = strchr(server, ':');
269            if (p != NULL)
270            {
271                    tcp_port_rdp = strtol(p + 1, NULL, 10);
272                    *p = 0;
273            }
274    
275          if (username[0] == 0)          if (!username_option)
276          {          {
277                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
278                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 208  main(int argc, char *argv[]) Line 299  main(int argc, char *argv[])
299                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
300          }          }
301    
302          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
303          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
304    
305          if ((width == 0) || (height == 0))          if (title[0] == 0)
306          {          {
307                  width = 800;                  strcpy(title, "rdesktop - ");
308                  height = 600;                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));
309          }          }
310    
311          strcpy(title, "rdesktop - ");          if (!ui_init())
312          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));                  return 1;
   
         xkeymap_init1();  
313    
314          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
315                  return 1;                  return 1;
316    
317          printf("Connection successful.\n");          DEBUG(("Connection successful.\n"));
318            memset(password, 0, sizeof(password));
319    
320          if (ui_create_window(title))          if (ui_create_window())
321          {          {
322                  rdp_main_loop();                  rdp_main_loop();
323                  ui_destroy_window();                  ui_destroy_window();
324          }          }
325    
326          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
327          rdp_disconnect();          rdp_disconnect();
328            ui_deinit();
329          return 0;          return 0;
330  }  }
331    
332    #ifdef EGD_SOCKET
333    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
334    static BOOL
335    generate_random_egd(uint8 * buf)
336    {
337            struct sockaddr_un addr;
338            BOOL ret = False;
339            int fd;
340    
341            fd = socket(AF_UNIX, SOCK_STREAM, 0);
342            if (fd == -1)
343                    return False;
344    
345            addr.sun_family = AF_UNIX;
346            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
347            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
348                    goto err;
349    
350            /* PRNGD and EGD use a simple communications protocol */
351            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
352            buf[1] = 32;            /* Number of requested random bytes */
353            if (write(fd, buf, 2) != 2)
354                    goto err;
355    
356            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
357                    goto err;
358    
359            if (read(fd, buf, 32) != 32)
360                    goto err;
361    
362            ret = True;
363    
364          err:
365            close(fd);
366            return ret;
367    }
368    #endif
369    
370  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
371  void  void
372  generate_random(uint8 * random)  generate_random(uint8 * random)
373  {  {
374          struct stat st;          struct stat st;
375          struct tms tmsbuf;          struct tms tmsbuf;
376          uint32 *r = (uint32 *) random;          MD5_CTX md5;
377          int fd;          uint32 *r;
378            int fd, n;
379    
380          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
381          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
382              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
383          {          {
384                  read(fd, random, 32);                  n = read(fd, random, 32);
385                  close(fd);                  close(fd);
386                  return;                  if (n == 32)
387                            return;
388          }          }
389    
390    #ifdef EGD_SOCKET
391            /* As a second preference use an EGD */
392            if (generate_random_egd(random))
393                    return;
394    #endif
395    
396          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
397            r = (uint32 *) random;
398          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
399          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
400          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 273  generate_random(uint8 * random) Line 403  generate_random(uint8 * random)
403          r[5] = st.st_atime;          r[5] = st.st_atime;
404          r[6] = st.st_mtime;          r[6] = st.st_mtime;
405          r[7] = st.st_ctime;          r[7] = st.st_ctime;
406    
407            /* Hash both halves with MD5 to obscure possible patterns */
408            MD5_Init(&md5);
409            MD5_Update(&md5, random, 16);
410            MD5_Final(random, &md5);
411            MD5_Update(&md5, random + 16, 16);
412            MD5_Final(random + 16, &md5);
413  }  }
414    
415  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 321  error(char *format, ...) Line 458  error(char *format, ...)
458          va_end(ap);          va_end(ap);
459  }  }
460    
461    /* report a warning */
462    void
463    warning(char *format, ...)
464    {
465            va_list ap;
466    
467            fprintf(stderr, "WARNING: ");
468    
469            va_start(ap, format);
470            vfprintf(stderr, format, ap);
471            va_end(ap);
472    }
473    
474  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
475  void  void
476  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 356  hexdump(unsigned char *p, unsigned int l Line 506  hexdump(unsigned char *p, unsigned int l
506                          printf("   ");                          printf("   ");
507    
508                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
509                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
510    
511                  printf("\n");                  printf("\n");
512                  offset += thisline;                  offset += thisline;
# Line 366  hexdump(unsigned char *p, unsigned int l Line 514  hexdump(unsigned char *p, unsigned int l
514          }          }
515  }  }
516    
517    #ifdef SAVE_LICENCE
518  int  int
519  load_licence(unsigned char **data)  load_licence(unsigned char **data)
520  {  {
521          char path[PATH_MAX];          char *path;
522          char *home;          char *home;
523          struct stat st;          struct stat st;
524          int fd;          int fd;
# Line 378  load_licence(unsigned char **data) Line 527  load_licence(unsigned char **data)
527          if (home == NULL)          if (home == NULL)
528                  return -1;                  return -1;
529    
530          STRNCPY(path, home, sizeof(path));          path = xmalloc(strlen(home) + strlen(hostname) + 20);
531          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
532    
533          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
534          if (fd == -1)          if (fd == -1)
# Line 395  load_licence(unsigned char **data) Line 544  load_licence(unsigned char **data)
544  void  void
545  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
546  {  {
547          char path[PATH_MAX];          char *fpath;            /* file path for licence */
548            char *fname, *fnamewrk; /* file name for licence .inkl path. */
549          char *home;          char *home;
550          int fd;          uint32 y;
551            struct flock fnfl;
552            int fnfd, fnwrkfd, i, wlen;
553            struct stream s, *s_ptr;
554            uint32 len;
555    
556            /* Construct a stream, so that we can use macros to extract the
557             * licence.
558             */
559            s_ptr = &s;
560            s_ptr->p = data;
561            /* Skip first two bytes */
562            in_uint16(s_ptr, len);
563    
564            /* Skip three strings */
565            for (i = 0; i < 3; i++)
566            {
567                    in_uint32(s_ptr, len);
568                    s_ptr->p += len;
569                    /* Make sure that we won't be past the end of data after
570                     * reading the next length value
571                     */
572                    if ((s_ptr->p) + 4 > data + length)
573                    {
574                            printf("Error in parsing licence key.\n");
575                            printf("Strings %d end value %x > supplied length (%x)\n",
576                                   i, s_ptr->p, data + length);
577                            return;
578                    }
579            }
580            in_uint32(s_ptr, len);
581            if (s_ptr->p + len > data + length)
582            {
583                    printf("Error in parsing licence key.\n");
584                    printf("End of licence %x > supplied length (%x)\n", s_ptr->p + len, data + length);
585                    return;
586            }
587    
588          home = getenv("HOME");          home = getenv("HOME");
589          if (home == NULL)          if (home == NULL)
590                  return;                  return;
591    
592          STRNCPY(path, home, sizeof(path));          /* set and create the directory -- if it doesn't exist. */
593          strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);          fpath = xmalloc(strlen(home) + 11);
594          mkdir(path, 0700);          STRNCPY(fpath, home, strlen(home) + 1);
595    
596          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(fpath, "%s/.rdesktop", fpath);
597            if (mkdir(fpath, 0700) == -1 && errno != EEXIST)
598            {
599                    perror("mkdir");
600                    exit(1);
601            }
602    
603          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          /* set the real licence filename, and put a write lock on it. */
604          if (fd == -1)          fname = xmalloc(strlen(fpath) + strlen(hostname) + 10);
605            sprintf(fname, "%s/licence.%s", fpath, hostname);
606            fnfd = open(fname, O_RDONLY);
607            if (fnfd != -1)
608            {
609                    fnfl.l_type = F_WRLCK;
610                    fnfl.l_whence = SEEK_SET;
611                    fnfl.l_start = 0;
612                    fnfl.l_len = 1;
613                    fcntl(fnfd, F_SETLK, &fnfl);
614            }
615    
616            /* create a temporary licence file */
617            fnamewrk = xmalloc(strlen(fname) + 12);
618            for (y = 0;; y++)
619            {
620                    sprintf(fnamewrk, "%s.%lu", fname, y);
621                    fnwrkfd = open(fnamewrk, O_WRONLY | O_CREAT | O_EXCL, 0600);
622                    if (fnwrkfd == -1)
623                    {
624                            if (errno == EINTR || errno == EEXIST)
625                                    continue;
626                            perror("create");
627                            exit(1);
628                    }
629                    break;
630            }
631            /* write to the licence file */
632            for (y = 0; y < len;)
633          {          {
634                  perror("open");                  do
635                  return;                  {
636                            wlen = write(fnwrkfd, s_ptr->p + y, len - y);
637                    }
638                    while (wlen == -1 && errno == EINTR);
639                    if (wlen < 1)
640                    {
641                            perror("write");
642                            unlink(fnamewrk);
643                            exit(1);
644                    }
645                    y += wlen;
646            }
647    
648            /* close the file and rename it to fname */
649            if (close(fnwrkfd) == -1)
650            {
651                    perror("close");
652                    unlink(fnamewrk);
653                    exit(1);
654            }
655            if (rename(fnamewrk, fname) == -1)
656            {
657                    perror("rename");
658                    unlink(fnamewrk);
659                    exit(1);
660            }
661            /* close the file lock on fname */
662            if (fnfd != -1)
663            {
664                    fnfl.l_type = F_UNLCK;
665                    fnfl.l_whence = SEEK_SET;
666                    fnfl.l_start = 0;
667                    fnfl.l_len = 1;
668                    fcntl(fnfd, F_SETLK, &fnfl);
669                    close(fnfd);
670          }          }
671    
         write(fd, data, length);  
         close(fd);  
672  }  }
673    #endif

Legend:
Removed from v.79  
changed lines
  Added in v.315

  ViewVC Help
Powered by ViewVC 1.1.26