/[rdesktop]/jpeg/rdesktop/trunk/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

Annotation of /jpeg/rdesktop/trunk/rdesktop.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1207 - (hide annotations)
Mon Mar 27 09:20:24 2006 UTC (18 years, 1 month ago) by ossman_
Original Path: sourceforge.net/trunk/rdesktop/rdesktop.c
File MIME type: text/plain
File size: 33094 byte(s)
Control clipboard behaviour (and even disable it) using command line options.

1 forsberg 350 /* -*- c-basic-offset: 8 -*-
2 matty 10 rdesktop: A Remote Desktop Protocol client.
3     Entrypoint and utility functions
4 stargo 828 Copyright (C) Matthew Chapman 1999-2005
5 jsorg71 100
6 matty 10 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 jsorg71 100
11 matty 10 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 jsorg71 100
16 matty 10 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 matty 30 #include <stdarg.h> /* va_list va_start va_end */
22 matty 24 #include <unistd.h> /* read close getuid getgid getpid getppid gethostname */
23     #include <fcntl.h> /* open */
24     #include <pwd.h> /* getpwuid */
25 matthewc 211 #include <termios.h> /* tcgetattr tcsetattr */
26 matty 24 #include <sys/stat.h> /* stat */
27     #include <sys/time.h> /* gettimeofday */
28     #include <sys/times.h> /* times */
29 stargo 570 #include <ctype.h> /* toupper */
30 astrand 325 #include <errno.h>
31 matty 10 #include "rdesktop.h"
32    
33 stargo 857 #ifdef HAVE_LOCALE_H
34 stargo 855 #include <locale.h>
35 stargo 857 #endif
36 astrand 962 #ifdef HAVE_ICONV
37 stargo 857 #ifdef HAVE_LANGINFO_H
38 stargo 855 #include <langinfo.h>
39     #endif
40 stargo 857 #endif
41 stargo 855
42 matthewc 220 #ifdef EGD_SOCKET
43 stargo 881 #include <sys/types.h>
44 matthewc 220 #include <sys/socket.h> /* socket connect */
45     #include <sys/un.h> /* sockaddr_un */
46     #endif
47    
48     #include <openssl/md5.h>
49    
50 astrand 479 char g_title[64] = "";
51     char g_username[64];
52 jsorg71 710 char g_hostname[16];
53 astrand 975 char g_keymapname[PATH_MAX] = "";
54 astrand 1035 unsigned int g_keylayout = 0x409; /* Defaults to US keyboard layout */
55 astrand 964 int g_keyboard_type = 0x4; /* Defaults to US keyboard layout */
56     int g_keyboard_subtype = 0x0; /* Defaults to US keyboard layout */
57     int g_keyboard_functionkeys = 0xc; /* Defaults to US keyboard layout */
58 astrand 500
59     int g_width = 800; /* width is special: If 0, the
60     geometry will be fetched from
61     _NET_WORKAREA. If negative,
62     absolute value specifies the
63     percent of the whole screen. */
64 jsorg71 447 int g_height = 600;
65 stargo 800 int g_xpos = 0;
66     int g_ypos = 0;
67 stargo 867 int g_pos = 0; /* 0 position unspecified,
68     1 specified,
69     2 xpos neg,
70     4 ypos neg */
71 jsorg71 710 extern int g_tcp_port_rdp;
72 astrand 1042 int g_server_depth = 8;
73 jsorg71 450 int g_win_button_size = 0; /* If zero, disable single app mode */
74 jsorg71 437 BOOL g_bitmap_compression = True;
75 jsorg71 447 BOOL g_sendmotion = True;
76 jsorg71 678 BOOL g_bitmap_cache = True;
77 jsorg71 725 BOOL g_bitmap_cache_persist_enable = False;
78     BOOL g_bitmap_cache_precache = True;
79 jsorg71 437 BOOL g_encryption = True;
80 forsberg 427 BOOL packet_encryption = True;
81 jsorg71 848 BOOL g_desktop_save = True; /* desktop save order */
82     BOOL g_polygon_ellipse_orders = True; /* polygon / ellipse orders */
83 jsorg71 447 BOOL g_fullscreen = False;
84 jsorg71 450 BOOL g_grab_keyboard = True;
85     BOOL g_hide_decorations = False;
86 astrand 458 BOOL g_use_rdp5 = True;
87 ossman_ 1207 BOOL g_rdpclip = True;
88 matthewc 482 BOOL g_console_session = False;
89 astrand 552 BOOL g_numlock_sync = False;
90 astrand 1053 BOOL lspci_enabled = False;
91 stargo 648 BOOL g_owncolmap = False;
92 astrand 651 BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */
93 astrand 1199 BOOL g_seamless_rdp = False;
94 stargo 648 uint32 g_embed_wnd;
95 astrand 651 uint32 g_rdp5_performanceflags =
96     RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
97 astrand 977 /* Session Directory redirection */
98     BOOL g_redirect = False;
99     char g_redirect_server[64];
100     char g_redirect_domain[16];
101     char g_redirect_password[64];
102     char g_redirect_username[64];
103     char g_redirect_cookie[128];
104     uint32 g_redirect_flags = 0;
105 matty 10
106 stargo 501 #ifdef WITH_RDPSND
107 matthewc 520 BOOL g_rdpsnd = False;
108 stargo 501 #endif
109    
110 stargo 855 #ifdef HAVE_ICONV
111     char g_codepage[16] = "";
112     #endif
113    
114 n-ki 569 extern RDPDR_DEVICE g_rdpdr_device[];
115     extern uint32 g_num_devices;
116 astrand 651 extern char *g_rdpdr_clientname;
117 n-ki 569
118 astrand 333 #ifdef RDP2VNC
119     extern int rfb_port;
120     extern int defer_time;
121     void
122     rdp2vnc_connect(char *server, uint32 flags, char *domain, char *password,
123     char *shell, char *directory);
124     #endif
125 matty 10 /* Display usage information */
126 matty 25 static void
127     usage(char *program)
128 matty 10 {
129 matthewc 122 fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
130 stargo 828 fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
131 matthewc 122 fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
132    
133 matthewc 222 fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
134 astrand 333 #ifdef RDP2VNC
135     fprintf(stderr, " -V: vnc port\n");
136 forsberg 471 fprintf(stderr, " -Q: defer time (ms)\n");
137 astrand 333 #endif
138 astrand 111 fprintf(stderr, " -u: user name\n");
139     fprintf(stderr, " -d: domain\n");
140     fprintf(stderr, " -s: shell\n");
141     fprintf(stderr, " -c: working directory\n");
142 matthewc 211 fprintf(stderr, " -p: password (- to prompt)\n");
143 astrand 111 fprintf(stderr, " -n: client hostname\n");
144 matthewc 520 fprintf(stderr, " -k: keyboard layout on server (en-us, de, sv, etc.)\n");
145 astrand 111 fprintf(stderr, " -g: desktop geometry (WxH)\n");
146     fprintf(stderr, " -f: full-screen mode\n");
147     fprintf(stderr, " -b: force bitmap updates\n");
148 stargo 855 #ifdef HAVE_ICONV
149     fprintf(stderr, " -L: local codepage\n");
150     #endif
151 astrand 1199 fprintf(stderr, " -A: enable SeamlessRDP mode\n");
152 stargo 609 fprintf(stderr, " -B: use BackingStore of X-server (if available)\n");
153 astrand 111 fprintf(stderr, " -e: disable encryption (French TS)\n");
154 forsberg 471 fprintf(stderr, " -E: disable encryption from client to server\n");
155 astrand 111 fprintf(stderr, " -m: do not send motion events\n");
156 n-ki 279 fprintf(stderr, " -C: use private colour map\n");
157 matthewc 520 fprintf(stderr, " -D: hide window manager decorations\n");
158 astrand 111 fprintf(stderr, " -K: keep window manager key bindings\n");
159 matthewc 520 fprintf(stderr, " -S: caption button size (single application mode)\n");
160 matthewc 223 fprintf(stderr, " -T: window title\n");
161 n-ki 569 fprintf(stderr, " -N: enable numlock syncronization\n");
162 stargo 636 fprintf(stderr, " -X: embed into another window with a given id.\n");
163 matthewc 520 fprintf(stderr, " -a: connection colour depth\n");
164 jsorg71 773 fprintf(stderr, " -z: enable rdp compression\n");
165 jsorg71 725 fprintf(stderr, " -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
166     fprintf(stderr, " -P: use persistent bitmap caching\n");
167 n-ki 569 fprintf(stderr, " -r: enable specified device redirection (this flag can be repeated)\n");
168 astrand 608 fprintf(stderr,
169     " '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
170 n-ki 578 fprintf(stderr, " or COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
171 astrand 608 fprintf(stderr,
172 astrand 747 " '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
173     fprintf(stderr, " or 'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
174 forsberg 646 fprintf(stderr, " '-r clientname=<client name>': Set the client name displayed\n");
175     fprintf(stderr, " for redirected disks\n");
176 astrand 608 fprintf(stderr,
177     " '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
178 n-ki 578 fprintf(stderr, " or LPT1=/dev/lp0,LPT2=/dev/lp1\n");
179 n-ki 569 fprintf(stderr, " '-r printer:mydeskjet': enable printer redirection\n");
180 astrand 608 fprintf(stderr,
181 n-ki 628 " or mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
182 n-ki 630 fprintf(stderr, " '-r sound:[local|off|remote]': enable sound redirection\n");
183 n-ki 628 fprintf(stderr, " remote would leave sound on server\n");
184 ossman_ 1207 fprintf(stderr,
185     " '-r clipboard:[on|off|auto|PRIMARYCLIPBOARD|CLIPBOARD]': enable clip-\n");
186     fprintf(stderr, " board redirection.\n");
187     fprintf(stderr,
188     " 'on|auto|PRIMARYCLIPBOARD' looks at both PRIMARY and\n");
189     fprintf(stderr, " CLIPBOARD when sending data to server.\n");
190     fprintf(stderr, " 'CLIPBOARD' looks at only CLIPBOARD.\n");
191 matthewc 482 fprintf(stderr, " -0: attach to console\n");
192     fprintf(stderr, " -4: use RDP version 4\n");
193     fprintf(stderr, " -5: use RDP version 5 (default)\n");
194 matty 10 }
195    
196 astrand 944 static void
197 astrand 676 print_disconnect_reason(uint16 reason)
198     {
199     char *text;
200    
201     switch (reason)
202     {
203     case exDiscReasonNoInfo:
204     text = "No information available";
205     break;
206    
207     case exDiscReasonAPIInitiatedDisconnect:
208     text = "Server initiated disconnect";
209     break;
210    
211     case exDiscReasonAPIInitiatedLogoff:
212     text = "Server initiated logoff";
213     break;
214    
215     case exDiscReasonServerIdleTimeout:
216     text = "Server idle timeout reached";
217     break;
218    
219     case exDiscReasonServerLogonTimeout:
220     text = "Server logon timeout reached";
221     break;
222    
223     case exDiscReasonReplacedByOtherConnection:
224     text = "The session was replaced";
225     break;
226    
227     case exDiscReasonOutOfMemory:
228     text = "The server is out of memory";
229     break;
230    
231     case exDiscReasonServerDeniedConnection:
232     text = "The server denied the connection";
233     break;
234    
235     case exDiscReasonServerDeniedConnectionFips:
236     text = "The server denied the connection for security reason";
237     break;
238    
239     case exDiscReasonLicenseInternal:
240     text = "Internal licensing error";
241     break;
242    
243     case exDiscReasonLicenseNoLicenseServer:
244     text = "No license server available";
245     break;
246    
247     case exDiscReasonLicenseNoLicense:
248     text = "No valid license available";
249     break;
250    
251     case exDiscReasonLicenseErrClientMsg:
252     text = "Invalid licensing message";
253     break;
254    
255     case exDiscReasonLicenseHwidDoesntMatchLicense:
256     text = "Hardware id doesn't match software license";
257     break;
258    
259     case exDiscReasonLicenseErrClientLicense:
260     text = "Client license error";
261     break;
262    
263     case exDiscReasonLicenseCantFinishProtocol:
264     text = "Network error during licensing protocol";
265     break;
266    
267     case exDiscReasonLicenseClientEndedProtocol:
268     text = "Licensing protocol was not completed";
269     break;
270    
271     case exDiscReasonLicenseErrClientEncryption:
272     text = "Incorrect client license enryption";
273     break;
274    
275     case exDiscReasonLicenseCantUpgradeLicense:
276     text = "Can't upgrade license";
277     break;
278    
279     case exDiscReasonLicenseNoRemoteConnections:
280     text = "The server is not licensed to accept remote connections";
281     break;
282    
283     default:
284     if (reason > 0x1000 && reason < 0x7fff)
285     {
286     text = "Internal protocol error";
287     }
288     else
289     {
290     text = "Unknown reason";
291     }
292     }
293     fprintf(stderr, "disconnect: %s.\n", text);
294     }
295    
296 astrand 977 static void
297     rdesktop_reset_state(void)
298     {
299     rdp_reset_state();
300     }
301    
302 matthewc 211 static BOOL
303     read_password(char *password, int size)
304     {
305     struct termios tios;
306     BOOL ret = False;
307     int istty = 0;
308     char *p;
309    
310     if (tcgetattr(STDIN_FILENO, &tios) == 0)
311     {
312     fprintf(stderr, "Password: ");
313     tios.c_lflag &= ~ECHO;
314     tcsetattr(STDIN_FILENO, TCSANOW, &tios);
315     istty = 1;
316     }
317    
318     if (fgets(password, size, stdin) != NULL)
319     {
320     ret = True;
321    
322     /* strip final newline */
323     p = strchr(password, '\n');
324     if (p != NULL)
325     *p = 0;
326     }
327    
328     if (istty)
329     {
330     tios.c_lflag |= ECHO;
331     tcsetattr(STDIN_FILENO, TCSANOW, &tios);
332     fprintf(stderr, "\n");
333     }
334    
335     return ret;
336     }
337    
338 astrand 444 static void
339     parse_server_and_port(char *server)
340     {
341     char *p;
342     #ifdef IPv6
343     int addr_colons;
344     #endif
345    
346     #ifdef IPv6
347     p = server;
348     addr_colons = 0;
349     while (*p)
350     if (*p++ == ':')
351     addr_colons++;
352     if (addr_colons >= 2)
353     {
354     /* numeric IPv6 style address format - [1:2:3::4]:port */
355     p = strchr(server, ']');
356     if (*server == '[' && p != NULL)
357     {
358     if (*(p + 1) == ':' && *(p + 2) != '\0')
359 jsorg71 710 g_tcp_port_rdp = strtol(p + 2, NULL, 10);
360 astrand 444 /* remove the port number and brackets from the address */
361     *p = '\0';
362     strncpy(server, server + 1, strlen(server));
363     }
364     }
365     else
366     {
367     /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
368     p = strchr(server, ':');
369     if (p != NULL)
370     {
371 jsorg71 710 g_tcp_port_rdp = strtol(p + 1, NULL, 10);
372 astrand 444 *p = 0;
373     }
374     }
375     #else /* no IPv6 support */
376     p = strchr(server, ':');
377     if (p != NULL)
378     {
379 jsorg71 710 g_tcp_port_rdp = strtol(p + 1, NULL, 10);
380 astrand 444 *p = 0;
381     }
382     #endif /* IPv6 */
383    
384     }
385    
386 matty 10 /* Client program */
387 matty 25 int
388     main(int argc, char *argv[])
389 matty 10 {
390 matthewc 222 char server[64];
391 matty 30 char fullhostname[64];
392 matty 21 char domain[16];
393 astrand 479 char password[64];
394 forsberg 1046 char shell[256];
395 astrand 1047 char directory[256];
396 astrand 676 BOOL prompt_password, deactivated;
397 matty 30 struct passwd *pw;
398 astrand 676 uint32 flags, ext_disc_reason = 0;
399 matthewc 222 char *p;
400 matty 10 int c;
401 astrand 973 char *locale = NULL;
402 astrand 289 int username_option = 0;
403 astrand 1199 BOOL geometry_option = False;
404 astrand 977 int run_count = 0; /* Session Directory support */
405     BOOL continue_connect = True; /* Session Directory support */
406 matty 10
407 astrand 973 #ifdef HAVE_LOCALE_H
408 astrand 962 /* Set locale according to environment */
409     locale = setlocale(LC_ALL, "");
410     if (locale)
411     {
412 astrand 974 locale = xstrdup(locale);
413 astrand 962 }
414    
415 astrand 973 #endif
416 matty 21 flags = RDP_LOGON_NORMAL;
417 matthewc 211 prompt_password = False;
418 matty 21 domain[0] = password[0] = shell[0] = directory[0] = 0;
419 stargo 636 g_embed_wnd = 0;
420 matty 21
421 n-ki 569 g_num_devices = 0;
422    
423 astrand 333 #ifdef RDP2VNC
424 forsberg 471 #define VNCOPT "V:Q:"
425 astrand 333 #else
426     #define VNCOPT
427     #endif
428    
429 jsorg71 725 while ((c = getopt(argc, argv,
430 astrand 1199 VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
431 matty 10 {
432     switch (c)
433     {
434 astrand 333 #ifdef RDP2VNC
435     case 'V':
436     rfb_port = strtol(optarg, NULL, 10);
437     if (rfb_port < 100)
438     rfb_port += 5900;
439     break;
440    
441 forsberg 471 case 'Q':
442 astrand 333 defer_time = strtol(optarg, NULL, 10);
443     if (defer_time < 0)
444     defer_time = 0;
445     break;
446     #endif
447    
448 astrand 1199 case 'A':
449     g_seamless_rdp = True;
450     break;
451    
452 matty 10 case 'u':
453 jsorg71 437 STRNCPY(g_username, optarg, sizeof(g_username));
454 astrand 289 username_option = 1;
455 matty 10 break;
456    
457 stargo 855 case 'L':
458     #ifdef HAVE_ICONV
459     STRNCPY(g_codepage, optarg, sizeof(g_codepage));
460     #else
461     error("iconv support not available\n");
462     #endif
463     break;
464    
465 matty 21 case 'd':
466 matty 30 STRNCPY(domain, optarg, sizeof(domain));
467 matty 21 break;
468    
469     case 's':
470 matty 30 STRNCPY(shell, optarg, sizeof(shell));
471 matty 21 break;
472    
473     case 'c':
474 matty 30 STRNCPY(directory, optarg, sizeof(directory));
475 matty 21 break;
476    
477 matty 30 case 'p':
478 matthewc 211 if ((optarg[0] == '-') && (optarg[1] == 0))
479     {
480     prompt_password = True;
481     break;
482     }
483    
484 matty 30 STRNCPY(password, optarg, sizeof(password));
485     flags |= RDP_LOGON_AUTO;
486 matthewc 211
487     /* try to overwrite argument so it won't appear in ps */
488 n-ki 171 p = optarg;
489     while (*p)
490     *(p++) = 'X';
491 matty 30 break;
492    
493 matty 10 case 'n':
494 jsorg71 710 STRNCPY(g_hostname, optarg, sizeof(g_hostname));
495 matty 10 break;
496    
497     case 'k':
498 astrand 975 STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
499 matty 10 break;
500    
501 matty 30 case 'g':
502 astrand 1199 geometry_option = True;
503 astrand 547 g_fullscreen = False;
504 astrand 263 if (!strcmp(optarg, "workarea"))
505     {
506 jsorg71 447 g_width = g_height = 0;
507 astrand 263 break;
508     }
509    
510 jsorg71 447 g_width = strtol(optarg, &p, 10);
511 astrand 500 if (g_width <= 0)
512     {
513     error("invalid geometry\n");
514     return 1;
515     }
516    
517 matty 30 if (*p == 'x')
518 stargo 800 g_height = strtol(p + 1, &p, 10);
519 matty 30
520 astrand 500 if (g_height <= 0)
521 matty 30 {
522     error("invalid geometry\n");
523     return 1;
524     }
525 astrand 500
526     if (*p == '%')
527 stargo 800 {
528 astrand 500 g_width = -g_width;
529 stargo 800 p++;
530     }
531 astrand 500
532 stargo 800 if (*p == '+' || *p == '-')
533 stargo 867 {
534     g_pos |= (*p == '-') ? 2 : 1;
535 stargo 800 g_xpos = strtol(p, &p, 10);
536 astrand 801
537 stargo 867 }
538 stargo 800 if (*p == '+' || *p == '-')
539 stargo 867 {
540     g_pos |= (*p == '-') ? 4 : 1;
541 stargo 800 g_ypos = strtol(p, NULL, 10);
542 stargo 867 }
543 stargo 800
544 matty 10 break;
545    
546 matty 30 case 'f':
547 jsorg71 447 g_fullscreen = True;
548 matty 30 break;
549    
550 matty 10 case 'b':
551 jsorg71 678 g_bitmap_cache = False;
552 matty 10 break;
553    
554 stargo 609 case 'B':
555     g_ownbackstore = False;
556     break;
557    
558 matty 30 case 'e':
559 jsorg71 437 g_encryption = False;
560 matty 10 break;
561 astrand 435 case 'E':
562 forsberg 427 packet_encryption = False;
563     break;
564 matty 30 case 'm':
565 jsorg71 447 g_sendmotion = False;
566 matty 28 break;
567 matty 29
568 n-ki 279 case 'C':
569 jsorg71 450 g_owncolmap = True;
570 n-ki 279 break;
571    
572 matthewc 520 case 'D':
573     g_hide_decorations = True;
574     break;
575    
576 astrand 76 case 'K':
577 jsorg71 450 g_grab_keyboard = False;
578 astrand 76 break;
579    
580 matthewc 520 case 'S':
581     if (!strcmp(optarg, "standard"))
582     {
583     g_win_button_size = 18;
584     break;
585     }
586    
587     g_win_button_size = strtol(optarg, &p, 10);
588    
589     if (*p)
590     {
591     error("invalid button size\n");
592     return 1;
593     }
594    
595     break;
596    
597 matthewc 223 case 'T':
598 jsorg71 450 STRNCPY(g_title, optarg, sizeof(g_title));
599 astrand 107 break;
600    
601 astrand 552 case 'N':
602     g_numlock_sync = True;
603     break;
604    
605 stargo 636 case 'X':
606 stargo 871 g_embed_wnd = strtol(optarg, NULL, 0);
607 stargo 636 break;
608 astrand 651
609 jsorg71 309 case 'a':
610 astrand 1042 g_server_depth = strtol(optarg, NULL, 10);
611     if (g_server_depth != 8 &&
612     g_server_depth != 16 &&
613     g_server_depth != 15 && g_server_depth != 24)
614 jsorg71 309 {
615 astrand 1042 error("Invalid server colour depth.\n");
616 jsorg71 309 return 1;
617     }
618     break;
619    
620 jsorg71 773 case 'z':
621     DEBUG(("rdp compression enabled\n"));
622 jdmeijer 889 flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
623 jsorg71 773 break;
624    
625 stargo 637 case 'x':
626 astrand 1010 if (str_startswith(optarg, "m")) /* modem */
627 stargo 637 {
628 astrand 651 g_rdp5_performanceflags =
629     RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
630     RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
631 stargo 637 }
632 astrand 1010 else if (str_startswith(optarg, "b")) /* broadband */
633 stargo 637 {
634     g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
635     }
636 astrand 1010 else if (str_startswith(optarg, "l")) /* lan */
637 stargo 637 {
638     g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
639     }
640     else
641     {
642     g_rdp5_performanceflags = strtol(optarg, NULL, 16);
643     }
644     break;
645 astrand 651
646 jsorg71 725 case 'P':
647     g_bitmap_cache_persist_enable = True;
648     break;
649    
650 matthewc 520 case 'r':
651 n-ki 569
652 astrand 1010 if (str_startswith(optarg, "sound"))
653 n-ki 569 {
654 n-ki 629 optarg += 5;
655    
656     if (*optarg == ':')
657 n-ki 628 {
658 n-ki 629 *optarg++;
659     while ((p = next_arg(optarg, ',')))
660     {
661 astrand 1010 if (str_startswith(optarg, "remote"))
662 n-ki 629 flags |= RDP_LOGON_LEAVE_AUDIO;
663 n-ki 628
664 astrand 1010 if (str_startswith(optarg, "local"))
665 stargo 501 #ifdef WITH_RDPSND
666 n-ki 629 g_rdpsnd = True;
667 matthewc 520 #else
668 stargo 739 warning("Not compiled with sound support\n");
669 matthewc 520 #endif
670 n-ki 629
671 astrand 1010 if (str_startswith(optarg, "off"))
672 stargo 685 #ifdef WITH_RDPSND
673 n-ki 629 g_rdpsnd = False;
674 stargo 685 #else
675 stargo 739 warning("Not compiled with sound support\n");
676 stargo 685 #endif
677 n-ki 629
678     optarg = p;
679 n-ki 628 }
680     }
681     else
682     {
683     #ifdef WITH_RDPSND
684     g_rdpsnd = True;
685     #else
686 stargo 739 warning("Not compiled with sound support\n");
687 n-ki 628 #endif
688     }
689 n-ki 569 }
690 astrand 1010 else if (str_startswith(optarg, "disk"))
691 n-ki 569 {
692     /* -r disk:h:=/mnt/floppy */
693     disk_enum_devices(&g_num_devices, optarg + 4);
694     }
695 astrand 1010 else if (str_startswith(optarg, "comport"))
696 n-ki 569 {
697     serial_enum_devices(&g_num_devices, optarg + 7);
698     }
699 astrand 1053 else if (str_startswith(optarg, "lspci"))
700     {
701     lspci_enabled = True;
702     }
703 astrand 1010 else if (str_startswith(optarg, "lptport"))
704 n-ki 569 {
705     parallel_enum_devices(&g_num_devices, optarg + 7);
706     }
707 astrand 1010 else if (str_startswith(optarg, "printer"))
708 n-ki 569 {
709     printer_enum_devices(&g_num_devices, optarg + 7);
710     }
711 astrand 1010 else if (str_startswith(optarg, "clientname"))
712 forsberg 646 {
713 astrand 651 g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
714 forsberg 646 strcpy(g_rdpdr_clientname, optarg + 11);
715     }
716 ossman_ 1207 else if (str_startswith(optarg, "clipboard"))
717     {
718     optarg += 9;
719    
720     if (*optarg == ':')
721     {
722     optarg++;
723    
724     if (str_startswith(optarg, "off"))
725     g_rdpclip = False;
726     else
727     cliprdr_set_mode(optarg);
728     }
729     else
730     g_rdpclip = True;
731     }
732 n-ki 569 else
733     {
734 ossman_ 1207 warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard\n");
735 n-ki 569 }
736 stargo 501 break;
737 matthewc 520
738 matthewc 482 case '0':
739     g_console_session = True;
740     break;
741    
742 astrand 458 case '4':
743     g_use_rdp5 = False;
744     break;
745    
746 forsberg 350 case '5':
747 jsorg71 438 g_use_rdp5 = True;
748 forsberg 350 break;
749 astrand 458
750 matty 28 case 'h':
751 matty 10 case '?':
752     default:
753     usage(argv[0]);
754     return 1;
755     }
756     }
757    
758 stargo 610 if (argc - optind != 1)
759 matty 10 {
760     usage(argv[0]);
761     return 1;
762     }
763    
764 matthewc 222 STRNCPY(server, argv[optind], sizeof(server));
765 astrand 444 parse_server_and_port(server);
766 matty 10
767 astrand 1199 if (g_seamless_rdp)
768     {
769     if (g_win_button_size)
770     {
771     error("You cannot use -S and -A at the same time\n");
772     return 1;
773     }
774     g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
775     if (geometry_option)
776     {
777     error("You cannot use -g and -A at the same time\n");
778     return 1;
779     }
780     if (g_fullscreen)
781     {
782     error("You cannot use -f and -A at the same time\n");
783     return 1;
784     }
785     if (g_hide_decorations)
786     {
787     error("You cannot use -D and -A at the same time\n");
788     return 1;
789     }
790     if (g_embed_wnd)
791     {
792     error("You cannot use -X and -A at the same time\n");
793     return 1;
794     }
795     if (!g_use_rdp5)
796     {
797     error("You cannot use -4 and -A at the same time\n");
798     return 1;
799     }
800     g_width = -100;
801     g_grab_keyboard = False;
802     }
803    
804 astrand 289 if (!username_option)
805 matty 10 {
806     pw = getpwuid(getuid());
807     if ((pw == NULL) || (pw->pw_name == NULL))
808     {
809 matty 30 error("could not determine username, use -u\n");
810 matty 10 return 1;
811     }
812    
813 jsorg71 437 STRNCPY(g_username, pw->pw_name, sizeof(g_username));
814 matty 10 }
815    
816 stargo 855 #ifdef HAVE_ICONV
817     if (g_codepage[0] == 0)
818     {
819     if (setlocale(LC_CTYPE, ""))
820     {
821     STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
822     }
823     else
824     {
825     STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
826     }
827     }
828     #endif
829 stargo 861
830 jsorg71 710 if (g_hostname[0] == 0)
831 matty 10 {
832 matty 30 if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
833 matty 10 {
834 matty 30 error("could not determine local hostname, use -n\n");
835 matty 10 return 1;
836     }
837 matty 30
838     p = strchr(fullhostname, '.');
839     if (p != NULL)
840     *p = 0;
841    
842 jsorg71 710 STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
843 matty 10 }
844    
845 astrand 975 if (g_keymapname[0] == 0)
846 astrand 973 {
847     if (locale && xkeymap_from_locale(locale))
848     {
849 astrand 975 fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
850 astrand 973 }
851     else
852     {
853 astrand 975 STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
854 astrand 973 }
855     }
856     if (locale)
857     xfree(locale);
858    
859    
860 matthewc 211 if (prompt_password && read_password(password, sizeof(password)))
861     flags |= RDP_LOGON_AUTO;
862 matty 30
863 jsorg71 450 if (g_title[0] == 0)
864 astrand 107 {
865 jsorg71 450 strcpy(g_title, "rdesktop - ");
866     strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
867 astrand 107 }
868 matty 12
869 astrand 333 #ifdef RDP2VNC
870     rdp2vnc_connect(server, flags, domain, password, shell, directory);
871 forsberg 424 return 0;
872 astrand 333 #else
873    
874 astrand 82 if (!ui_init())
875     return 1;
876 astrand 66
877 matthewc 474 #ifdef WITH_RDPSND
878 stargo 501 if (g_rdpsnd)
879     rdpsnd_init();
880 matthewc 474 #endif
881 astrand 1053
882     if (lspci_enabled)
883     lspci_init();
884    
885 n-ki 569 rdpdr_init();
886 forsberg 416
887 astrand 977 while (run_count < 2 && continue_connect) /* add support for Session Directory; only reconnect once */
888     {
889     if (run_count == 0)
890     {
891     if (!rdp_connect(server, flags, domain, password, shell, directory))
892     return 1;
893     }
894     else if (!rdp_reconnect
895     (server, flags, domain, password, shell, directory, g_redirect_cookie))
896     return 1;
897 matthewc 53
898 astrand 977 /* By setting encryption to False here, we have an encrypted login
899     packet but unencrypted transfer of other packets */
900     if (!packet_encryption)
901     g_encryption = False;
902 forsberg 427
903    
904 astrand 977 DEBUG(("Connection successful.\n"));
905     memset(password, 0, sizeof(password));
906 matthewc 53
907 astrand 977 if (run_count == 0)
908     if (!ui_create_window())
909     continue_connect = False;
910    
911     if (continue_connect)
912     rdp_main_loop(&deactivated, &ext_disc_reason);
913    
914     DEBUG(("Disconnecting...\n"));
915     rdp_disconnect();
916    
917     if ((g_redirect == True) && (run_count == 0)) /* Support for Session Directory */
918     {
919     /* reset state of major globals */
920     rdesktop_reset_state();
921    
922     STRNCPY(domain, g_redirect_domain, sizeof(domain));
923     STRNCPY(g_username, g_redirect_username, sizeof(g_username));
924     STRNCPY(password, g_redirect_password, sizeof(password));
925     STRNCPY(server, g_redirect_server, sizeof(server));
926     flags |= RDP_LOGON_AUTO;
927    
928     g_redirect = False;
929     }
930     else
931     {
932     continue_connect = False;
933     ui_destroy_window();
934     break;
935     }
936    
937     run_count++;
938 matty 10 }
939    
940 jsorg71 725 cache_save_state();
941 matthewc 188 ui_deinit();
942 astrand 333
943 astrand 676 if (ext_disc_reason >= 2)
944     print_disconnect_reason(ext_disc_reason);
945    
946     if (deactivated)
947     {
948     /* clean disconnect */
949 forsberg 424 return 0;
950 astrand 676 }
951 forsberg 424 else
952 astrand 676 {
953     if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
954     || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
955     {
956     /* not so clean disconnect, but nothing to worry about */
957     return 0;
958     }
959     else
960     {
961     /* return error */
962     return 2;
963     }
964     }
965 forsberg 424
966 astrand 333 #endif
967    
968 matty 10 }
969    
970 matthewc 220 #ifdef EGD_SOCKET
971     /* Read 32 random bytes from PRNGD or EGD socket (based on OpenSSL RAND_egd) */
972     static BOOL
973     generate_random_egd(uint8 * buf)
974     {
975     struct sockaddr_un addr;
976     BOOL ret = False;
977     int fd;
978    
979     fd = socket(AF_UNIX, SOCK_STREAM, 0);
980     if (fd == -1)
981     return False;
982    
983     addr.sun_family = AF_UNIX;
984     memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
985 astrand 259 if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
986 matthewc 220 goto err;
987    
988     /* PRNGD and EGD use a simple communications protocol */
989 astrand 259 buf[0] = 1; /* Non-blocking (similar to /dev/urandom) */
990     buf[1] = 32; /* Number of requested random bytes */
991 matthewc 220 if (write(fd, buf, 2) != 2)
992     goto err;
993    
994 astrand 259 if ((read(fd, buf, 1) != 1) || (buf[0] == 0)) /* Available? */
995 matthewc 220 goto err;
996    
997     if (read(fd, buf, 32) != 32)
998     goto err;
999    
1000     ret = True;
1001    
1002 astrand 259 err:
1003 matthewc 220 close(fd);
1004     return ret;
1005     }
1006     #endif
1007    
1008 matty 10 /* Generate a 32-byte random for the secure transport code. */
1009 matty 25 void
1010 astrand 64 generate_random(uint8 * random)
1011 matty 10 {
1012     struct stat st;
1013 matty 22 struct tms tmsbuf;
1014 matthewc 220 MD5_CTX md5;
1015     uint32 *r;
1016     int fd, n;
1017 matty 10
1018 matthewc 220 /* If we have a kernel random device, try that first */
1019 matty 30 if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
1020     || ((fd = open("/dev/random", O_RDONLY)) != -1))
1021 matty 10 {
1022 matthewc 220 n = read(fd, random, 32);
1023 matty 10 close(fd);
1024 matthewc 220 if (n == 32)
1025     return;
1026 matty 10 }
1027    
1028 matthewc 220 #ifdef EGD_SOCKET
1029     /* As a second preference use an EGD */
1030     if (generate_random_egd(random))
1031     return;
1032     #endif
1033    
1034 matty 10 /* Otherwise use whatever entropy we can gather - ideas welcome. */
1035 astrand 259 r = (uint32 *) random;
1036 matty 10 r[0] = (getpid()) | (getppid() << 16);
1037     r[1] = (getuid()) | (getgid() << 16);
1038 matty 24 r[2] = times(&tmsbuf); /* system uptime (clocks) */
1039     gettimeofday((struct timeval *) &r[3], NULL); /* sec and usec */
1040 matty 10 stat("/tmp", &st);
1041     r[5] = st.st_atime;
1042     r[6] = st.st_mtime;
1043     r[7] = st.st_ctime;
1044 matthewc 220
1045     /* Hash both halves with MD5 to obscure possible patterns */
1046     MD5_Init(&md5);
1047 astrand 259 MD5_Update(&md5, random, 16);
1048 matthewc 220 MD5_Final(random, &md5);
1049 astrand 259 MD5_Update(&md5, random + 16, 16);
1050     MD5_Final(random + 16, &md5);
1051 matty 10 }
1052    
1053     /* malloc; exit if out of memory */
1054 matty 25 void *
1055     xmalloc(int size)
1056 matty 10 {
1057     void *mem = malloc(size);
1058     if (mem == NULL)
1059     {
1060 matty 30 error("xmalloc %d\n", size);
1061 matty 10 exit(1);
1062     }
1063     return mem;
1064     }
1065    
1066 astrand 974 /* strdup */
1067     char *
1068     xstrdup(const char *s)
1069     {
1070     char *mem = strdup(s);
1071     if (mem == NULL)
1072     {
1073     perror("strdup");
1074     exit(1);
1075     }
1076     return mem;
1077     }
1078    
1079 matty 10 /* realloc; exit if out of memory */
1080 matty 25 void *
1081     xrealloc(void *oldmem, int size)
1082 matty 10 {
1083 astrand 782 void *mem;
1084 jsorg71 773
1085     if (size < 1)
1086     size = 1;
1087     mem = realloc(oldmem, size);
1088 matty 10 if (mem == NULL)
1089     {
1090 matty 30 error("xrealloc %d\n", size);
1091 matty 10 exit(1);
1092     }
1093     return mem;
1094     }
1095    
1096     /* free */
1097 matty 25 void
1098     xfree(void *mem)
1099 matty 10 {
1100     free(mem);
1101     }
1102    
1103 matty 30 /* report an error */
1104 matty 25 void
1105 matty 30 error(char *format, ...)
1106     {
1107     va_list ap;
1108    
1109     fprintf(stderr, "ERROR: ");
1110    
1111     va_start(ap, format);
1112     vfprintf(stderr, format, ap);
1113     va_end(ap);
1114     }
1115    
1116 matthewc 297 /* report a warning */
1117     void
1118     warning(char *format, ...)
1119     {
1120     va_list ap;
1121    
1122     fprintf(stderr, "WARNING: ");
1123    
1124     va_start(ap, format);
1125     vfprintf(stderr, format, ap);
1126     va_end(ap);
1127     }
1128    
1129 matty 30 /* report an unimplemented protocol feature */
1130     void
1131     unimpl(char *format, ...)
1132     {
1133     va_list ap;
1134    
1135     fprintf(stderr, "NOT IMPLEMENTED: ");
1136    
1137     va_start(ap, format);
1138     vfprintf(stderr, format, ap);
1139     va_end(ap);
1140     }
1141    
1142     /* produce a hex dump */
1143     void
1144 n-ki 569 hexdump(unsigned char *p, unsigned int len)
1145 matty 10 {
1146     unsigned char *line = p;
1147 jsorg71 376 int i, thisline, offset = 0;
1148 matty 10
1149     while (offset < len)
1150     {
1151 matthewc 169 printf("%04x ", offset);
1152 matty 10 thisline = len - offset;
1153     if (thisline > 16)
1154     thisline = 16;
1155    
1156     for (i = 0; i < thisline; i++)
1157 matthewc 169 printf("%02x ", line[i]);
1158 matty 10
1159 matty 30 for (; i < 16; i++)
1160 matthewc 169 printf(" ");
1161 matty 30
1162 matty 10 for (i = 0; i < thisline; i++)
1163 matthewc 169 printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1164 matty 10
1165 matthewc 169 printf("\n");
1166 matty 10 offset += thisline;
1167     line += thisline;
1168     }
1169     }
1170 astrand 325
1171 n-ki 569 /*
1172 n-ki 583 input: src is the string we look in for needle.
1173     Needle may be escaped by a backslash, in
1174     that case we ignore that particular needle.
1175 n-ki 569 return value: returns next src pointer, for
1176     succesive executions, like in a while loop
1177     if retval is 0, then there are no more args.
1178     pitfalls:
1179     src is modified. 0x00 chars are inserted to
1180     terminate strings.
1181     return val, points on the next val chr after ins
1182     0x00
1183 astrand 325
1184 n-ki 569 example usage:
1185     while( (pos = next_arg( optarg, ',')) ){
1186     printf("%s\n",optarg);
1187     optarg=pos;
1188     }
1189    
1190     */
1191     char *
1192     next_arg(char *src, char needle)
1193     {
1194     char *nextval;
1195 n-ki 571 char *p;
1196 n-ki 575 char *mvp = 0;
1197 n-ki 569
1198 n-ki 575 /* EOS */
1199 n-ki 569 if (*src == (char) 0x00)
1200     return 0;
1201    
1202 n-ki 571 p = src;
1203 n-ki 575 /* skip escaped needles */
1204 astrand 580 while ((nextval = strchr(p, needle)))
1205 n-ki 571 {
1206 n-ki 575 mvp = nextval - 1;
1207     /* found backslashed needle */
1208 astrand 580 if (*mvp == '\\' && (mvp > src))
1209 n-ki 575 {
1210     /* move string one to the left */
1211 astrand 580 while (*(mvp + 1) != (char) 0x00)
1212 n-ki 575 {
1213 astrand 580 *mvp = *(mvp + 1);
1214 n-ki 575 *mvp++;
1215     }
1216 astrand 580 *mvp = (char) 0x00;
1217 n-ki 575 p = nextval;
1218     }
1219     else
1220     {
1221 astrand 580 p = nextval + 1;
1222 n-ki 571 break;
1223 n-ki 575 }
1224    
1225 n-ki 571 }
1226    
1227 n-ki 575 /* more args available */
1228 n-ki 569 if (nextval)
1229     {
1230     *nextval = (char) 0x00;
1231     return ++nextval;
1232     }
1233    
1234 n-ki 575 /* no more args after this, jump to EOS */
1235 n-ki 569 nextval = src + strlen(src);
1236     return nextval;
1237     }
1238    
1239    
1240 stargo 570 void
1241 astrand 580 toupper_str(char *p)
1242 n-ki 569 {
1243 astrand 580 while (*p)
1244     {
1245     if ((*p >= 'a') && (*p <= 'z'))
1246 stargo 570 *p = toupper((int) *p);
1247 n-ki 569 p++;
1248     }
1249     }
1250    
1251    
1252 astrand 1010 BOOL
1253     str_startswith(const char *s, const char *prefix)
1254     {
1255     return (strncmp(s, prefix, strlen(prefix)) == 0);
1256     }
1257    
1258    
1259 astrand 1053 /* Split input into lines, and call linehandler for each
1260     line. Incomplete lines are saved in the rest variable, which should
1261     initially point to NULL. When linehandler returns False, stop and
1262     return False. Otherwise, return True. */
1263     BOOL
1264     str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1265     {
1266     char *buf, *p;
1267     char *oldrest;
1268     size_t inputlen;
1269     size_t buflen;
1270     size_t restlen = 0;
1271     BOOL ret = True;
1272    
1273     /* Copy data to buffer */
1274     inputlen = strlen(input);
1275     if (*rest)
1276     restlen = strlen(*rest);
1277     buflen = restlen + inputlen + 1;
1278     buf = (char *) xmalloc(buflen);
1279     buf[0] = '\0';
1280     if (*rest)
1281     STRNCPY(buf, *rest, buflen);
1282     strncat(buf, input, inputlen);
1283     p = buf;
1284    
1285     while (1)
1286     {
1287     char *newline = strchr(p, '\n');
1288     if (newline)
1289     {
1290     *newline = '\0';
1291     if (!linehandler(p, data))
1292     {
1293     p = newline + 1;
1294     ret = False;
1295     break;
1296     }
1297     p = newline + 1;
1298     }
1299     else
1300     {
1301     break;
1302    
1303     }
1304     }
1305    
1306     /* Save in rest */
1307     oldrest = *rest;
1308     restlen = buf + buflen - p;
1309     *rest = (char *) xmalloc(restlen);
1310     STRNCPY((*rest), p, restlen);
1311     xfree(oldrest);
1312    
1313     xfree(buf);
1314     return ret;
1315     }
1316    
1317     /* Execute the program specified by argv. For each line in
1318     stdout/stderr output, call linehandler. Returns false on failure. */
1319     BOOL
1320     subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1321     {
1322     pid_t child;
1323     int fd[2];
1324     int n = 1;
1325     char output[256];
1326     char *rest = NULL;
1327    
1328     if (pipe(fd) < 0)
1329     {
1330     perror("pipe");
1331     return False;
1332     }
1333    
1334     if ((child = fork()) < 0)
1335     {
1336     perror("fork");
1337     return False;
1338     }
1339    
1340     /* Child */
1341     if (child == 0)
1342     {
1343     /* Close read end */
1344     close(fd[0]);
1345    
1346     /* Redirect stdout and stderr to pipe */
1347     dup2(fd[1], 1);
1348     dup2(fd[1], 2);
1349    
1350     /* Execute */
1351     execvp(argv[0], argv);
1352     perror("Error executing child");
1353     _exit(128);
1354     }
1355    
1356     /* Parent. Close write end. */
1357     close(fd[1]);
1358     while (n > 0)
1359     {
1360     n = read(fd[0], output, 255);
1361     output[n] = '\0';
1362     str_handle_lines(output, &rest, linehandler, data);
1363     }
1364     xfree(rest);
1365    
1366     return True;
1367     }
1368    
1369    
1370 n-ki 569 /* not all clibs got ltoa */
1371     #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1372    
1373     char *
1374 stargo 603 l_to_a(long N, int base)
1375 n-ki 569 {
1376     static char ret[LTOA_BUFSIZE];
1377    
1378 n-ki 583 char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1379 n-ki 569
1380 n-ki 583 register int divrem;
1381    
1382     if (base < 36 || 2 > base)
1383 n-ki 569 base = 10;
1384    
1385 n-ki 583 if (N < 0)
1386 n-ki 569 {
1387     *head++ = '-';
1388 n-ki 583 N = -N;
1389 n-ki 569 }
1390    
1391 n-ki 583 tail = buf + sizeof(buf);
1392     *--tail = 0;
1393    
1394     do
1395 n-ki 569 {
1396 n-ki 583 divrem = N % base;
1397     *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1398     N /= base;
1399 n-ki 569 }
1400 n-ki 583 while (N);
1401 n-ki 569
1402 n-ki 583 strcpy(head, tail);
1403 n-ki 569 return ret;
1404     }
1405    
1406    
1407 astrand 325 int
1408     load_licence(unsigned char **data)
1409     {
1410 matthewc 367 char *home, *path;
1411 astrand 325 struct stat st;
1412 matthewc 367 int fd, length;
1413 astrand 325
1414     home = getenv("HOME");
1415     if (home == NULL)
1416     return -1;
1417    
1418 jsorg71 710 path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1419     sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1420 astrand 325
1421     fd = open(path, O_RDONLY);
1422     if (fd == -1)
1423     return -1;
1424    
1425     if (fstat(fd, &st))
1426     return -1;
1427    
1428 forsberg 416 *data = (uint8 *) xmalloc(st.st_size);
1429 matthewc 367 length = read(fd, *data, st.st_size);
1430     close(fd);
1431     xfree(path);
1432     return length;
1433 astrand 325 }
1434    
1435     void
1436     save_licence(unsigned char *data, int length)
1437     {
1438 matthewc 367 char *home, *path, *tmppath;
1439     int fd;
1440 astrand 325
1441     home = getenv("HOME");
1442     if (home == NULL)
1443     return;
1444    
1445 jsorg71 710 path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1446 astrand 325
1447 matthewc 367 sprintf(path, "%s/.rdesktop", home);
1448     if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1449 astrand 325 {
1450 matthewc 367 perror(path);
1451     return;
1452 astrand 325 }
1453    
1454 matthewc 367 /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1455 astrand 325
1456 jsorg71 710 sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1457 forsberg 416 tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1458 matthewc 367 strcpy(tmppath, path);
1459     strcat(tmppath, ".new");
1460    
1461 forsberg 416 fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1462 matthewc 367 if (fd == -1)
1463 astrand 325 {
1464 matthewc 367 perror(tmppath);
1465     return;
1466 astrand 325 }
1467    
1468 matthewc 367 if (write(fd, data, length) != length)
1469 astrand 325 {
1470 matthewc 367 perror(tmppath);
1471     unlink(tmppath);
1472 astrand 325 }
1473 matthewc 367 else if (rename(tmppath, path) == -1)
1474 astrand 325 {
1475 matthewc 367 perror(path);
1476     unlink(tmppath);
1477 astrand 325 }
1478    
1479 matthewc 367 close(fd);
1480     xfree(tmppath);
1481     xfree(path);
1482 astrand 325 }
1483 jsorg71 725
1484     /* Create the bitmap cache directory */
1485     BOOL
1486     rd_pstcache_mkdir(void)
1487     {
1488     char *home;
1489     char bmpcache_dir[256];
1490    
1491     home = getenv("HOME");
1492    
1493     if (home == NULL)
1494     return False;
1495    
1496     sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1497    
1498     if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1499     {
1500     perror(bmpcache_dir);
1501     return False;
1502     }
1503    
1504     sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1505    
1506     if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1507     {
1508     perror(bmpcache_dir);
1509     return False;
1510     }
1511    
1512     return True;
1513     }
1514    
1515     /* open a file in the .rdesktop directory */
1516     int
1517     rd_open_file(char *filename)
1518     {
1519     char *home;
1520     char fn[256];
1521 astrand 738 int fd;
1522 jsorg71 725
1523     home = getenv("HOME");
1524     if (home == NULL)
1525     return -1;
1526     sprintf(fn, "%s/.rdesktop/%s", home, filename);
1527     fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1528     if (fd == -1)
1529     perror(fn);
1530     return fd;
1531     }
1532    
1533     /* close file */
1534     void
1535     rd_close_file(int fd)
1536     {
1537 astrand 738 close(fd);
1538 jsorg71 725 }
1539    
1540     /* read from file*/
1541     int
1542     rd_read_file(int fd, void *ptr, int len)
1543     {
1544 astrand 738 return read(fd, ptr, len);
1545 jsorg71 725 }
1546    
1547     /* write to file */
1548     int
1549 astrand 738 rd_write_file(int fd, void *ptr, int len)
1550 jsorg71 725 {
1551 astrand 738 return write(fd, ptr, len);
1552 jsorg71 725 }
1553    
1554     /* move file pointer */
1555     int
1556     rd_lseek_file(int fd, int offset)
1557     {
1558 astrand 738 return lseek(fd, offset, SEEK_SET);
1559 jsorg71 725 }
1560    
1561     /* do a write lock on a file */
1562     BOOL
1563     rd_lock_file(int fd, int start, int len)
1564     {
1565     struct flock lock;
1566    
1567     lock.l_type = F_WRLCK;
1568     lock.l_whence = SEEK_SET;
1569     lock.l_start = start;
1570     lock.l_len = len;
1571     if (fcntl(fd, F_SETLK, &lock) == -1)
1572     return False;
1573     return True;
1574     }

  ViewVC Help
Powered by ViewVC 1.1.26