/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c

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

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

Legend:
Removed from v.10  
changed lines
  Added in v.450

  ViewVC Help
Powered by ViewVC 1.1.26