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

Legend:
Removed from v.29  
changed lines
  Added in v.424

  ViewVC Help
Powered by ViewVC 1.1.26