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

Diff of /jpeg/rdesktop/trunk/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 1207 by ossman_, Mon Mar 27 09:20:24 2006 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-2005
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 HAVE_LOCALE_H
34  char hostname[16];  #include <locale.h>
35  int width = 800;  #endif
36  int height = 600;  #ifdef HAVE_ICONV
37  int keylayout = 0x409;  #ifdef HAVE_LANGINFO_H
38  BOOL motion = False;  #include <langinfo.h>
39  BOOL orders = True;  #endif
40  BOOL licence = True;  #endif
41    
42    #ifdef EGD_SOCKET
43    #include <sys/types.h>
44    #include <sys/socket.h>         /* socket connect */
45    #include <sys/un.h>             /* sockaddr_un */
46    #endif
47    
48    #include <openssl/md5.h>
49    
50    char g_title[64] = "";
51    char g_username[64];
52    char g_hostname[16];
53    char g_keymapname[PATH_MAX] = "";
54    unsigned int g_keylayout = 0x409;       /* Defaults to US keyboard layout */
55    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    
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    int g_height = 600;
65    int g_xpos = 0;
66    int g_ypos = 0;
67    int g_pos = 0;                  /* 0 position unspecified,
68                                       1 specified,
69                                       2 xpos neg,
70                                       4 ypos neg  */
71    extern int g_tcp_port_rdp;
72    int g_server_depth = 8;
73    int g_win_button_size = 0;      /* If zero, disable single app mode */
74    BOOL g_bitmap_compression = True;
75    BOOL g_sendmotion = True;
76    BOOL g_bitmap_cache = True;
77    BOOL g_bitmap_cache_persist_enable = False;
78    BOOL g_bitmap_cache_precache = True;
79    BOOL g_encryption = True;
80    BOOL packet_encryption = True;
81    BOOL g_desktop_save = True;     /* desktop save order */
82    BOOL g_polygon_ellipse_orders = True;   /* polygon / ellipse orders */
83    BOOL g_fullscreen = False;
84    BOOL g_grab_keyboard = True;
85    BOOL g_hide_decorations = False;
86    BOOL g_use_rdp5 = True;
87    BOOL g_rdpclip = True;
88    BOOL g_console_session = False;
89    BOOL g_numlock_sync = False;
90    BOOL lspci_enabled = False;
91    BOOL g_owncolmap = False;
92    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
93    BOOL g_seamless_rdp = False;
94    uint32 g_embed_wnd;
95    uint32 g_rdp5_performanceflags =
96            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
97    /* 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    
106    #ifdef WITH_RDPSND
107    BOOL g_rdpsnd = False;
108    #endif
109    
110    #ifdef HAVE_ICONV
111    char g_codepage[16] = "";
112    #endif
113    
114    extern RDPDR_DEVICE g_rdpdr_device[];
115    extern uint32 g_num_devices;
116    extern char *g_rdpdr_clientname;
117    
118    #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  /* Display usage information */  /* Display usage information */
126  static void usage(char *program)  static void
127    usage(char *program)
128    {
129            fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
130            fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
131            fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
132    
133            fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
134    #ifdef RDP2VNC
135            fprintf(stderr, "   -V: vnc port\n");
136            fprintf(stderr, "   -Q: defer time (ms)\n");
137    #endif
138            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            fprintf(stderr, "   -p: password (- to prompt)\n");
143            fprintf(stderr, "   -n: client hostname\n");
144            fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
145            fprintf(stderr, "   -g: desktop geometry (WxH)\n");
146            fprintf(stderr, "   -f: full-screen mode\n");
147            fprintf(stderr, "   -b: force bitmap updates\n");
148    #ifdef HAVE_ICONV
149            fprintf(stderr, "   -L: local codepage\n");
150    #endif
151            fprintf(stderr, "   -A: enable SeamlessRDP mode\n");
152            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
153            fprintf(stderr, "   -e: disable encryption (French TS)\n");
154            fprintf(stderr, "   -E: disable encryption from client to server\n");
155            fprintf(stderr, "   -m: do not send motion events\n");
156            fprintf(stderr, "   -C: use private colour map\n");
157            fprintf(stderr, "   -D: hide window manager decorations\n");
158            fprintf(stderr, "   -K: keep window manager key bindings\n");
159            fprintf(stderr, "   -S: caption button size (single application mode)\n");
160            fprintf(stderr, "   -T: window title\n");
161            fprintf(stderr, "   -N: enable numlock syncronization\n");
162            fprintf(stderr, "   -X: embed into another window with a given id.\n");
163            fprintf(stderr, "   -a: connection colour depth\n");
164            fprintf(stderr, "   -z: enable rdp compression\n");
165            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            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
168            fprintf(stderr,
169                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
170            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
171            fprintf(stderr,
172                    "         '-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            fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
175            fprintf(stderr, "             for redirected disks\n");
176            fprintf(stderr,
177                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
178            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
179            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
180            fprintf(stderr,
181                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
182            fprintf(stderr, "         '-r sound:[local|off|remote]': enable sound redirection\n");
183            fprintf(stderr, "                     remote would leave sound on server\n");
184            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            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    }
195    
196    static void
197    print_disconnect_reason(uint16 reason)
198  {  {
199          STATUS("Usage: %s [options] server\n", program);          char *text;
200          STATUS("   -u: user name\n");  
201          STATUS("   -n: client hostname\n");          switch (reason)
202          STATUS("   -w: desktop width\n");          {
203          STATUS("   -h: desktop height\n");                  case exDiscReasonNoInfo:
204          STATUS("   -k: keyboard layout (hex)\n");                          text = "No information available";
205          STATUS("   -m: send motion events\n");                          break;
206          STATUS("   -b: force bitmap updates\n");  
207          STATUS("   -l: do not request licence\n\n");                  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    static void
297    rdesktop_reset_state(void)
298    {
299            rdp_reset_state();
300    }
301    
302    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    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                                    g_tcp_port_rdp = strtol(p + 2, NULL, 10);
360                            /* 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                            g_tcp_port_rdp = strtol(p + 1, NULL, 10);
372                            *p = 0;
373                    }
374            }
375    #else /* no IPv6 support */
376            p = strchr(server, ':');
377            if (p != NULL)
378            {
379                    g_tcp_port_rdp = strtol(p + 1, NULL, 10);
380                    *p = 0;
381            }
382    #endif /* IPv6 */
383    
384  }  }
385    
386  /* Client program */  /* Client program */
387  int main(int argc, char *argv[])  int
388    main(int argc, char *argv[])
389  {  {
390            char server[64];
391            char fullhostname[64];
392            char domain[16];
393            char password[64];
394            char shell[256];
395            char directory[256];
396            BOOL prompt_password, deactivated;
397          struct passwd *pw;          struct passwd *pw;
398          char *server;          uint32 flags, ext_disc_reason = 0;
399          char title[32];          char *p;
400          int c;          int c;
401            char *locale = NULL;
402            int username_option = 0;
403            BOOL geometry_option = False;
404            int run_count = 0;      /* Session Directory support */
405            BOOL continue_connect = True;   /* Session Directory support */
406    
407    #ifdef HAVE_LOCALE_H
408            /* Set locale according to environment */
409            locale = setlocale(LC_ALL, "");
410            if (locale)
411            {
412                    locale = xstrdup(locale);
413            }
414    
415          STATUS("rdesktop: A Remote Desktop Protocol client.\n");  #endif
416          STATUS("Version "VERSION". Copyright (C) 1999-2000 Matt Chapman.\n\n");          flags = RDP_LOGON_NORMAL;
417            prompt_password = False;
418            domain[0] = password[0] = shell[0] = directory[0] = 0;
419            g_embed_wnd = 0;
420    
421            g_num_devices = 0;
422    
423    #ifdef RDP2VNC
424    #define VNCOPT "V:Q:"
425    #else
426    #define VNCOPT
427    #endif
428    
429          while ((c = getopt(argc, argv, "u:n:w:h:k:mbl?")) != -1)          while ((c = getopt(argc, argv,
430                               VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
431          {          {
432                  switch (c)                  switch (c)
433                  {                  {
434    #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                            case 'Q':
442                                    defer_time = strtol(optarg, NULL, 10);
443                                    if (defer_time < 0)
444                                            defer_time = 0;
445                                    break;
446    #endif
447    
448                            case 'A':
449                                    g_seamless_rdp = True;
450                                    break;
451    
452                          case 'u':                          case 'u':
453                                  strncpy(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
454                                    username_option = 1;
455                                  break;                                  break;
456    
457                          case 'n':                          case 'L':
458                                  strncpy(hostname, optarg, sizeof(hostname));  #ifdef HAVE_ICONV
459                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
460    #else
461                                    error("iconv support not available\n");
462    #endif
463                                  break;                                  break;
464    
465                          case 'w':                          case 'd':
466                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(domain, optarg, sizeof(domain));
467                                  break;                                  break;
468    
469                          case 'h':                          case 's':
470                                  height = strtol(optarg, NULL, 10);                                  STRNCPY(shell, optarg, sizeof(shell));
471                                    break;
472    
473                            case 'c':
474                                    STRNCPY(directory, optarg, sizeof(directory));
475                                    break;
476    
477                            case 'p':
478                                    if ((optarg[0] == '-') && (optarg[1] == 0))
479                                    {
480                                            prompt_password = True;
481                                            break;
482                                    }
483    
484                                    STRNCPY(password, optarg, sizeof(password));
485                                    flags |= RDP_LOGON_AUTO;
486    
487                                    /* try to overwrite argument so it won't appear in ps */
488                                    p = optarg;
489                                    while (*p)
490                                            *(p++) = 'X';
491                                    break;
492    
493                            case 'n':
494                                    STRNCPY(g_hostname, optarg, sizeof(g_hostname));
495                                  break;                                  break;
496    
497                          case 'k':                          case 'k':
498                                  keylayout = strtol(optarg, NULL, 16);                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
499                                  break;                                  break;
500    
501                          case 'm':                          case 'g':
502                                  motion = True;                                  geometry_option = True;
503                                    g_fullscreen = False;
504                                    if (!strcmp(optarg, "workarea"))
505                                    {
506                                            g_width = g_height = 0;
507                                            break;
508                                    }
509    
510                                    g_width = strtol(optarg, &p, 10);
511                                    if (g_width <= 0)
512                                    {
513                                            error("invalid geometry\n");
514                                            return 1;
515                                    }
516    
517                                    if (*p == 'x')
518                                            g_height = strtol(p + 1, &p, 10);
519    
520                                    if (g_height <= 0)
521                                    {
522                                            error("invalid geometry\n");
523                                            return 1;
524                                    }
525    
526                                    if (*p == '%')
527                                    {
528                                            g_width = -g_width;
529                                            p++;
530                                    }
531    
532                                    if (*p == '+' || *p == '-')
533                                    {
534                                            g_pos |= (*p == '-') ? 2 : 1;
535                                            g_xpos = strtol(p, &p, 10);
536    
537                                    }
538                                    if (*p == '+' || *p == '-')
539                                    {
540                                            g_pos |= (*p == '-') ? 4 : 1;
541                                            g_ypos = strtol(p, NULL, 10);
542                                    }
543    
544                                    break;
545    
546                            case 'f':
547                                    g_fullscreen = True;
548                                  break;                                  break;
549    
550                          case 'b':                          case 'b':
551                                  orders = False;                                  g_bitmap_cache = False;
552                                    break;
553    
554                            case 'B':
555                                    g_ownbackstore = False;
556                                    break;
557    
558                            case 'e':
559                                    g_encryption = False;
560                                    break;
561                            case 'E':
562                                    packet_encryption = False;
563                                    break;
564                            case 'm':
565                                    g_sendmotion = False;
566                                    break;
567    
568                            case 'C':
569                                    g_owncolmap = True;
570                                    break;
571    
572                            case 'D':
573                                    g_hide_decorations = True;
574                                    break;
575    
576                            case 'K':
577                                    g_grab_keyboard = False;
578                                    break;
579    
580                            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                            case 'T':
598                                    STRNCPY(g_title, optarg, sizeof(g_title));
599                                    break;
600    
601                            case 'N':
602                                    g_numlock_sync = True;
603                                    break;
604    
605                            case 'X':
606                                    g_embed_wnd = strtol(optarg, NULL, 0);
607                                    break;
608    
609                            case 'a':
610                                    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                                    {
615                                            error("Invalid server colour depth.\n");
616                                            return 1;
617                                    }
618                                    break;
619    
620                            case 'z':
621                                    DEBUG(("rdp compression enabled\n"));
622                                    flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
623                                  break;                                  break;
624    
625                          case 'l':                          case 'x':
626                                  licence = False;                                  if (str_startswith(optarg, "m"))        /* modem */
627                                    {
628                                            g_rdp5_performanceflags =
629                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
630                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
631                                    }
632                                    else if (str_startswith(optarg, "b"))   /* broadband */
633                                    {
634                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
635                                    }
636                                    else if (str_startswith(optarg, "l"))   /* lan */
637                                    {
638                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
639                                    }
640                                    else
641                                    {
642                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
643                                    }
644                                  break;                                  break;
645    
646                            case 'P':
647                                    g_bitmap_cache_persist_enable = True;
648                                    break;
649    
650                            case 'r':
651    
652                                    if (str_startswith(optarg, "sound"))
653                                    {
654                                            optarg += 5;
655    
656                                            if (*optarg == ':')
657                                            {
658                                                    *optarg++;
659                                                    while ((p = next_arg(optarg, ',')))
660                                                    {
661                                                            if (str_startswith(optarg, "remote"))
662                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
663    
664                                                            if (str_startswith(optarg, "local"))
665    #ifdef WITH_RDPSND
666                                                                    g_rdpsnd = True;
667    #else
668                                                                    warning("Not compiled with sound support\n");
669    #endif
670    
671                                                            if (str_startswith(optarg, "off"))
672    #ifdef WITH_RDPSND
673                                                                    g_rdpsnd = False;
674    #else
675                                                                    warning("Not compiled with sound support\n");
676    #endif
677    
678                                                            optarg = p;
679                                                    }
680                                            }
681                                            else
682                                            {
683    #ifdef WITH_RDPSND
684                                                    g_rdpsnd = True;
685    #else
686                                                    warning("Not compiled with sound support\n");
687    #endif
688                                            }
689                                    }
690                                    else if (str_startswith(optarg, "disk"))
691                                    {
692                                            /* -r disk:h:=/mnt/floppy */
693                                            disk_enum_devices(&g_num_devices, optarg + 4);
694                                    }
695                                    else if (str_startswith(optarg, "comport"))
696                                    {
697                                            serial_enum_devices(&g_num_devices, optarg + 7);
698                                    }
699                                    else if (str_startswith(optarg, "lspci"))
700                                    {
701                                            lspci_enabled = True;
702                                    }
703                                    else if (str_startswith(optarg, "lptport"))
704                                    {
705                                            parallel_enum_devices(&g_num_devices, optarg + 7);
706                                    }
707                                    else if (str_startswith(optarg, "printer"))
708                                    {
709                                            printer_enum_devices(&g_num_devices, optarg + 7);
710                                    }
711                                    else if (str_startswith(optarg, "clientname"))
712                                    {
713                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
714                                            strcpy(g_rdpdr_clientname, optarg + 11);
715                                    }
716                                    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                                    else
733                                    {
734                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound, clipboard\n");
735                                    }
736                                    break;
737    
738                            case '0':
739                                    g_console_session = True;
740                                    break;
741    
742                            case '4':
743                                    g_use_rdp5 = False;
744                                    break;
745    
746                            case '5':
747                                    g_use_rdp5 = True;
748                                    break;
749    
750                            case 'h':
751                          case '?':                          case '?':
752                          default:                          default:
753                                  usage(argv[0]);                                  usage(argv[0]);
# Line 105  int main(int argc, char *argv[]) Line 755  int main(int argc, char *argv[])
755                  }                  }
756          }          }
757    
758          if (argc - optind < 1)          if (argc - optind != 1)
759          {          {
760                  usage(argv[0]);                  usage(argv[0]);
761                  return 1;                  return 1;
762          }          }
763    
764          server = argv[optind];          STRNCPY(server, argv[optind], sizeof(server));
765            parse_server_and_port(server);
766    
767            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          if (username[0] == 0)          if (!username_option)
805          {          {
806                  pw = getpwuid(getuid());                  pw = getpwuid(getuid());
807                  if ((pw == NULL) || (pw->pw_name == NULL))                  if ((pw == NULL) || (pw->pw_name == NULL))
808                  {                  {
809                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
810                          return 1;                          return 1;
811                  }                  }
812    
813                  strncpy(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
814          }          }
815    
816          if (hostname[0] == 0)  #ifdef HAVE_ICONV
817            if (g_codepage[0] == 0)
818          {          {
819                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (setlocale(LC_CTYPE, ""))
820                  {                  {
821                          STATUS("Could not determine host name.\n");                          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    
830            if (g_hostname[0] == 0)
831            {
832                    if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
833                    {
834                            error("could not determine local hostname, use -n\n");
835                          return 1;                          return 1;
836                  }                  }
837    
838                    p = strchr(fullhostname, '.');
839                    if (p != NULL)
840                            *p = 0;
841    
842                    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
843          }          }
844    
845          if (!rdp_connect(server))          if (g_keymapname[0] == 0)
846                  return 1;          {
847                    if (locale && xkeymap_from_locale(locale))
848                    {
849                            fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
850                    }
851                    else
852                    {
853                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
854                    }
855            }
856            if (locale)
857                    xfree(locale);
858    
859    
860          STATUS("Connection successful.\n");          if (prompt_password && read_password(password, sizeof(password)))
861                    flags |= RDP_LOGON_AUTO;
862    
863          snprintf(title, sizeof(title), "rdesktop - %s", server);          if (g_title[0] == 0)
         if (ui_create_window(title))  
864          {          {
865                  rdp_main_loop();                  strcpy(g_title, "rdesktop - ");
866                  ui_destroy_window();                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
867          }          }
868    
869          rdp_disconnect();  #ifdef RDP2VNC
870            rdp2vnc_connect(server, flags, domain, password, shell, directory);
871          return 0;          return 0;
872    #else
873    
874            if (!ui_init())
875                    return 1;
876    
877    #ifdef WITH_RDPSND
878            if (g_rdpsnd)
879                    rdpsnd_init();
880    #endif
881    
882            if (lspci_enabled)
883                    lspci_init();
884    
885            rdpdr_init();
886    
887            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    
898                    /* 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    
903    
904                    DEBUG(("Connection successful.\n"));
905                    memset(password, 0, sizeof(password));
906    
907                    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            }
939    
940            cache_save_state();
941            ui_deinit();
942    
943            if (ext_disc_reason >= 2)
944                    print_disconnect_reason(ext_disc_reason);
945    
946            if (deactivated)
947            {
948                    /* clean disconnect */
949                    return 0;
950            }
951            else
952            {
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    
966    #endif
967    
968  }  }
969    
970  /* Generate a 32-byte random for the secure transport code. */  #ifdef EGD_SOCKET
971  void generate_random(uint8 *random)  /* 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 stat st;          struct sockaddr_un addr;
976          uint32 *r = (uint32 *)random;          BOOL ret = False;
977          int fd;          int fd;
978    
979          /* If we have a kernel random device, use it. */          fd = socket(AF_UNIX, SOCK_STREAM, 0);
980          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          if (fd == -1)
981                    return False;
982    
983            addr.sun_family = AF_UNIX;
984            memcpy(addr.sun_path, EGD_SOCKET, sizeof(EGD_SOCKET));
985            if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
986                    goto err;
987    
988            /* PRNGD and EGD use a simple communications protocol */
989            buf[0] = 1;             /* Non-blocking (similar to /dev/urandom) */
990            buf[1] = 32;            /* Number of requested random bytes */
991            if (write(fd, buf, 2) != 2)
992                    goto err;
993    
994            if ((read(fd, buf, 1) != 1) || (buf[0] == 0))   /* Available? */
995                    goto err;
996    
997            if (read(fd, buf, 32) != 32)
998                    goto err;
999    
1000            ret = True;
1001    
1002          err:
1003            close(fd);
1004            return ret;
1005    }
1006    #endif
1007    
1008    /* Generate a 32-byte random for the secure transport code. */
1009    void
1010    generate_random(uint8 * random)
1011    {
1012            struct stat st;
1013            struct tms tmsbuf;
1014            MD5_CTX md5;
1015            uint32 *r;
1016            int fd, n;
1017    
1018            /* If we have a kernel random device, try that first */
1019            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
1020                || ((fd = open("/dev/random", O_RDONLY)) != -1))
1021          {          {
1022                  read(fd, random, 32);                  n = read(fd, random, 32);
1023                  close(fd);                  close(fd);
1024                  return;                  if (n == 32)
1025                            return;
1026          }          }
1027    
1028    #ifdef EGD_SOCKET
1029            /* As a second preference use an EGD */
1030            if (generate_random_egd(random))
1031                    return;
1032    #endif
1033    
1034          /* Otherwise use whatever entropy we can gather - ideas welcome. */          /* Otherwise use whatever entropy we can gather - ideas welcome. */
1035            r = (uint32 *) random;
1036          r[0] = (getpid()) | (getppid() << 16);          r[0] = (getpid()) | (getppid() << 16);
1037          r[1] = (getuid()) | (getgid() << 16);          r[1] = (getuid()) | (getgid() << 16);
1038          r[2] = times(NULL); /* system uptime (clocks) */          r[2] = times(&tmsbuf);  /* system uptime (clocks) */
1039          gettimeofday((struct timeval *)&r[3], NULL); /* sec and usec */          gettimeofday((struct timeval *) &r[3], NULL);   /* sec and usec */
1040          stat("/tmp", &st);          stat("/tmp", &st);
1041          r[5] = st.st_atime;          r[5] = st.st_atime;
1042          r[6] = st.st_mtime;          r[6] = st.st_mtime;
1043          r[7] = st.st_ctime;          r[7] = st.st_ctime;
1044    
1045            /* Hash both halves with MD5 to obscure possible patterns */
1046            MD5_Init(&md5);
1047            MD5_Update(&md5, random, 16);
1048            MD5_Final(random, &md5);
1049            MD5_Update(&md5, random + 16, 16);
1050            MD5_Final(random + 16, &md5);
1051  }  }
1052    
1053  /* malloc; exit if out of memory */  /* malloc; exit if out of memory */
1054  void *xmalloc(int size)  void *
1055    xmalloc(int size)
1056  {  {
1057          void *mem = malloc(size);          void *mem = malloc(size);
1058          if (mem == NULL)          if (mem == NULL)
1059          {          {
1060                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
1061                    exit(1);
1062            }
1063            return mem;
1064    }
1065    
1066    /* 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);                  exit(1);
1075          }          }
1076          return mem;          return mem;
1077  }  }
1078    
1079  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1080  void *xrealloc(void *oldmem, int size)  void *
1081    xrealloc(void *oldmem, int size)
1082  {  {
1083          void *mem = realloc(oldmem, size);          void *mem;
1084    
1085            if (size < 1)
1086                    size = 1;
1087            mem = realloc(oldmem, size);
1088          if (mem == NULL)          if (mem == NULL)
1089          {          {
1090                  ERROR("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
1091                  exit(1);                  exit(1);
1092          }          }
1093          return mem;          return mem;
1094  }  }
1095    
1096  /* free */  /* free */
1097  void xfree(void *mem)  void
1098    xfree(void *mem)
1099  {  {
1100          free(mem);          free(mem);
1101  }  }
1102    
1103  /* Produce a hex dump */  /* report an error */
1104  void hexdump(unsigned char *p, unsigned int len)  void
1105    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    /* 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    /* 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    hexdump(unsigned char *p, unsigned int len)
1145  {  {
1146          unsigned char *line = p;          unsigned char *line = p;
1147          unsigned int thisline, offset = 0;          int i, thisline, offset = 0;
         int i;  
1148    
1149          while (offset < len)          while (offset < len)
1150          {          {
1151                  STATUS("%04x ", offset);                  printf("%04x ", offset);
1152                  thisline = len - offset;                  thisline = len - offset;
1153                  if (thisline > 16)                  if (thisline > 16)
1154                          thisline = 16;                          thisline = 16;
1155    
1156                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1157                          STATUS("%02x ", line[i])                          printf("%02x ", line[i]);
1158    
1159                  for (; i < 16; i++)                  for (; i < 16; i++)
1160                          STATUS("   ");                          printf("   ");
1161    
1162                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1163                          STATUS("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
1164    
1165                  STATUS("\n");                  printf("\n");
1166                  offset += thisline;                  offset += thisline;
1167                  line += thisline;                  line += thisline;
1168          }          }
1169  }  }
1170    
1171    /*
1172      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      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    
1184            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            char *p;
1196            char *mvp = 0;
1197    
1198            /* EOS */
1199            if (*src == (char) 0x00)
1200                    return 0;
1201    
1202            p = src;
1203            /*  skip escaped needles */
1204            while ((nextval = strchr(p, needle)))
1205            {
1206                    mvp = nextval - 1;
1207                    /* found backslashed needle */
1208                    if (*mvp == '\\' && (mvp > src))
1209                    {
1210                            /* move string one to the left */
1211                            while (*(mvp + 1) != (char) 0x00)
1212                            {
1213                                    *mvp = *(mvp + 1);
1214                                    *mvp++;
1215                            }
1216                            *mvp = (char) 0x00;
1217                            p = nextval;
1218                    }
1219                    else
1220                    {
1221                            p = nextval + 1;
1222                            break;
1223                    }
1224    
1225            }
1226    
1227            /* more args available */
1228            if (nextval)
1229            {
1230                    *nextval = (char) 0x00;
1231                    return ++nextval;
1232            }
1233    
1234            /* no more args after this, jump to EOS */
1235            nextval = src + strlen(src);
1236            return nextval;
1237    }
1238    
1239    
1240    void
1241    toupper_str(char *p)
1242    {
1243            while (*p)
1244            {
1245                    if ((*p >= 'a') && (*p <= 'z'))
1246                            *p = toupper((int) *p);
1247                    p++;
1248            }
1249    }
1250    
1251    
1252    BOOL
1253    str_startswith(const char *s, const char *prefix)
1254    {
1255            return (strncmp(s, prefix, strlen(prefix)) == 0);
1256    }
1257    
1258    
1259    /* 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    /* not all clibs got ltoa */
1371    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1372    
1373    char *
1374    l_to_a(long N, int base)
1375    {
1376            static char ret[LTOA_BUFSIZE];
1377    
1378            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1379    
1380            register int divrem;
1381    
1382            if (base < 36 || 2 > base)
1383                    base = 10;
1384    
1385            if (N < 0)
1386            {
1387                    *head++ = '-';
1388                    N = -N;
1389            }
1390    
1391            tail = buf + sizeof(buf);
1392            *--tail = 0;
1393    
1394            do
1395            {
1396                    divrem = N % base;
1397                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1398                    N /= base;
1399            }
1400            while (N);
1401    
1402            strcpy(head, tail);
1403            return ret;
1404    }
1405    
1406    
1407    int
1408    load_licence(unsigned char **data)
1409    {
1410            char *home, *path;
1411            struct stat st;
1412            int fd, length;
1413    
1414            home = getenv("HOME");
1415            if (home == NULL)
1416                    return -1;
1417    
1418            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1419            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1420    
1421            fd = open(path, O_RDONLY);
1422            if (fd == -1)
1423                    return -1;
1424    
1425            if (fstat(fd, &st))
1426                    return -1;
1427    
1428            *data = (uint8 *) xmalloc(st.st_size);
1429            length = read(fd, *data, st.st_size);
1430            close(fd);
1431            xfree(path);
1432            return length;
1433    }
1434    
1435    void
1436    save_licence(unsigned char *data, int length)
1437    {
1438            char *home, *path, *tmppath;
1439            int fd;
1440    
1441            home = getenv("HOME");
1442            if (home == NULL)
1443                    return;
1444    
1445            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1446    
1447            sprintf(path, "%s/.rdesktop", home);
1448            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1449            {
1450                    perror(path);
1451                    return;
1452            }
1453    
1454            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1455    
1456            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1457            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1458            strcpy(tmppath, path);
1459            strcat(tmppath, ".new");
1460    
1461            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1462            if (fd == -1)
1463            {
1464                    perror(tmppath);
1465                    return;
1466            }
1467    
1468            if (write(fd, data, length) != length)
1469            {
1470                    perror(tmppath);
1471                    unlink(tmppath);
1472            }
1473            else if (rename(tmppath, path) == -1)
1474            {
1475                    perror(path);
1476                    unlink(tmppath);
1477            }
1478    
1479            close(fd);
1480            xfree(tmppath);
1481            xfree(path);
1482    }
1483    
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            int fd;
1522    
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            close(fd);
1538    }
1539    
1540    /* read from file*/
1541    int
1542    rd_read_file(int fd, void *ptr, int len)
1543    {
1544            return read(fd, ptr, len);
1545    }
1546    
1547    /* write to file */
1548    int
1549    rd_write_file(int fd, void *ptr, int len)
1550    {
1551            return write(fd, ptr, len);
1552    }
1553    
1554    /* move file pointer */
1555    int
1556    rd_lseek_file(int fd, int offset)
1557    {
1558            return lseek(fd, offset, SEEK_SET);
1559    }
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    }

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

  ViewVC Help
Powered by ViewVC 1.1.26