/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 648 - (show annotations)
Sat Apr 10 09:34:52 2004 UTC (20 years, 1 month ago) by stargo
Original Path: sourceforge.net/trunk/rdesktop/rdesktop.c
File MIME type: text/plain
File size: 21311 byte(s)
rdp2vnc fixes from Johannes Schindelin <Johannes.Schindelin@gmx.de>

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

  ViewVC Help
Powered by ViewVC 1.1.26