/[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 10 by matty, Tue Aug 15 10:23:24 2000 UTC revision 582 by n-ki, Fri Jan 23 14:37:51 2004 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 <ctype.h>              /* toupper */
30    #include <errno.h>
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33  char username[16];  #ifdef EGD_SOCKET
34    #include <sys/socket.h>         /* socket connect */
35    #include <sys/un.h>             /* sockaddr_un */
36    #endif
37    
38    #ifdef WITH_OPENSSL
39    #include <openssl/md5.h>
40    #else
41    #include "crypto/md5.h"
42    #endif
43    
44    char g_title[64] = "";
45    char g_username[64];
46  char hostname[16];  char hostname[16];
47  int width = 800;  char keymapname[16];
48  int height = 600;  int keylayout = 0x409;          /* Defaults to US keyboard layout */
 int keylayout = 0x409;  
 BOOL motion = False;  
 BOOL orders = True;  
 BOOL licence = True;  
49    
50    int g_width = 800;              /* width is special: If 0, the
51                                       geometry will be fetched from
52                                       _NET_WORKAREA. If negative,
53                                       absolute value specifies the
54                                       percent of the whole screen. */
55    int g_height = 600;
56    int tcp_port_rdp = TCP_PORT_RDP;
57    int g_server_bpp = 8;
58    int g_win_button_size = 0;      /* If zero, disable single app mode */
59    BOOL g_bitmap_compression = True;
60    BOOL g_sendmotion = True;
61    BOOL g_orders = True;
62    BOOL g_encryption = True;
63    BOOL packet_encryption = True;
64    BOOL g_desktop_save = True;
65    BOOL g_fullscreen = False;
66    BOOL g_grab_keyboard = True;
67    BOOL g_hide_decorations = False;
68    BOOL g_use_rdp5 = True;
69    BOOL g_console_session = False;
70    BOOL g_numlock_sync = False;
71    extern BOOL g_owncolmap;
72    
73    #ifdef WITH_RDPSND
74    BOOL g_rdpsnd = False;
75    #endif
76    
77    extern RDPDR_DEVICE g_rdpdr_device[];
78    extern uint32 g_num_devices;
79    
80    #ifdef RDP2VNC
81    extern int rfb_port;
82    extern int defer_time;
83    void
84    rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
85                    char *shell, char *directory);
86    #endif
87  /* Display usage information */  /* Display usage information */
88  static void usage(char *program)  static void
89    usage(char *program)
90    {
91            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
92            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");
93            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
94    
95            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
96    #ifdef RDP2VNC
97            fprintf(stderr, "   -V: vnc port\n");
98            fprintf(stderr, "   -Q: defer time (ms)\n");
99    #endif
100            fprintf(stderr, "   -u: user name\n");
101            fprintf(stderr, "   -d: domain\n");
102            fprintf(stderr, "   -s: shell\n");
103            fprintf(stderr, "   -c: working directory\n");
104            fprintf(stderr, "   -p: password (- to prompt)\n");
105            fprintf(stderr, "   -n: client hostname\n");
106            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
107            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
108            fprintf(stderr, "   -f: full-screen mode\n");
109            fprintf(stderr, "   -b: force bitmap updates\n");
110            fprintf(stderr, "   -e: disable encryption (French TS)\n");
111            fprintf(stderr, "   -E: disable encryption from client to server\n");
112            fprintf(stderr, "   -m: do not send motion events\n");
113            fprintf(stderr, "   -C: use private colour map\n");
114            fprintf(stderr, "   -D: hide window manager decorations\n");
115            fprintf(stderr, "   -K: keep window manager key bindings\n");
116            fprintf(stderr, "   -S: caption button size (single application mode)\n");
117            fprintf(stderr, "   -T: window title\n");
118            fprintf(stderr, "   -N: enable numlock syncronization\n");
119            fprintf(stderr, "   -a: connection colour depth\n");
120            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
121            fprintf(stderr,
122                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
123            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
124            fprintf(stderr,
125                    "         '-r disk:A=/mnt/floppy': enable redirection of /mnt/floppy to A:\n");
126            fprintf(stderr, "             or   A=/mnt/floppy,D=/mnt/cdrom'\n");
127            fprintf(stderr,
128                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
129            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
130            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
131            fprintf(stderr,
132                    "             or       mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
133            fprintf(stderr, "         '-r sound': enable sound redirection\n");
134            fprintf(stderr, "   -0: attach to console\n");
135            fprintf(stderr, "   -4: use RDP version 4\n");
136            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
137    }
138    
139    static BOOL
140    read_password(char *password, int size)
141    {
142            struct termios tios;
143            BOOL ret = False;
144            int istty = 0;
145            char *p;
146    
147            if (tcgetattr(STDIN_FILENO, &tios) == 0)
148            {
149                    fprintf(stderr, "Password: ");
150                    tios.c_lflag &= ~ECHO;
151                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
152                    istty = 1;
153            }
154    
155            if (fgets(password, size, stdin) != NULL)
156            {
157                    ret = True;
158    
159                    /* strip final newline */
160                    p = strchr(password, '\n');
161                    if (p != NULL)
162                            *p = 0;
163            }
164    
165            if (istty)
166            {
167                    tios.c_lflag |= ECHO;
168                    tcsetattr(STDIN_FILENO, TCSANOW, &tios);
169                    fprintf(stderr, "\n");
170            }
171    
172            return ret;
173    }
174    
175    static void
176    parse_server_and_port(char *server)
177  {  {
178          STATUS("Usage: %s [options] server\n", program);          char *p;
179          STATUS("   -u: user name\n");  #ifdef IPv6
180          STATUS("   -n: client hostname\n");          int addr_colons;
181          STATUS("   -w: desktop width\n");  #endif
182          STATUS("   -h: desktop height\n");  
183          STATUS("   -k: keyboard layout (hex)\n");  #ifdef IPv6
184          STATUS("   -m: send motion events\n");          p = server;
185          STATUS("   -b: force bitmap updates\n");          addr_colons = 0;
186          STATUS("   -l: do not request licence\n\n");          while (*p)
187                    if (*p++ == ':')
188                            addr_colons++;
189            if (addr_colons >= 2)
190            {
191                    /* numeric IPv6 style address format - [1:2:3::4]:port */
192                    p = strchr(server, ']');
193                    if (*server == '[' && p != NULL)
194                    {
195                            if (*(p + 1) == ':' && *(p + 2) != '\0')
196                                    tcp_port_rdp = strtol(p + 2, NULL, 10);
197                            /* remove the port number and brackets from the address */
198                            *p = '\0';
199                            strncpy(server, server + 1, strlen(server));
200                    }
201            }
202            else
203            {
204                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
205                    p = strchr(server, ':');
206                    if (p != NULL)
207                    {
208                            tcp_port_rdp = strtol(p + 1, NULL, 10);
209                            *p = 0;
210                    }
211            }
212    #else /* no IPv6 support */
213            p = strchr(server, ':');
214            if (p != NULL)
215            {
216                    tcp_port_rdp = strtol(p + 1, NULL, 10);
217                    *p = 0;
218            }
219    #endif /* IPv6 */
220    
221  }  }
222    
223  /* Client program */  /* Client program */
224  int main(int argc, char *argv[])  int
225    main(int argc, char *argv[])
226  {  {
227            char server[64];
228            char fullhostname[64];
229            char domain[16];
230            char password[64];
231            char shell[128];
232            char directory[32];
233            BOOL prompt_password, rdp_retval = False;
234          struct passwd *pw;          struct passwd *pw;
235          char *server;          uint32 flags;
236          char title[32];          char *p;
237          int c;          int c;
238    
239          STATUS("rdesktop: A Remote Desktop Protocol client.\n");          int username_option = 0;
         STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n\n");  
240    
241          while ((c = getopt(argc, argv, "u:n:w:h:k:mbl?")) != -1)          flags = RDP_LOGON_NORMAL;
242            prompt_password = False;
243            domain[0] = password[0] = shell[0] = directory[0] = 0;
244            strcpy(keymapname, "en-us");
245    
246            g_num_devices = 0;
247    
248    #ifdef RDP2VNC
249    #define VNCOPT "V:Q:"
250    #else
251    #define VNCOPT
252    #endif
253    
254            while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbeEmCDKS:T:Na:r:045h?")) != -1)
255          {          {
256                  switch (c)                  switch (c)
257                  {                  {
258    #ifdef RDP2VNC
259                            case 'V':
260                                    rfb_port = strtol(optarg, NULL, 10);
261                                    if (rfb_port < 100)
262                                            rfb_port += 5900;
263                                    break;
264    
265                            case 'Q':
266                                    defer_time = strtol(optarg, NULL, 10);
267                                    if (defer_time < 0)
268                                            defer_time = 0;
269                                    break;
270    #endif
271    
272                          case 'u':                          case 'u':
273                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
274                                    username_option = 1;
275                                  break;                                  break;
276    
277                          case 'n':                          case 'd':
278                                  strncpy(hostname, optarg, sizeof(hostname));                                  STRNCPY(domain, optarg, sizeof(domain));
279                                  break;                                  break;
280    
281                          case 'w':                          case 's':
282                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
283                                  break;                                  break;
284    
285                          case 'h':                          case 'c':
286                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(directory, optarg, sizeof(directory));
287                                    break;
288    
289                            case 'p':
290                                    if ((optarg[0] == '-') && (optarg[1] == 0))
291                                    {
292                                            prompt_password = True;
293                                            break;
294                                    }
295    
296                                    STRNCPY(password, optarg, sizeof(password));
297                                    flags |= RDP_LOGON_AUTO;
298    
299                                    /* try to overwrite argument so it won't appear in ps */
300                                    p = optarg;
301                                    while (*p)
302                                            *(p++) = 'X';
303                                    break;
304    
305                            case 'n':
306                                    STRNCPY(hostname, optarg, sizeof(hostname));
307                                  break;                                  break;
308    
309                          case 'k':                          case 'k':
310                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(keymapname, optarg, sizeof(keymapname));
311                                  break;                                  break;
312    
313                          case 'm':                          case 'g':
314                                  motion = True;                                  g_fullscreen = False;
315                                    if (!strcmp(optarg, "workarea"))
316                                    {
317                                            g_width = g_height = 0;
318                                            break;
319                                    }
320    
321                                    g_width = strtol(optarg, &p, 10);
322                                    if (g_width <= 0)
323                                    {
324                                            error("invalid geometry\n");
325                                            return 1;
326                                    }
327    
328                                    if (*p == 'x')
329                                            g_height = strtol(p + 1, NULL, 10);
330    
331                                    if (g_height <= 0)
332                                    {
333                                            error("invalid geometry\n");
334                                            return 1;
335                                    }
336    
337                                    if (*p == '%')
338                                            g_width = -g_width;
339    
340                                    break;
341    
342                            case 'f':
343                                    g_fullscreen = True;
344                                  break;                                  break;
345    
346                          case 'b':                          case 'b':
347                                  orders = False;                                  g_orders = False;
348                                    break;
349    
350                            case 'e':
351                                    g_encryption = False;
352                                    break;
353                            case 'E':
354                                    packet_encryption = False;
355                                    break;
356                            case 'm':
357                                    g_sendmotion = False;
358                                    break;
359    
360                            case 'C':
361                                    g_owncolmap = True;
362                                    break;
363    
364                            case 'D':
365                                    g_hide_decorations = True;
366                                    break;
367    
368                            case 'K':
369                                    g_grab_keyboard = False;
370                                    break;
371    
372                            case 'S':
373                                    if (!strcmp(optarg, "standard"))
374                                    {
375                                            g_win_button_size = 18;
376                                            break;
377                                    }
378    
379                                    g_win_button_size = strtol(optarg, &p, 10);
380    
381                                    if (*p)
382                                    {
383                                            error("invalid button size\n");
384                                            return 1;
385                                    }
386    
387                                    break;
388    
389                            case 'T':
390                                    STRNCPY(g_title, optarg, sizeof(g_title));
391                                    break;
392    
393                            case 'N':
394                                    g_numlock_sync = True;
395                                    break;
396    
397                            case 'a':
398                                    g_server_bpp = strtol(optarg, NULL, 10);
399                                    if (g_server_bpp != 8 && g_server_bpp != 16 && g_server_bpp != 15
400                                        && g_server_bpp != 24)
401                                    {
402                                            error("invalid server bpp\n");
403                                            return 1;
404                                    }
405                                    break;
406    
407                            case 'r':
408    
409                                    if (strncmp("sound", optarg, 5) == 0)
410                                    {
411    #ifdef WITH_RDPSND
412                                            g_rdpsnd = True;
413    #else
414                                            warning("Not compiled with sound support");
415    #endif
416                                    }
417                                    else if (strncmp("disk", optarg, 4) == 0)
418                                    {
419                                            /* -r disk:h:=/mnt/floppy */
420                                            disk_enum_devices(&g_num_devices, optarg + 4);
421                                    }
422                                    else if (strncmp("comport", optarg, 7) == 0)
423                                    {
424                                            serial_enum_devices(&g_num_devices, optarg + 7);
425                                    }
426                                    else if (strncmp("lptport", optarg, 7) == 0)
427                                    {
428                                            parallel_enum_devices(&g_num_devices, optarg + 7);
429                                    }
430                                    else if (strncmp("printer", optarg, 7) == 0)
431                                    {
432                                            printer_enum_devices(&g_num_devices, optarg + 7);
433                                    }
434                                    else
435                                    {
436                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
437                                    }
438                                    break;
439    
440                            case '0':
441                                    g_console_session = True;
442                                  break;                                  break;
443    
444                          case 'l':                          case '4':
445                                  licence = False;                                  g_use_rdp5 = False;
446                                  break;                                  break;
447    
448                            case '5':
449                                    g_use_rdp5 = True;
450                                    break;
451    
452                            case 'h':
453                          case '?':                          case '?':
454                          default:                          default:
455                                  usage(argv[0]);                                  usage(argv[0]);
# Line 111  int main(int argc, char *argv[]) Line 463  int main(int argc, char *argv[])
463                  return 1;                  return 1;
464          }          }
465    
466          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
467            parse_server_and_port(server);
468    
469          if (username[0] == 0)          if (!username_option)
470          {          {
471                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
472                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
473                  {                  {
474                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
475                          return 1;                          return 1;
476                  }                  }
477    
478                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
479          }          }
480    
481          if (hostname[0] == 0)          if (hostname[0] == 0)
482          {          {
483                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
484                  {                  {
485                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
486                          return 1;                          return 1;
487                  }                  }
488    
489                    p = strchr(fullhostname, '.');
490                    if (p != NULL)
491                            *p = 0;
492    
493                    STRNCPY(hostname, fullhostname, sizeof(hostname));
494            }
495    
496            if (prompt_password && read_password(password, sizeof(password)))
497                    flags |= RDP_LOGON_AUTO;
498    
499            if (g_title[0] == 0)
500            {
501                    strcpy(g_title, "rdesktop - ");
502                    strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
503          }          }
504    
505          if (!rdp_connect(server))  #ifdef RDP2VNC
506            rdp2vnc_connect(server, flags, domain, password, shell, directory);
507            return 0;
508    #else
509    
510            if (!ui_init())
511                    return 1;
512    
513    #ifdef WITH_RDPSND
514            if (g_rdpsnd)
515                    rdpsnd_init();
516    #endif
517            rdpdr_init();
518    
519            if (!rdp_connect(server, flags, domain, password, shell, directory))
520                  return 1;                  return 1;
521    
522          STATUS("Connection successful.\n");          /* By setting encryption to False here, we have an encrypted login
523               packet but unencrypted transfer of other packets */
524            if (!packet_encryption)
525                    g_encryption = False;
526    
527    
528          snprintf(title, sizeof(title), "rdesktop - %s", server);          DEBUG(("Connection successful.\n"));
529          if (ui_create_window(title))          memset(password, 0, sizeof(password));
530    
531            if (ui_create_window())
532          {          {
533                  rdp_main_loop();                  rdp_retval = rdp_main_loop();
534                  ui_destroy_window();                  ui_destroy_window();
535          }          }
536    
537            DEBUG(("Disconnecting...\n"));
538          rdp_disconnect();          rdp_disconnect();
539          return 0;          ui_deinit();
540    
541            if (True == rdp_retval)
542                    return 0;
543            else
544                    return 2;
545    
546    #endif
547    
548  }  }
549    
550  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
551  void generate_random(uint8 *random)  /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
552    static BOOL
553    generate_random_egd(uint8 * buf)
554  {  {
555          struct stat st;          struct sockaddr_un addr;
556          uint32 *r = (uint32 *)random;          BOOL ret = False;
557          int fd;          int fd;
558    
559          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
560          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (fd == -1)
561                    return False;
562    
563            addr.sun_family = AF_UNIX;
564            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
565            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
566                    goto err;
567    
568            /* PRNGD and EGD use a simple communications protocol */
569            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
570            buf[1] = 32;            /* Number of requested random bytes */
571            if (write(fd, buf, 2) != 2)
572                    goto err;
573    
574            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
575                    goto err;
576    
577            if (read(fd, buf, 32) != 32)
578                    goto err;
579    
580            ret = True;
581    
582          err:
583            close(fd);
584            return ret;
585    }
586    #endif
587    
588    /* Generate a 32-byte random for the secure transport code. */
589    void
590    generate_random(uint8 * random)
591    {
592            struct stat st;
593            struct tms tmsbuf;
594            MD5_CTX md5;
595            uint32 *r;
596            int fd, n;
597    
598            /* If we have a kernel random device, try that first */
599            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
600                || ((fd = open("/dev/random", O_RDONLY)) != -1))
601          {          {
602                  read(fd, random, 32);                  n = read(fd, random, 32);
603                  close(fd);                  close(fd);
604                  return;                  if (n == 32)
605                            return;
606          }          }
607    
608    #ifdef EGD_SOCKET
609            /* As a second preference use an EGD */
610            if (generate_random_egd(random))
611                    return;
612    #endif
613    
614          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
615            r = (uint32 *) random;
616          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
617          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
618          r[2] = times(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
619          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
620          stat("/tmp", &st);          stat("/tmp", &st);
621          r[5] = st.st_atime;          r[5] = st.st_atime;
622          r[6] = st.st_mtime;          r[6] = st.st_mtime;
623          r[7] = st.st_ctime;          r[7] = st.st_ctime;
624    
625            /* Hash both halves with MD5 to obscure possible patterns */
626            MD5_Init(&md5);
627            MD5_Update(&md5, random, 16);
628            MD5_Final(random, &md5);
629            MD5_Update(&md5, random + 16, 16);
630            MD5_Final(random + 16, &md5);
631  }  }
632    
633  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
634  void *xmalloc(int size)  void *
635    xmalloc(int size)
636  {  {
637          void *mem = malloc(size);          void *mem = malloc(size);
638          if (mem == NULL)          if (mem == NULL)
639          {          {
640                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
641                  exit(1);                  exit(1);
642          }          }
643          return mem;          return mem;
644  }  }
645    
646  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
647  void *xrealloc(void *oldmem, int size)  void *
648    xrealloc(void *oldmem, int size)
649  {  {
650          void *mem = realloc(oldmem, size);          void *mem = realloc(oldmem, size);
651          if (mem == NULL)          if (mem == NULL)
652          {          {
653                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
654                  exit(1);                  exit(1);
655          }          }
656          return mem;          return mem;
657  }  }
658    
659  /* free */  /* free */
660  void xfree(void *mem)  void
661    xfree(void *mem)
662  {  {
663          free(mem);          free(mem);
664  }  }
665    
666  /* Produce a hex dump */  /* report an error */
667  void hexdump(unsigned char *p, unsigned int len)  void
668    error(char *format, ...)
669    {
670            va_list ap;
671    
672            fprintf(stderr, "ERROR: ");
673    
674            va_start(ap, format);
675            vfprintf(stderr, format, ap);
676            va_end(ap);
677    }
678    
679    /* report a warning */
680    void
681    warning(char *format, ...)
682    {
683            va_list ap;
684    
685            fprintf(stderr, "WARNING: ");
686    
687            va_start(ap, format);
688            vfprintf(stderr, format, ap);
689            va_end(ap);
690    }
691    
692    /* report an unimplemented protocol feature */
693    void
694    unimpl(char *format, ...)
695    {
696            va_list ap;
697    
698            fprintf(stderr, "NOT IMPLEMENTED: ");
699    
700            va_start(ap, format);
701            vfprintf(stderr, format, ap);
702            va_end(ap);
703    }
704    
705    /* produce a hex dump */
706    void
707    hexdump(unsigned char *p, unsigned int len)
708  {  {
709          unsigned char *line = p;          unsigned char *line = p;
710          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
711    
712          while (offset < len)          while (offset < len)
713          {          {
714                  STATUS("%04x ", offset);                  printf("%04x ", offset);
715                  thisline = len - offset;                  thisline = len - offset;
716                  if (thisline > 16)                  if (thisline > 16)
717                          thisline = 16;                          thisline = 16;
718    
719                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
720                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
721    
722                  for (; i < 16; i++)                  for (; i < 16; i++)
723                          STATUS("   ");                          printf("   ");
724    
725                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
726                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
727    
728                  STATUS("\n");                  printf("\n");
729                  offset += thisline;                  offset += thisline;
730                  line += thisline;                  line += thisline;
731          }          }
732  }  }
733    
734    /*
735      input: src is the string we look in for needle
736      return value: returns next src pointer, for
737            succesive executions, like in a while loop
738            if retval is 0, then there are no more args.
739      pitfalls:
740            src is modified. 0x00 chars are inserted to
741            terminate strings.
742            return val, points on the next val chr after ins
743            0x00
744    
745            example usage:
746            while( (pos = next_arg( optarg, ',')) ){
747                    printf("%s\n",optarg);
748                    optarg=pos;
749            }
750    
751    */
752    char *
753    next_arg(char *src, char needle)
754    {
755            char *nextval;
756            char *p;
757            char *mvp = 0;
758    
759            /* EOS */
760            if (*src == (char) 0x00)
761                    return 0;
762    
763            p = src;
764            /*  skip escaped needles */
765            while ((nextval = strchr(p, needle)))
766            {
767                    mvp = nextval - 1;
768                    /* found backslashed needle */
769                    if (*mvp == '\\' && (mvp > src))
770                    {
771                            /* move string one to the left */
772                            while (*(mvp + 1) != (char) 0x00)
773                            {
774                                    *mvp = *(mvp + 1);
775                                    *mvp++;
776                            }
777                            *mvp = (char) 0x00;
778                            p = nextval;
779                    }
780                    else
781                    {
782                            p = nextval + 1;
783                            break;
784                    }
785    
786            }
787    
788            /* more args available */
789            if (nextval)
790            {
791                    *nextval = (char) 0x00;
792                    return ++nextval;
793            }
794    
795            /* no more args after this, jump to EOS */
796            nextval = src + strlen(src);
797            return nextval;
798    }
799    
800    
801    void
802    toupper_str(char *p)
803    {
804            while (*p)
805            {
806                    if ((*p >= 'a') && (*p <= 'z'))
807                            *p = toupper((int) *p);
808                    p++;
809            }
810    }
811    
812    
813    /* not all clibs got ltoa */
814    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
815    
816    char *
817    ltoa(long N, int base)
818    {
819            static char ret[LTOA_BUFSIZE];
820    
821            register int i = 2;
822            long uarg;
823            char *tail, *head = ret, buf[LTOA_BUFSIZE];
824    
825            if (36 < base || 2 > base)
826                    base = 10;
827    
828            tail = &buf[LTOA_BUFSIZE - 1];
829            *tail-- = '\0';
830    
831            if (10 == base && N < 0L)
832            {
833                    *head++ = '-';
834                    uarg = -N;
835            }
836            else
837                    uarg = N;
838    
839            if (uarg)
840            {
841                    for (i = 1; uarg; ++i)
842                    {
843                            register ldiv_t r;
844    
845                            r = ldiv(uarg, base);
846                            *tail-- = (char) (r.rem + ((9L < r.rem) ? ('A' - 10L) : '0'));
847                            uarg = r.quot;
848                    }
849            }
850            else
851                    *tail-- = '0';
852    
853            memcpy(head, ++tail, i);
854            return ret;
855    }
856    
857    
858    int
859    load_licence(unsigned char **data)
860    {
861            char *home, *path;
862            struct stat st;
863            int fd, length;
864    
865            home = getenv("HOME");
866            if (home == NULL)
867                    return -1;
868    
869            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
870            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
871    
872            fd = open(path, O_RDONLY);
873            if (fd == -1)
874                    return -1;
875    
876            if (fstat(fd, &st))
877                    return -1;
878    
879            *data = (uint8 *) xmalloc(st.st_size);
880            length = read(fd, *data, st.st_size);
881            close(fd);
882            xfree(path);
883            return length;
884    }
885    
886    void
887    save_licence(unsigned char *data, int length)
888    {
889            char *home, *path, *tmppath;
890            int fd;
891    
892            home = getenv("HOME");
893            if (home == NULL)
894                    return;
895    
896            path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));
897    
898            sprintf(path, "%s/.rdesktop", home);
899            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
900            {
901                    perror(path);
902                    return;
903            }
904    
905            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
906    
907            sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);
908            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
909            strcpy(tmppath, path);
910            strcat(tmppath, ".new");
911    
912            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
913            if (fd == -1)
914            {
915                    perror(tmppath);
916                    return;
917            }
918    
919            if (write(fd, data, length) != length)
920            {
921                    perror(tmppath);
922                    unlink(tmppath);
923            }
924            else if (rename(tmppath, path) == -1)
925            {
926                    perror(path);
927                    unlink(tmppath);
928            }
929    
930            close(fd);
931            xfree(tmppath);
932            xfree(path);
933    }

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

  ViewVC Help
Powered by ViewVC 1.1.26