/[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 66 by astrand, Thu Jul 18 18:28:12 2002 UTC revision 520 by matthewc, Tue Oct 28 05:07:00 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-2001     Copyright (C) Matthew Chapman 1999-2003
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
 #include <stdlib.h>             /* malloc realloc free */  
21  #include <stdarg.h>             /* va_list va_start va_end */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25  #include <limits.h>             /* PATH_MAX */  #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    #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 g_title[64] = "";
44    char g_username[64];
45  char hostname[16];  char hostname[16];
46  char keymapname[16];  char keymapname[16];
47  int keylayout = 0x409;          /* Defaults to US keyboard layout */  int keylayout = 0x409;          /* Defaults to US keyboard layout */
 int width;  
 int height;  
 int tcp_port_rdp = TCP_PORT_RDP;  
 BOOL bitmap_compression = True;  
 BOOL sendmotion = True;  
 BOOL orders = True;  
 BOOL licence = True;  
 BOOL encryption = True;  
 BOOL desktop_save = True;  
 BOOL fullscreen = False;  
48    
49    int g_width = 800;              /* width is special: If 0, the
50                                       geometry will be fetched from
51                                       _NET_WORKAREA. If negative,
52                                       absolute value specifies the
53                                       percent of the whole screen. */
54    int g_height = 600;
55    int tcp_port_rdp = TCP_PORT_RDP;
56    int g_server_bpp = 8;
57    int g_win_button_size = 0;      /* If zero, disable single app mode */
58    BOOL g_bitmap_compression = True;
59    BOOL g_sendmotion = True;
60    BOOL g_orders = True;
61    BOOL g_encryption = True;
62    BOOL packet_encryption = True;
63    BOOL g_desktop_save = True;
64    BOOL g_fullscreen = False;
65    BOOL g_grab_keyboard = True;
66    BOOL g_hide_decorations = False;
67    BOOL g_use_rdp5 = True;
68    BOOL g_console_session = False;
69    extern BOOL g_owncolmap;
70    
71    #ifdef WITH_RDPSND
72    BOOL g_rdpsnd = False;
73    #endif
74    
75    #ifdef RDP2VNC
76    extern int rfb_port;
77    extern int defer_time;
78    void
79    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
80                    char *shell, char *directory);
81    #endif
82  /* Display usage information */  /* Display usage information */
83  static void  static void
84  usage(char *program)  usage(char *program)
85  {  {
86          printf("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
87          printf("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
88          printf("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
89          printf("   -s: shell\n");  
90          printf("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
91          printf("   -p: password (autologon)\n");  #ifdef RDP2VNC
92          printf("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
93          printf("   -k: keyboard layout on terminal server (us,sv,gr etc.)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
94          printf("   -g: desktop geometry (WxH)\n");  #endif
95          printf("   -f: full-screen mode\n");          fprintf(stderr, "   -u: user name\n");
96          printf("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
97          printf("   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -s: shell\n");
98          printf("   -m: do not send motion events\n");          fprintf(stderr, "   -c: working directory\n");
99          printf("   -l: do not request licence\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
100          printf("   -t: rdp tcp port\n\n");          fprintf(stderr, "   -n: client hostname\n");
101            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
102            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
103            fprintf(stderr, "   -f: full-screen mode\n");
104            fprintf(stderr, "   -b: force bitmap updates\n");
105            fprintf(stderr, "   -e: disable encryption (French TS)\n");
106            fprintf(stderr, "   -E: disable encryption from client to server\n");
107            fprintf(stderr, "   -m: do not send motion events\n");
108            fprintf(stderr, "   -C: use private colour map\n");
109            fprintf(stderr, "   -D: hide window manager decorations\n");
110            fprintf(stderr, "   -K: keep window manager key bindings\n");
111            fprintf(stderr, "   -S: caption button size (single application mode)\n");
112            fprintf(stderr, "   -T: window title\n");
113            fprintf(stderr, "   -a: connection colour depth\n");
114            fprintf(stderr, "   -r: enable specified device redirection (currently: sound)\n");
115            fprintf(stderr, "   -0: attach to console\n");
116            fprintf(stderr, "   -4: use RDP version 4\n");
117            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
118    }
119    
120    static BOOL
121    read_password(char *password, int size)
122    {
123            struct termios tios;
124            BOOL ret = False;
125            int istty = 0;
126            char *p;
127    
128            if (tcgetattr(STDIN_FILENO, &tios) == 0)
129            {
130                    fprintf(stderr, "Password: ");
131                    tios.c_lflag &= ~ECHO;
132                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
133                    istty = 1;
134            }
135    
136            if (fgets(password, size, stdin) != NULL)
137            {
138                    ret = True;
139    
140                    /* strip final newline */
141                    p = strchr(password, '\n');
142                    if (p != NULL)
143                            *p = 0;
144            }
145    
146            if (istty)
147            {
148                    tios.c_lflag |= ECHO;
149                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
150                    fprintf(stderr, "\n");
151            }
152    
153            return ret;
154    }
155    
156    static void
157    parse_server_and_port(char *server)
158    {
159            char *p;
160    #ifdef IPv6
161            int addr_colons;
162    #endif
163    
164    #ifdef IPv6
165            p = server;
166            addr_colons = 0;
167            while (*p)
168                    if (*p++ == ':')
169                            addr_colons++;
170            if (addr_colons >= 2)
171            {
172                    /* numeric IPv6 style address format - [1:2:3::4]:port */
173                    p = strchr(server, ']');
174                    if (*server == '[' && p != NULL)
175                    {
176                            if (*(p + 1) == ':' && *(p + 2) != '\0')
177                                    tcp_port_rdp = strtol(p + 2, NULL, 10);
178                            /* remove the port number and brackets from the address */
179                            *p = '\0';
180                            strncpy(server, server + 1, strlen(server));
181                    }
182            }
183            else
184            {
185                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
186                    p = strchr(server, ':');
187                    if (p != NULL)
188                    {
189                            tcp_port_rdp = strtol(p + 1, NULL, 10);
190                            *p = 0;
191                    }
192            }
193    #else /* no IPv6 support */
194            p = strchr(server, ':');
195            if (p != NULL)
196            {
197                    tcp_port_rdp = strtol(p + 1, NULL, 10);
198                    *p = 0;
199            }
200    #endif /* IPv6 */
201    
202  }  }
203    
204  /* Client program */  /* Client program */
205  int  int
206  main(int argc, char *argv[])  main(int argc, char *argv[])
207  {  {
208            char server[64];
209          char fullhostname[64];          char fullhostname[64];
210          char domain[16];          char domain[16];
211          char password[16];          char password[64];
212          char shell[32];          char shell[128];
213          char directory[32];          char directory[32];
214          char title[32];          BOOL prompt_password, rdp_retval = False;
215          struct passwd *pw;          struct passwd *pw;
         char *server, *p;  
216          uint32 flags;          uint32 flags;
217            char *p;
218          int c;          int c;
219            int username_option = 0;
         printf("rdesktop: A Remote Desktop Protocol client.\n");  
         printf("Version " VERSION  
                ". Copyright (C) 1999-2001 Matt Chapman.\n");  
         printf("See http://www.rdesktop.org/ for more information.\n\n");  
220    
221          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
222            prompt_password = False;
223          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
224          strcpy(keymapname, "us");          strcpy(keymapname, "en-us");
225    
226          while ((c = getopt(argc, argv, "u:d:s:c:p:n:k:g:t:fbemlh?")) != -1)  #ifdef RDP2VNC
227    #define VNCOPT "V:Q:"
228    #else
229    #define VNCOPT
230    #endif
231    
232            while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbeEmCDKS:T:a:r:045h?")) != -1)
233          {          {
234                  switch (c)                  switch (c)
235                  {                  {
236    #ifdef RDP2VNC
237                            case 'V':
238                                    rfb_port = strtol(optarg, NULL, 10);
239                                    if (rfb_port < 100)
240                                            rfb_port += 5900;
241                                    break;
242    
243                            case 'Q':
244                                    defer_time = strtol(optarg, NULL, 10);
245                                    if (defer_time < 0)
246                                            defer_time = 0;
247                                    break;
248    #endif
249    
250                          case 'u':                          case 'u':
251                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
252                                    username_option = 1;
253                                  break;                                  break;
254    
255                          case 'd':                          case 'd':
# Line 110  main(int argc, char *argv[]) Line 265  main(int argc, char *argv[])
265                                  break;                                  break;
266    
267                          case 'p':                          case 'p':
268                                    if ((optarg[0] == '-') && (optarg[1] == 0))
269                                    {
270                                            prompt_password = True;
271                                            break;
272                                    }
273    
274                                  STRNCPY(password, optarg, sizeof(password));                                  STRNCPY(password, optarg, sizeof(password));
275                                  flags |= RDP_LOGON_AUTO;                                  flags |= RDP_LOGON_AUTO;
276    
277                                    /* try to overwrite argument so it won't appear in ps */
278                                    p = optarg;
279                                    while (*p)
280                                            *(p++) = 'X';
281                                  break;                                  break;
282    
283                          case 'n':                          case 'n':
# Line 119  main(int argc, char *argv[]) Line 285  main(int argc, char *argv[])
285                                  break;                                  break;
286    
287                          case 'k':                          case 'k':
288                                  STRNCPY(keymapname, optarg,                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
                                         sizeof(keymapname));  
289                                  break;                                  break;
290    
291                          case 'g':                          case 'g':
292                                  width = strtol(optarg, &p, 10);                                  if (!strcmp(optarg, "workarea"))
293                                    {
294                                            g_width = g_height = 0;
295                                            break;
296                                    }
297    
298                                    g_width = strtol(optarg, &p, 10);
299                                    if (g_width <= 0)
300                                    {
301                                            error("invalid geometry\n");
302                                            return 1;
303                                    }
304    
305                                  if (*p == 'x')                                  if (*p == 'x')
306                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, NULL, 10);
307    
308                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
309                                  {                                  {
310                                          error("invalid geometry\n");                                          error("invalid geometry\n");
311                                          return 1;                                          return 1;
312                                  }                                  }
313    
314                                    if (*p == '%')
315                                            g_width = -g_width;
316    
317                                  break;                                  break;
318    
319                          case 'f':                          case 'f':
320                                  fullscreen = True;                                  g_fullscreen = True;
321                                  break;                                  break;
322    
323                          case 'b':                          case 'b':
324                                  orders = False;                                  g_orders = False;
325                                  break;                                  break;
326    
327                          case 'e':                          case 'e':
328                                  encryption = False;                                  g_encryption = False;
329                                    break;
330                            case 'E':
331                                    packet_encryption = False;
332                                  break;                                  break;
   
333                          case 'm':                          case 'm':
334                                  sendmotion = False;                                  g_sendmotion = False;
335                                  break;                                  break;
336    
337                          case 'l':                          case 'C':
338                                  licence = False;                                  g_owncolmap = True;
339                                  break;                                  break;
340    
341                          case 't':                          case 'D':
342                                  tcp_port_rdp = strtol(optarg, NULL, 10);                                  g_hide_decorations = True;
343                                    break;
344    
345                            case 'K':
346                                    g_grab_keyboard = False;
347                                    break;
348    
349                            case 'S':
350                                    if (!strcmp(optarg, "standard"))
351                                    {
352                                            g_win_button_size = 18;
353                                            break;
354                                    }
355    
356                                    g_win_button_size = strtol(optarg, &p, 10);
357    
358                                    if (*p)
359                                    {
360                                            error("invalid button size\n");
361                                            return 1;
362                                    }
363    
364                                    break;
365    
366                            case 'T':
367                                    STRNCPY(g_title, optarg, sizeof(g_title));
368                                    break;
369    
370                            case 'a':
371                                    g_server_bpp = strtol(optarg, NULL, 10);
372                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
373                                        && g_server_bpp != 24)
374                                    {
375                                            error("invalid server bpp\n");
376                                            return 1;
377                                    }
378                                    break;
379    
380                            case 'r':
381                                    if (!strcmp(optarg, "sound"))
382    #ifdef WITH_RDPSND
383                                            g_rdpsnd = True;
384    #else
385                                            warning("Not compiled with sound support");
386    #endif
387                                    break;
388    
389                            case '0':
390                                    g_console_session = True;
391                                    break;
392    
393                            case '4':
394                                    g_use_rdp5 = False;
395                                    break;
396    
397                            case '5':
398                                    g_use_rdp5 = True;
399                                  break;                                  break;
400    
401                          case 'h':                          case 'h':
# Line 173  main(int argc, char *argv[]) Line 412  main(int argc, char *argv[])
412                  return 1;                  return 1;
413          }          }
414    
415          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
416            parse_server_and_port(server);
417    
418          if (username[0] == 0)          if (!username_option)
419          {          {
420                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
421                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
# Line 184  main(int argc, char *argv[]) Line 424  main(int argc, char *argv[])
424                          return 1;                          return 1;
425                  }                  }
426    
427                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
428          }          }
429    
430          if (hostname[0] == 0)          if (hostname[0] == 0)
# Line 202  main(int argc, char *argv[]) Line 442  main(int argc, char *argv[])
442                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(hostname, fullhostname, sizeof(hostname));
443          }          }
444    
445          if (!strcmp(password, "-"))          if (prompt_password && read_password(password, sizeof(password)))
446          {                  flags |= RDP_LOGON_AUTO;
                 p = getpass("Password: ");  
                 if (p == NULL)  
                 {  
                         error("failed to read password\n");  
                         return 0;  
                 }  
                 STRNCPY(password, p, sizeof(password));  
         }  
447    
448          if ((width == 0) || (height == 0))          if (g_title[0] == 0)
449          {          {
450                  width = 800;                  strcpy(g_title, "rdesktop - ");
451                  height = 600;                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
452          }          }
453    
454          strcpy(title, "rdesktop - ");  #ifdef RDP2VNC
455          strncat(title, server, sizeof(title) - sizeof("rdesktop - "));          rdp2vnc_connect(server, flags, domain, password, shell, directory);
456            return 0;
457    #else
458    
459          xkeymap_init1();          if (!ui_init())
460                    return 1;
461    
462    #ifdef WITH_RDPSND
463            if (g_rdpsnd)
464                    rdpsnd_init();
465    #endif
466            /* rdpdr_init(); */
467    
468          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (!rdp_connect(server, flags, domain, password, shell, directory))
469                  return 1;                  return 1;
470    
471          printf("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
472               packet but unencrypted transfer of other packets */
473            if (!packet_encryption)
474                    g_encryption = False;
475    
476    
477          if (ui_create_window(title))          DEBUG(("Connection successful.\n"));
478            memset(password, 0, sizeof(password));
479    
480            if (ui_create_window())
481          {          {
482                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
483                  ui_destroy_window();                  ui_destroy_window();
484          }          }
485    
486          printf("Disconnecting...\n");          DEBUG(("Disconnecting...\n"));
487          rdp_disconnect();          rdp_disconnect();
488          return 0;          ui_deinit();
489    
490            if (True == rdp_retval)
491                    return 0;
492            else
493                    return 2;
494    
495    #endif
496    
497    }
498    
499    #ifdef EGD_SOCKET
500    /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
501    static BOOL
502    generate_random_egd(uint8 * buf)
503    {
504            struct sockaddr_un addr;
505            BOOL ret = False;
506            int fd;
507    
508            fd = socket(AF_UNIX, SOCK_STREAM, 0);
509            if (fd == -1)
510                    return False;
511    
512            addr.sun_family = AF_UNIX;
513            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
514            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
515                    goto err;
516    
517            /* PRNGD and EGD use a simple communications protocol */
518            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
519            buf[1] = 32;            /* Number of requested random bytes */
520            if (write(fd, buf, 2) != 2)
521                    goto err;
522    
523            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
524                    goto err;
525    
526            if (read(fd, buf, 32) != 32)
527                    goto err;
528    
529            ret = True;
530    
531          err:
532            close(fd);
533            return ret;
534  }  }
535    #endif
536    
537  /* Generate a 32-byte random for the secure transport code. */  /* Generate a 32-byte random for the secure transport code. */
538  void  void
# Line 246  generate_random(uint8 * random) Line 540  generate_random(uint8 * random)
540  {  {
541          struct stat st;          struct stat st;
542          struct tms tmsbuf;          struct tms tmsbuf;
543          uint32 *r = (uint32 *) random;          MD5_CTX md5;
544          int fd;          uint32 *r;
545            int fd, n;
546    
547          /* If we have a kernel random device, use it. */          /* If we have a kernel random device, try that first */
548          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
549              || ((fd = open("/dev/random", O_RDONLY)) != -1))              || ((fd = open("/dev/random", O_RDONLY)) != -1))
550          {          {
551                  read(fd, random, 32);                  n = read(fd, random, 32);
552                  close(fd);                  close(fd);
553                  return;                  if (n == 32)
554                            return;
555          }          }
556    
557    #ifdef EGD_SOCKET
558            /* As a second preference use an EGD */
559            if (generate_random_egd(random))
560                    return;
561    #endif
562    
563          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
564            r = (uint32 *) random;
565          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
566          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
567          r[2] = times(&tmsbuf);  /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
# Line 267  generate_random(uint8 * random) Line 570  generate_random(uint8 * random)
570          r[5] = st.st_atime;          r[5] = st.st_atime;
571          r[6] = st.st_mtime;          r[6] = st.st_mtime;
572          r[7] = st.st_ctime;          r[7] = st.st_ctime;
573    
574            /* Hash both halves with MD5 to obscure possible patterns */
575            MD5_Init(&md5);
576            MD5_Update(&md5, random, 16);
577            MD5_Final(random, &md5);
578            MD5_Update(&md5, random + 16, 16);
579            MD5_Final(random + 16, &md5);
580  }  }
581    
582  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
# Line 315  error(char *format, ...) Line 625  error(char *format, ...)
625          va_end(ap);          va_end(ap);
626  }  }
627    
628    /* report a warning */
629    void
630    warning(char *format, ...)
631    {
632            va_list ap;
633    
634            fprintf(stderr, "WARNING: ");
635    
636            va_start(ap, format);
637            vfprintf(stderr, format, ap);
638            va_end(ap);
639    }
640    
641  /* report an unimplemented protocol feature */  /* report an unimplemented protocol feature */
642  void  void
643  unimpl(char *format, ...)  unimpl(char *format, ...)
# Line 330  unimpl(char *format, ...) Line 653  unimpl(char *format, ...)
653    
654  /* produce a hex dump */  /* produce a hex dump */
655  void  void
656  hexdump(unsigned char *p, unsigned int len)  hexdump(unsigned char *p, int len)
657  {  {
658          unsigned char *line = p;          unsigned char *line = p;
659          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
660    
661          while (offset < len)          while (offset < len)
662          {          {
# Line 350  hexdump(unsigned char *p, unsigned int l Line 672  hexdump(unsigned char *p, unsigned int l
672                          printf("   ");                          printf("   ");
673    
674                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
675                          printf("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
676    
677                  printf("\n");                  printf("\n");
678                  offset += thisline;                  offset += thisline;
# Line 360  hexdump(unsigned char *p, unsigned int l Line 680  hexdump(unsigned char *p, unsigned int l
680          }          }
681  }  }
682    
683    
684  int  int
685  load_licence(unsigned char **data)  load_licence(unsigned char **data)
686  {  {
687          char path[PATH_MAX];          char *home, *path;
         char *home;  
688          struct stat st;          struct stat st;
689          int fd;          int fd, length;
690    
691          home = getenv("HOME");          home = getenv("HOME");
692          if (home == NULL)          if (home == NULL)
693                  return -1;                  return -1;
694    
695          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
696          strncat(path, "/.rdesktop/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
697    
698          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
699          if (fd == -1)          if (fd == -1)
# Line 382  load_licence(unsigned char **data) Line 702  load_licence(unsigned char **data)
702          if (fstat(fd, &st))          if (fstat(fd, &st))
703                  return -1;                  return -1;
704    
705          *data = xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
706          return read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
707            close(fd);
708            xfree(path);
709            return length;
710  }  }
711    
712  void  void
713  save_licence(unsigned char *data, int length)  save_licence(unsigned char *data, int length)
714  {  {
715          char path[PATH_MAX];          char *home, *path, *tmppath;
         char *home;  
716          int fd;          int fd;
717    
718          home = getenv("HOME");          home = getenv("HOME");
719          if (home == NULL)          if (home == NULL)
720                  return;                  return;
721    
722          STRNCPY(path, home, sizeof(path));          path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
         strncat(path, "/.rdesktop", sizeof(path) - strlen(path) - 1);  
         mkdir(path, 0700);  
723    
724          strncat(path, "/licence", sizeof(path) - strlen(path) - 1);          sprintf(path, "%s/.rdesktop", home);
725            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
726            {
727                    perror(path);
728                    return;
729            }
730    
731            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
732    
733          fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0600);          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
734            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
735            strcpy(tmppath, path);
736            strcat(tmppath, ".new");
737    
738            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
739          if (fd == -1)          if (fd == -1)
740          {          {
741                  perror("open");                  perror(tmppath);
742                  return;                  return;
743          }          }
744    
745          write(fd, data, length);          if (write(fd, data, length) != length)
746            {
747                    perror(tmppath);
748                    unlink(tmppath);
749            }
750            else if (rename(tmppath, path) == -1)
751            {
752                    perror(path);
753                    unlink(tmppath);
754            }
755    
756          close(fd);          close(fd);
757            xfree(tmppath);
758            xfree(path);
759  }  }

Legend:
Removed from v.66  
changed lines
  Added in v.520

  ViewVC Help
Powered by ViewVC 1.1.26