/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/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/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

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

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

  ViewVC Help
Powered by ViewVC 1.1.26