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

Legend:
Removed from v.28  
changed lines
  Added in v.297

  ViewVC Help
Powered by ViewVC 1.1.26