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

Legend:
Removed from v.24  
changed lines
  Added in v.482

  ViewVC Help
Powered by ViewVC 1.1.26