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

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

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

sourceforge.net/trunk/rdesktop/rdesktop.c revision 376 by jsorg71, Mon May 19 21:36:33 2003 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/rdesktop.c revision 1089 by astrand, Fri Mar 10 08:50:43 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- 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-2003     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
# Line 26  Line 26 
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>  #include <errno.h>
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33    #ifdef HAVE_LOCALE_H
34    #include <locale.h>
35    #endif
36    #ifdef HAVE_ICONV
37    #ifdef HAVE_LANGINFO_H
38    #include <langinfo.h>
39    #endif
40    #endif
41    
42  #ifdef EGD_SOCKET  #ifdef EGD_SOCKET
43    #include <sys/types.h>
44  #include <sys/socket.h>         /* socket connect */  #include <sys/socket.h>         /* socket connect */
45  #include <sys/un.h>             /* sockaddr_un */  #include <sys/un.h>             /* sockaddr_un */
46  #endif  #endif
47    
 #ifdef WITH_OPENSSL  
48  #include <openssl/md5.h>  #include <openssl/md5.h>
49  #else  
50  #include "crypto/md5.h"  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_console_session = False;
88    BOOL g_numlock_sync = False;
89    BOOL lspci_enabled = False;
90    BOOL g_owncolmap = False;
91    BOOL g_ownbackstore = True;     /* We can't rely on external BackingStore */
92    BOOL g_seamless_rdp = False;
93    uint32 g_embed_wnd;
94    uint32 g_rdp5_performanceflags =
95            RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS;
96    /* Session Directory redirection */
97    BOOL g_redirect = False;
98    char g_redirect_server[64];
99    char g_redirect_domain[16];
100    char g_redirect_password[64];
101    char g_redirect_username[64];
102    char g_redirect_cookie[128];
103    uint32 g_redirect_flags = 0;
104    
105    #ifdef WITH_RDPSND
106    BOOL g_rdpsnd = False;
107    #endif
108    
109    #ifdef HAVE_ICONV
110    char g_codepage[16] = "";
111  #endif  #endif
112    
113  char title[32] = "";  extern RDPDR_DEVICE g_rdpdr_device[];
114  char username[16];  extern uint32 g_num_devices;
115  char hostname[16];  extern char *g_rdpdr_clientname;
 char keymapname[16];  
 int keylayout = 0x409;          /* Defaults to US keyboard layout */  
 int width = 800;                /* If width or height are reset to zero, the geometry will  
                                    be fetched from _NET_WORKAREA */  
 int height = 600;  
 int tcp_port_rdp = TCP_PORT_RDP;  
 int server_bpp = 8;  
 int win_button_size = 0;        /* If zero, disable single app mode */  
 BOOL bitmap_compression = True;  
 BOOL sendmotion = True;  
 BOOL orders = True;  
 BOOL encryption = True;  
 BOOL desktop_save = True;  
 BOOL fullscreen = False;  
 BOOL grab_keyboard = True;  
 BOOL hide_decorations = False;  
 BOOL use_rdp5 = False;  
 extern BOOL owncolmap;  
116    
117  #ifdef RDP2VNC  #ifdef RDP2VNC
118  extern int rfb_port;  extern int rfb_port;
# Line 74  static void Line 126  static void
126  usage(char *program)  usage(char *program)
127  {  {
128          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
129          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
130          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
131    
132          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
133  #ifdef RDP2VNC  #ifdef RDP2VNC
134          fprintf(stderr, "   -V: vnc port\n");          fprintf(stderr, "   -V: vnc port\n");
135          fprintf(stderr, "   -E: defer time (ms)\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
136  #endif  #endif
137          fprintf(stderr, "   -u: user name\n");          fprintf(stderr, "   -u: user name\n");
138          fprintf(stderr, "   -d: domain\n");          fprintf(stderr, "   -d: domain\n");
139          fprintf(stderr, "   -s: shell\n");          fprintf(stderr, "   -s: shell\n");
         fprintf(stderr, "   -S: caption button size (single application mode)\n");  
140          fprintf(stderr, "   -c: working directory\n");          fprintf(stderr, "   -c: working directory\n");
141          fprintf(stderr, "   -p: password (- to prompt)\n");          fprintf(stderr, "   -p: password (- to prompt)\n");
142          fprintf(stderr, "   -n: client hostname\n");          fprintf(stderr, "   -n: client hostname\n");
143          fprintf(stderr, "   -k: keyboard layout on terminal server (us,sv,gr,etc.)\n");          fprintf(stderr, "   -k: keyboard layout on server (en-us, de, sv, etc.)\n");
144          fprintf(stderr, "   -g: desktop geometry (WxH)\n");          fprintf(stderr, "   -g: desktop geometry (WxH)\n");
145          fprintf(stderr, "   -f: full-screen mode\n");          fprintf(stderr, "   -f: full-screen mode\n");
146          fprintf(stderr, "   -b: force bitmap updates\n");          fprintf(stderr, "   -b: force bitmap updates\n");
147    #ifdef HAVE_ICONV
148            fprintf(stderr, "   -L: local codepage\n");
149    #endif
150            fprintf(stderr, "   -A: enable SeamlessRDP mode\n");
151            fprintf(stderr, "   -B: use BackingStore of X-server (if available)\n");
152          fprintf(stderr, "   -e: disable encryption (French TS)\n");          fprintf(stderr, "   -e: disable encryption (French TS)\n");
153            fprintf(stderr, "   -E: disable encryption from client to server\n");
154          fprintf(stderr, "   -m: do not send motion events\n");          fprintf(stderr, "   -m: do not send motion events\n");
155          fprintf(stderr, "   -C: use private colour map\n");          fprintf(stderr, "   -C: use private colour map\n");
156            fprintf(stderr, "   -D: hide window manager decorations\n");
157          fprintf(stderr, "   -K: keep window manager key bindings\n");          fprintf(stderr, "   -K: keep window manager key bindings\n");
158            fprintf(stderr, "   -S: caption button size (single application mode)\n");
159          fprintf(stderr, "   -T: window title\n");          fprintf(stderr, "   -T: window title\n");
160          fprintf(stderr, "   -D: hide window manager decorations\n");          fprintf(stderr, "   -N: enable numlock syncronization\n");
161          fprintf(stderr, "   -a: server bpp\n");          fprintf(stderr, "   -X: embed into another window with a given id.\n");
162          fprintf(stderr, "   -5: Use RDP5 (EXPERIMENTAL!)\n");          fprintf(stderr, "   -a: connection colour depth\n");
163            fprintf(stderr, "   -z: enable rdp compression\n");
164            fprintf(stderr, "   -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n");
165            fprintf(stderr, "   -P: use persistent bitmap caching\n");
166            fprintf(stderr, "   -r: enable specified device redirection (this flag can be repeated)\n");
167            fprintf(stderr,
168                    "         '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n");
169            fprintf(stderr, "             or      COM1=/dev/ttyS0,COM2=/dev/ttyS1\n");
170            fprintf(stderr,
171                    "         '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n");
172            fprintf(stderr, "             or   'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n");
173            fprintf(stderr, "         '-r clientname=<client name>': Set the client name displayed\n");
174            fprintf(stderr, "             for redirected disks\n");
175            fprintf(stderr,
176                    "         '-r lptport:LPT1=/dev/lp0': enable parallel redirection of /dev/lp0 to LPT1\n");
177            fprintf(stderr, "             or      LPT1=/dev/lp0,LPT2=/dev/lp1\n");
178            fprintf(stderr, "         '-r printer:mydeskjet': enable printer redirection\n");
179            fprintf(stderr,
180                    "             or      mydeskjet=\"HP LaserJet IIIP\" to enter server driver as well\n");
181            fprintf(stderr, "         '-r sound:[local|off|remote]': enable sound redirection\n");
182            fprintf(stderr, "                     remote would leave sound on server\n");
183            fprintf(stderr, "   -0: attach to console\n");
184            fprintf(stderr, "   -4: use RDP version 4\n");
185            fprintf(stderr, "   -5: use RDP version 5 (default)\n");
186    }
187    
188    static void
189    print_disconnect_reason(uint16 reason)
190    {
191            char *text;
192    
193            switch (reason)
194            {
195                    case exDiscReasonNoInfo:
196                            text = "No information available";
197                            break;
198    
199                    case exDiscReasonAPIInitiatedDisconnect:
200                            text = "Server initiated disconnect";
201                            break;
202    
203                    case exDiscReasonAPIInitiatedLogoff:
204                            text = "Server initiated logoff";
205                            break;
206    
207                    case exDiscReasonServerIdleTimeout:
208                            text = "Server idle timeout reached";
209                            break;
210    
211                    case exDiscReasonServerLogonTimeout:
212                            text = "Server logon timeout reached";
213                            break;
214    
215                    case exDiscReasonReplacedByOtherConnection:
216                            text = "The session was replaced";
217                            break;
218    
219                    case exDiscReasonOutOfMemory:
220                            text = "The server is out of memory";
221                            break;
222    
223                    case exDiscReasonServerDeniedConnection:
224                            text = "The server denied the connection";
225                            break;
226    
227                    case exDiscReasonServerDeniedConnectionFips:
228                            text = "The server denied the connection for security reason";
229                            break;
230    
231                    case exDiscReasonLicenseInternal:
232                            text = "Internal licensing error";
233                            break;
234    
235                    case exDiscReasonLicenseNoLicenseServer:
236                            text = "No license server available";
237                            break;
238    
239                    case exDiscReasonLicenseNoLicense:
240                            text = "No valid license available";
241                            break;
242    
243                    case exDiscReasonLicenseErrClientMsg:
244                            text = "Invalid licensing message";
245                            break;
246    
247                    case exDiscReasonLicenseHwidDoesntMatchLicense:
248                            text = "Hardware id doesn't match software license";
249                            break;
250    
251                    case exDiscReasonLicenseErrClientLicense:
252                            text = "Client license error";
253                            break;
254    
255                    case exDiscReasonLicenseCantFinishProtocol:
256                            text = "Network error during licensing protocol";
257                            break;
258    
259                    case exDiscReasonLicenseClientEndedProtocol:
260                            text = "Licensing protocol was not completed";
261                            break;
262    
263                    case exDiscReasonLicenseErrClientEncryption:
264                            text = "Incorrect client license enryption";
265                            break;
266    
267                    case exDiscReasonLicenseCantUpgradeLicense:
268                            text = "Can't upgrade license";
269                            break;
270    
271                    case exDiscReasonLicenseNoRemoteConnections:
272                            text = "The server is not licensed to accept remote connections";
273                            break;
274    
275                    default:
276                            if (reason > 0x1000 && reason < 0x7fff)
277                            {
278                                    text = "Internal protocol error";
279                            }
280                            else
281                            {
282                                    text = "Unknown reason";
283                            }
284            }
285            fprintf(stderr, "disconnect: %s.\n", text);
286    }
287    
288    static void
289    rdesktop_reset_state(void)
290    {
291            rdp_reset_state();
292  }  }
293    
294  static BOOL  static BOOL
# Line 139  read_password(char *password, int size) Line 327  read_password(char *password, int size)
327          return ret;          return ret;
328  }  }
329    
330    static void
331    parse_server_and_port(char *server)
332    {
333            char *p;
334    #ifdef IPv6
335            int addr_colons;
336    #endif
337    
338    #ifdef IPv6
339            p = server;
340            addr_colons = 0;
341            while (*p)
342                    if (*p++ == ':')
343                            addr_colons++;
344            if (addr_colons >= 2)
345            {
346                    /* numeric IPv6 style address format - [1:2:3::4]:port */
347                    p = strchr(server, ']');
348                    if (*server == '[' && p != NULL)
349                    {
350                            if (*(p + 1) == ':' && *(p + 2) != '\0')
351                                    g_tcp_port_rdp = strtol(p + 2, NULL, 10);
352                            /* remove the port number and brackets from the address */
353                            *p = '\0';
354                            strncpy(server, server + 1, strlen(server));
355                    }
356            }
357            else
358            {
359                    /* dns name or IPv4 style address format - server.example.com:port or 1.2.3.4:port */
360                    p = strchr(server, ':');
361                    if (p != NULL)
362                    {
363                            g_tcp_port_rdp = strtol(p + 1, NULL, 10);
364                            *p = 0;
365                    }
366            }
367    #else /* no IPv6 support */
368            p = strchr(server, ':');
369            if (p != NULL)
370            {
371                    g_tcp_port_rdp = strtol(p + 1, NULL, 10);
372                    *p = 0;
373            }
374    #endif /* IPv6 */
375    
376    }
377    
378  /* Client program */  /* Client program */
379  int  int
380  main(int argc, char *argv[])  main(int argc, char *argv[])
# Line 146  main(int argc, char *argv[]) Line 382  main(int argc, char *argv[])
382          char server[64];          char server[64];
383          char fullhostname[64];          char fullhostname[64];
384          char domain[16];          char domain[16];
385          char password[16];          char password[64];
386          char shell[128];          char shell[256];
387          char directory[32];          char directory[256];
388          BOOL prompt_password;          BOOL prompt_password, deactivated;
389          struct passwd *pw;          struct passwd *pw;
390          uint32 flags;          uint32 flags, ext_disc_reason = 0;
391          char *p;          char *p;
392          int c;          int c;
393            char *locale = NULL;
394          int username_option = 0;          int username_option = 0;
395            BOOL geometry_option = False;
396            int run_count = 0;      /* Session Directory support */
397            BOOL continue_connect = True;   /* Session Directory support */
398    
399    #ifdef HAVE_LOCALE_H
400            /* Set locale according to environment */
401            locale = setlocale(LC_ALL, "");
402            if (locale)
403            {
404                    locale = xstrdup(locale);
405            }
406    
407    #endif
408          flags = RDP_LOGON_NORMAL;          flags = RDP_LOGON_NORMAL;
409          prompt_password = False;          prompt_password = False;
410          domain[0] = password[0] = shell[0] = directory[0] = 0;          domain[0] = password[0] = shell[0] = directory[0] = 0;
411          strcpy(keymapname, "en-us");          g_embed_wnd = 0;
412    
413            g_num_devices = 0;
414    
415  #ifdef RDP2VNC  #ifdef RDP2VNC
416  #define VNCOPT "V:E:"  #define VNCOPT "V:Q:"
417  #else  #else
418  #define VNCOPT  #define VNCOPT
419  #endif  #endif
420    
421          while ((c = getopt(argc, argv, VNCOPT "u:d:s:S:c:p:n:k:g:a:fbemCKT:Dh?54")) != -1)          while ((c = getopt(argc, argv,
422                               VNCOPT "Au:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1)
423          {          {
424                  switch (c)                  switch (c)
425                  {                  {
# Line 178  main(int argc, char *argv[]) Line 430  main(int argc, char *argv[])
430                                          rfb_port += 5900;                                          rfb_port += 5900;
431                                  break;                                  break;
432    
433                          case 'E':                          case 'Q':
434                                  defer_time = strtol(optarg, NULL, 10);                                  defer_time = strtol(optarg, NULL, 10);
435                                  if (defer_time < 0)                                  if (defer_time < 0)
436                                          defer_time = 0;                                          defer_time = 0;
437                                  break;                                  break;
438  #endif  #endif
439    
440                            case 'A':
441                                    g_seamless_rdp = True;
442                                    break;
443    
444                          case 'u':                          case 'u':
445                                  STRNCPY(username, optarg, sizeof(username));                                  STRNCPY(g_username, optarg, sizeof(g_username));
446                                  username_option = 1;                                  username_option = 1;
447                                  break;                                  break;
448    
449                            case 'L':
450    #ifdef HAVE_ICONV
451                                    STRNCPY(g_codepage, optarg, sizeof(g_codepage));
452    #else
453                                    error("iconv support not available\n");
454    #endif
455                                    break;
456    
457                          case 'd':                          case 'd':
458                                  STRNCPY(domain, optarg, sizeof(domain));                                  STRNCPY(domain, optarg, sizeof(domain));
459                                  break;                                  break;
# Line 198  main(int argc, char *argv[]) Line 462  main(int argc, char *argv[])
462                                  STRNCPY(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
463                                  break;                                  break;
464    
                         case 'S':  
                                 if (!strcmp(optarg, "standard"))  
                                 {  
                                         win_button_size = 18;  
                                         break;  
                                 }  
   
                                 win_button_size = strtol(optarg, &p, 10);  
   
                                 if (*p)  
                                 {  
                                         error("invalid button size\n");  
                                         return 1;  
                                 }  
   
                                 break;  
   
465                          case 'c':                          case 'c':
466                                  STRNCPY(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
467                                  break;                                  break;
# Line 236  main(int argc, char *argv[]) Line 483  main(int argc, char *argv[])
483                                  break;                                  break;
484    
485                          case 'n':                          case 'n':
486                                  STRNCPY(hostname, optarg, sizeof(hostname));                                  STRNCPY(g_hostname, optarg, sizeof(g_hostname));
487                                  break;                                  break;
488    
489                          case 'k':                          case 'k':
490                                  STRNCPY(keymapname, optarg, sizeof(keymapname));                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
491                                  break;                                  break;
492    
493                          case 'g':                          case 'g':
494                                    geometry_option = True;
495                                    g_fullscreen = False;
496                                  if (!strcmp(optarg, "workarea"))                                  if (!strcmp(optarg, "workarea"))
497                                  {                                  {
498                                          width = height = 0;                                          g_width = g_height = 0;
499                                          break;                                          break;
500                                  }                                  }
501    
502                                  width = strtol(optarg, &p, 10);                                  g_width = strtol(optarg, &p, 10);
503                                    if (g_width <= 0)
504                                    {
505                                            error("invalid geometry\n");
506                                            return 1;
507                                    }
508    
509                                  if (*p == 'x')                                  if (*p == 'x')
510                                          height = strtol(p + 1, NULL, 10);                                          g_height = strtol(p + 1, &p, 10);
511    
512                                  if ((width == 0) || (height == 0))                                  if (g_height <= 0)
513                                  {                                  {
514                                          error("invalid geometry\n");                                          error("invalid geometry\n");
515                                          return 1;                                          return 1;
516                                  }                                  }
517    
518                                    if (*p == '%')
519                                    {
520                                            g_width = -g_width;
521                                            p++;
522                                    }
523    
524                                    if (*p == '+' || *p == '-')
525                                    {
526                                            g_pos |= (*p == '-') ? 2 : 1;
527                                            g_xpos = strtol(p, &p, 10);
528    
529                                    }
530                                    if (*p == '+' || *p == '-')
531                                    {
532                                            g_pos |= (*p == '-') ? 4 : 1;
533                                            g_ypos = strtol(p, NULL, 10);
534                                    }
535    
536                                  break;                                  break;
537    
538                          case 'f':                          case 'f':
539                                  fullscreen = True;                                  g_fullscreen = True;
540                                  break;                                  break;
541    
542                          case 'b':                          case 'b':
543                                  orders = False;                                  g_bitmap_cache = False;
544                                  break;                                  break;
545    
546                          case 'e':                          case 'B':
547                                  encryption = False;                                  g_ownbackstore = False;
548                                  break;                                  break;
549    
550                            case 'e':
551                                    g_encryption = False;
552                                    break;
553                            case 'E':
554                                    packet_encryption = False;
555                                    break;
556                          case 'm':                          case 'm':
557                                  sendmotion = False;                                  g_sendmotion = False;
558                                  break;                                  break;
559    
560                          case 'C':                          case 'C':
561                                  owncolmap = True;                                  g_owncolmap = True;
562                                    break;
563    
564                            case 'D':
565                                    g_hide_decorations = True;
566                                  break;                                  break;
567    
568                          case 'K':                          case 'K':
569                                  grab_keyboard = False;                                  g_grab_keyboard = False;
570                                    break;
571    
572                            case 'S':
573                                    if (!strcmp(optarg, "standard"))
574                                    {
575                                            g_win_button_size = 18;
576                                            break;
577                                    }
578    
579                                    g_win_button_size = strtol(optarg, &p, 10);
580    
581                                    if (*p)
582                                    {
583                                            error("invalid button size\n");
584                                            return 1;
585                                    }
586    
587                                  break;                                  break;
588    
589                          case 'T':                          case 'T':
590                                  STRNCPY(title, optarg, sizeof(title));                                  STRNCPY(g_title, optarg, sizeof(g_title));
591                                  break;                                  break;
592    
593                          case 'D':                          case 'N':
594                                  hide_decorations = True;                                  g_numlock_sync = True;
595                                    break;
596    
597                            case 'X':
598                                    g_embed_wnd = strtol(optarg, NULL, 0);
599                                  break;                                  break;
600    
601                          case 'a':                          case 'a':
602                                  server_bpp = strtol(optarg, NULL, 10);                                  g_server_depth = strtol(optarg, NULL, 10);
603                                  if (server_bpp != 8 && server_bpp != 16 && server_bpp != 15                                  if (g_server_depth != 8 &&
604                                      && server_bpp != 24)                                      g_server_depth != 16 &&
605                                        g_server_depth != 15 && g_server_depth != 24)
606                                  {                                  {
607                                          error("invalid server bpp\n");                                          error("Invalid server colour depth.\n");
608                                          return 1;                                          return 1;
609                                  }                                  }
610                                  break;                                  break;
611    
612                            case 'z':
613                                    DEBUG(("rdp compression enabled\n"));
614                                    flags |= (RDP_LOGON_COMPRESSION | RDP_LOGON_COMPRESSION2);
615                                    break;
616    
617                            case 'x':
618                                    if (str_startswith(optarg, "m"))        /* modem */
619                                    {
620                                            g_rdp5_performanceflags =
621                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
622                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
623                                    }
624                                    else if (str_startswith(optarg, "b"))   /* broadband */
625                                    {
626                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
627                                    }
628                                    else if (str_startswith(optarg, "l"))   /* lan */
629                                    {
630                                            g_rdp5_performanceflags = RDP5_DISABLE_NOTHING;
631                                    }
632                                    else
633                                    {
634                                            g_rdp5_performanceflags = strtol(optarg, NULL, 16);
635                                    }
636                                    break;
637    
638                            case 'P':
639                                    g_bitmap_cache_persist_enable = True;
640                                    break;
641    
642                            case 'r':
643    
644                                    if (str_startswith(optarg, "sound"))
645                                    {
646                                            optarg += 5;
647    
648                                            if (*optarg == ':')
649                                            {
650                                                    *optarg++;
651                                                    while ((p = next_arg(optarg, ',')))
652                                                    {
653                                                            if (str_startswith(optarg, "remote"))
654                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
655    
656                                                            if (str_startswith(optarg, "local"))
657    #ifdef WITH_RDPSND
658                                                                    g_rdpsnd = True;
659    #else
660                                                                    warning("Not compiled with sound support\n");
661    #endif
662    
663                                                            if (str_startswith(optarg, "off"))
664    #ifdef WITH_RDPSND
665                                                                    g_rdpsnd = False;
666    #else
667                                                                    warning("Not compiled with sound support\n");
668    #endif
669    
670                                                            optarg = p;
671                                                    }
672                                            }
673                                            else
674                                            {
675    #ifdef WITH_RDPSND
676                                                    g_rdpsnd = True;
677    #else
678                                                    warning("Not compiled with sound support\n");
679    #endif
680                                            }
681                                    }
682                                    else if (str_startswith(optarg, "disk"))
683                                    {
684                                            /* -r disk:h:=/mnt/floppy */
685                                            disk_enum_devices(&g_num_devices, optarg + 4);
686                                    }
687                                    else if (str_startswith(optarg, "comport"))
688                                    {
689                                            serial_enum_devices(&g_num_devices, optarg + 7);
690                                    }
691                                    else if (str_startswith(optarg, "lspci"))
692                                    {
693                                            lspci_enabled = True;
694                                    }
695                                    else if (str_startswith(optarg, "lptport"))
696                                    {
697                                            parallel_enum_devices(&g_num_devices, optarg + 7);
698                                    }
699                                    else if (str_startswith(optarg, "printer"))
700                                    {
701                                            printer_enum_devices(&g_num_devices, optarg + 7);
702                                    }
703                                    else if (str_startswith(optarg, "clientname"))
704                                    {
705                                            g_rdpdr_clientname = xmalloc(strlen(optarg + 11) + 1);
706                                            strcpy(g_rdpdr_clientname, optarg + 11);
707                                    }
708                                    else
709                                    {
710                                            warning("Unknown -r argument\n\n\tPossible arguments are: comport, disk, lptport, printer, sound\n");
711                                    }
712                                    break;
713    
714                            case '0':
715                                    g_console_session = True;
716                                    break;
717    
718                            case '4':
719                                    g_use_rdp5 = False;
720                                    break;
721    
722                          case '5':                          case '5':
723                                  use_rdp5 = True;                                  g_use_rdp5 = True;
724                                  break;                                  break;
725    
726                          case 'h':                          case 'h':
727                          case '?':                          case '?':
728                          default:                          default:
# Line 314  main(int argc, char *argv[]) Line 731  main(int argc, char *argv[])
731                  }                  }
732          }          }
733    
734          if (argc - optind < 1)          if (argc - optind != 1)
735          {          {
736                  usage(argv[0]);                  usage(argv[0]);
737                  return 1;                  return 1;
738          }          }
739    
740          STRNCPY(server, argv[optind], sizeof(server));          STRNCPY(server, argv[optind], sizeof(server));
741          p = strchr(server, ':');          parse_server_and_port(server);
742          if (p != NULL)  
743            if (g_seamless_rdp)
744          {          {
745                  tcp_port_rdp = strtol(p + 1, NULL, 10);                  if (g_win_button_size)
746                  *p = 0;                  {
747                            error("You cannot use -S and -A at the same time\n");
748                            return 1;
749                    }
750                    g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG;
751                    if (geometry_option)
752                    {
753                            error("You cannot use -g and -A at the same time\n");
754                            return 1;
755                    }
756                    if (g_fullscreen)
757                    {
758                            error("You cannot use -f and -A at the same time\n");
759                            return 1;
760                    }
761                    if (g_hide_decorations)
762                    {
763                            error("You cannot use -D and -A at the same time\n");
764                            return 1;
765                    }
766                    if (g_embed_wnd)
767                    {
768                            error("You cannot use -X and -A at the same time\n");
769                            return 1;
770                    }
771                    if (!g_use_rdp5)
772                    {
773                            error("You cannot use -4 and -A at the same time\n");
774                            return 1;
775                    }
776                    g_width = -100;
777                    g_grab_keyboard = False;
778          }          }
779    
780          if (!username_option)          if (!username_option)
# Line 337  main(int argc, char *argv[]) Line 786  main(int argc, char *argv[])
786                          return 1;                          return 1;
787                  }                  }
788    
789                  STRNCPY(username, pw->pw_name, sizeof(username));                  STRNCPY(g_username, pw->pw_name, sizeof(g_username));
790          }          }
791    
792          if (hostname[0] == 0)  #ifdef HAVE_ICONV
793            if (g_codepage[0] == 0)
794            {
795                    if (setlocale(LC_CTYPE, ""))
796                    {
797                            STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage));
798                    }
799                    else
800                    {
801                            STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage));
802                    }
803            }
804    #endif
805    
806            if (g_hostname[0] == 0)
807          {          {
808                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
809                  {                  {
# Line 352  main(int argc, char *argv[]) Line 815  main(int argc, char *argv[])
815                  if (p != NULL)                  if (p != NULL)
816                          *p = 0;                          *p = 0;
817    
818                  STRNCPY(hostname, fullhostname, sizeof(hostname));                  STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
819            }
820    
821            if (g_keymapname[0] == 0)
822            {
823                    if (locale && xkeymap_from_locale(locale))
824                    {
825                            fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
826                    }
827                    else
828                    {
829                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
830                    }
831          }          }
832            if (locale)
833                    xfree(locale);
834    
835    
836          if (prompt_password && read_password(password, sizeof(password)))          if (prompt_password && read_password(password, sizeof(password)))
837                  flags |= RDP_LOGON_AUTO;                  flags |= RDP_LOGON_AUTO;
838    
839          if (title[0] == 0)          if (g_title[0] == 0)
840          {          {
841                  strcpy(title, "rdesktop - ");                  strcpy(g_title, "rdesktop - ");
842                  strncat(title, server, sizeof(title) - sizeof("rdesktop - "));                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
843          }          }
844    
845  #ifdef RDP2VNC  #ifdef RDP2VNC
846          rdp2vnc_connect(server, flags, domain, password, shell, directory);          rdp2vnc_connect(server, flags, domain, password, shell, directory);
847            return 0;
848  #else  #else
849    
850          if (!ui_init())          if (!ui_init())
851                  return 1;                  return 1;
852    
853          if (!rdp_connect(server, flags, domain, password, shell, directory))  #ifdef WITH_RDPSND
854                  return 1;          if (g_rdpsnd)
855                    rdpsnd_init();
856    #endif
857    
858          DEBUG(("Connection successful.\n"));          if (lspci_enabled)
859          memset(password, 0, sizeof(password));                  lspci_init();
860    
861          if (ui_create_window())          rdpdr_init();
862    
863            while (run_count < 2 && continue_connect)       /* add support for Session Directory; only reconnect once */
864          {          {
865                  rdp_main_loop();                  if (run_count == 0)
866                  ui_destroy_window();                  {
867                            if (!rdp_connect(server, flags, domain, password, shell, directory))
868                                    return 1;
869                    }
870                    else if (!rdp_reconnect
871                             (server, flags, domain, password, shell, directory, g_redirect_cookie))
872                            return 1;
873    
874                    /* By setting encryption to False here, we have an encrypted login
875                       packet but unencrypted transfer of other packets */
876                    if (!packet_encryption)
877                            g_encryption = False;
878    
879    
880                    DEBUG(("Connection successful.\n"));
881                    memset(password, 0, sizeof(password));
882    
883                    if (run_count == 0)
884                            if (!ui_create_window())
885                                    continue_connect = False;
886    
887                    if (continue_connect)
888                            rdp_main_loop(&deactivated, &ext_disc_reason);
889    
890                    DEBUG(("Disconnecting...\n"));
891                    rdp_disconnect();
892    
893                    if ((g_redirect == True) && (run_count == 0))   /* Support for Session Directory */
894                    {
895                            /* reset state of major globals */
896                            rdesktop_reset_state();
897    
898                            STRNCPY(domain, g_redirect_domain, sizeof(domain));
899                            STRNCPY(g_username, g_redirect_username, sizeof(g_username));
900                            STRNCPY(password, g_redirect_password, sizeof(password));
901                            STRNCPY(server, g_redirect_server, sizeof(server));
902                            flags |= RDP_LOGON_AUTO;
903    
904                            g_redirect = False;
905                    }
906                    else
907                    {
908                            continue_connect = False;
909                            ui_destroy_window();
910                            break;
911                    }
912    
913                    run_count++;
914          }          }
915    
916          DEBUG(("Disconnecting...\n"));          cache_save_state();
         rdp_disconnect();  
917          ui_deinit();          ui_deinit();
918    
919            if (ext_disc_reason >= 2)
920                    print_disconnect_reason(ext_disc_reason);
921    
922            if (deactivated)
923            {
924                    /* clean disconnect */
925                    return 0;
926            }
927            else
928            {
929                    if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect
930                        || ext_disc_reason == exDiscReasonAPIInitiatedLogoff)
931                    {
932                            /* not so clean disconnect, but nothing to worry about */
933                            return 0;
934                    }
935                    else
936                    {
937                            /* return error */
938                            return 2;
939                    }
940            }
941    
942  #endif  #endif
943    
         return 0;  
944  }  }
945    
946  #ifdef EGD_SOCKET  #ifdef EGD_SOCKET
# Line 488  xmalloc(int size) Line 1039  xmalloc(int size)
1039          return mem;          return mem;
1040  }  }
1041    
1042    /* strdup */
1043    char *
1044    xstrdup(const char *s)
1045    {
1046            char *mem = strdup(s);
1047            if (mem == NULL)
1048            {
1049                    perror("strdup");
1050                    exit(1);
1051            }
1052            return mem;
1053    }
1054    
1055  /* realloc; exit if out of memory */  /* realloc; exit if out of memory */
1056  void *  void *
1057  xrealloc(void *oldmem, int size)  xrealloc(void *oldmem, int size)
1058  {  {
1059          void *mem = realloc(oldmem, size);          void *mem;
1060    
1061            if (size < 1)
1062                    size = 1;
1063            mem = realloc(oldmem, size);
1064          if (mem == NULL)          if (mem == NULL)
1065          {          {
1066                  error("xrealloc %d\n", size);                  error("xrealloc %d\n", size);
# Line 549  unimpl(char *format, ...) Line 1117  unimpl(char *format, ...)
1117    
1118  /* produce a hex dump */  /* produce a hex dump */
1119  void  void
1120  hexdump(unsigned char *p, int len)  hexdump(unsigned char *p, unsigned int len)
1121  {  {
1122          unsigned char *line = p;          unsigned char *line = p;
1123          int i, thisline, offset = 0;          int i, thisline, offset = 0;
# Line 576  hexdump(unsigned char *p, int len) Line 1144  hexdump(unsigned char *p, int len)
1144          }          }
1145  }  }
1146    
1147    /*
1148      input: src is the string we look in for needle.
1149             Needle may be escaped by a backslash, in
1150             that case we ignore that particular needle.
1151      return value: returns next src pointer, for
1152            succesive executions, like in a while loop
1153            if retval is 0, then there are no more args.
1154      pitfalls:
1155            src is modified. 0x00 chars are inserted to
1156            terminate strings.
1157            return val, points on the next val chr after ins
1158            0x00
1159    
1160            example usage:
1161            while( (pos = next_arg( optarg, ',')) ){
1162                    printf("%s\n",optarg);
1163                    optarg=pos;
1164            }
1165    
1166    */
1167    char *
1168    next_arg(char *src, char needle)
1169    {
1170            char *nextval;
1171            char *p;
1172            char *mvp = 0;
1173    
1174            /* EOS */
1175            if (*src == (char) 0x00)
1176                    return 0;
1177    
1178            p = src;
1179            /*  skip escaped needles */
1180            while ((nextval = strchr(p, needle)))
1181            {
1182                    mvp = nextval - 1;
1183                    /* found backslashed needle */
1184                    if (*mvp == '\\' && (mvp > src))
1185                    {
1186                            /* move string one to the left */
1187                            while (*(mvp + 1) != (char) 0x00)
1188                            {
1189                                    *mvp = *(mvp + 1);
1190                                    *mvp++;
1191                            }
1192                            *mvp = (char) 0x00;
1193                            p = nextval;
1194                    }
1195                    else
1196                    {
1197                            p = nextval + 1;
1198                            break;
1199                    }
1200    
1201            }
1202    
1203            /* more args available */
1204            if (nextval)
1205            {
1206                    *nextval = (char) 0x00;
1207                    return ++nextval;
1208            }
1209    
1210            /* no more args after this, jump to EOS */
1211            nextval = src + strlen(src);
1212            return nextval;
1213    }
1214    
1215    
1216    void
1217    toupper_str(char *p)
1218    {
1219            while (*p)
1220            {
1221                    if ((*p >= 'a') && (*p <= 'z'))
1222                            *p = toupper((int) *p);
1223                    p++;
1224            }
1225    }
1226    
1227    
1228    BOOL
1229    str_startswith(const char *s, const char *prefix)
1230    {
1231            return (strncmp(s, prefix, strlen(prefix)) == 0);
1232    }
1233    
1234    
1235    /* Split input into lines, and call linehandler for each
1236       line. Incomplete lines are saved in the rest variable, which should
1237       initially point to NULL. When linehandler returns False, stop and
1238       return False. Otherwise, return True.  */
1239    BOOL
1240    str_handle_lines(const char *input, char **rest, str_handle_lines_t linehandler, void *data)
1241    {
1242            char *buf, *p;
1243            char *oldrest;
1244            size_t inputlen;
1245            size_t buflen;
1246            size_t restlen = 0;
1247            BOOL ret = True;
1248    
1249            /* Copy data to buffer */
1250            inputlen = strlen(input);
1251            if (*rest)
1252                    restlen = strlen(*rest);
1253            buflen = restlen + inputlen + 1;
1254            buf = (char *) xmalloc(buflen);
1255            buf[0] = '\0';
1256            if (*rest)
1257                    STRNCPY(buf, *rest, buflen);
1258            strncat(buf, input, inputlen);
1259            p = buf;
1260    
1261            while (1)
1262            {
1263                    char *newline = strchr(p, '\n');
1264                    if (newline)
1265                    {
1266                            *newline = '\0';
1267                            if (!linehandler(p, data))
1268                            {
1269                                    p = newline + 1;
1270                                    ret = False;
1271                                    break;
1272                            }
1273                            p = newline + 1;
1274                    }
1275                    else
1276                    {
1277                            break;
1278    
1279                    }
1280            }
1281    
1282            /* Save in rest */
1283            oldrest = *rest;
1284            restlen = buf + buflen - p;
1285            *rest = (char *) xmalloc(restlen);
1286            STRNCPY((*rest), p, restlen);
1287            xfree(oldrest);
1288    
1289            xfree(buf);
1290            return ret;
1291    }
1292    
1293    /* Execute the program specified by argv. For each line in
1294       stdout/stderr output, call linehandler. Returns false on failure. */
1295    BOOL
1296    subprocess(char *const argv[], str_handle_lines_t linehandler, void *data)
1297    {
1298            pid_t child;
1299            int fd[2];
1300            int n = 1;
1301            char output[256];
1302            char *rest = NULL;
1303    
1304            if (pipe(fd) < 0)
1305            {
1306                    perror("pipe");
1307                    return False;
1308            }
1309    
1310            if ((child = fork()) < 0)
1311            {
1312                    perror("fork");
1313                    return False;
1314            }
1315    
1316            /* Child */
1317            if (child == 0)
1318            {
1319                    /* Close read end */
1320                    close(fd[0]);
1321    
1322                    /* Redirect stdout and stderr to pipe */
1323                    dup2(fd[1], 1);
1324                    dup2(fd[1], 2);
1325    
1326                    /* Execute */
1327                    execvp(argv[0], argv);
1328                    perror("Error executing child");
1329                    _exit(128);
1330            }
1331    
1332            /* Parent. Close write end. */
1333            close(fd[1]);
1334            while (n > 0)
1335            {
1336                    n = read(fd[0], output, 255);
1337                    output[n] = '\0';
1338                    str_handle_lines(output, &rest, linehandler, data);
1339            }
1340            xfree(rest);
1341    
1342            return True;
1343    }
1344    
1345    
1346    /* not all clibs got ltoa */
1347    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1348    
1349    char *
1350    l_to_a(long N, int base)
1351    {
1352            static char ret[LTOA_BUFSIZE];
1353    
1354            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1355    
1356            register int divrem;
1357    
1358            if (base < 36 || 2 > base)
1359                    base = 10;
1360    
1361            if (N < 0)
1362            {
1363                    *head++ = '-';
1364                    N = -N;
1365            }
1366    
1367            tail = buf + sizeof(buf);
1368            *--tail = 0;
1369    
1370            do
1371            {
1372                    divrem = N % base;
1373                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1374                    N /= base;
1375            }
1376            while (N);
1377    
1378            strcpy(head, tail);
1379            return ret;
1380    }
1381    
1382    
1383  int  int
1384  load_licence(unsigned char **data)  load_licence(unsigned char **data)
# Line 588  load_licence(unsigned char **data) Line 1391  load_licence(unsigned char **data)
1391          if (home == NULL)          if (home == NULL)
1392                  return -1;                  return -1;
1393    
1394          path = (char*)xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1395          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1396    
1397          fd = open(path, O_RDONLY);          fd = open(path, O_RDONLY);
1398          if (fd == -1)          if (fd == -1)
# Line 598  load_licence(unsigned char **data) Line 1401  load_licence(unsigned char **data)
1401          if (fstat(fd, &st))          if (fstat(fd, &st))
1402                  return -1;                  return -1;
1403    
1404          *data = (uint8*)xmalloc(st.st_size);          *data = (uint8 *) xmalloc(st.st_size);
1405          length = read(fd, *data, st.st_size);          length = read(fd, *data, st.st_size);
1406          close(fd);          close(fd);
1407          xfree(path);          xfree(path);
# Line 615  save_licence(unsigned char *data, int le Line 1418  save_licence(unsigned char *data, int le
1418          if (home == NULL)          if (home == NULL)
1419                  return;                  return;
1420    
1421          path = (char*)xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence."));          path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1422    
1423          sprintf(path, "%s/.rdesktop", home);          sprintf(path, "%s/.rdesktop", home);
1424          if ((mkdir(path, 0700) == -1) && errno != EEXIST)          if ((mkdir(path, 0700) == -1) && errno != EEXIST)
# Line 626  save_licence(unsigned char *data, int le Line 1429  save_licence(unsigned char *data, int le
1429    
1430          /* write licence to licence.hostname.new, then atomically rename to licence.hostname */          /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1431    
1432          sprintf(path, "%s/.rdesktop/licence.%s", home, hostname);          sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1433          tmppath = (char*)xmalloc(strlen(path) + sizeof(".new"));          tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1434          strcpy(tmppath, path);          strcpy(tmppath, path);
1435          strcat(tmppath, ".new");          strcat(tmppath, ".new");
1436    
1437          fd = open(tmppath, O_WRONLY|O_CREAT|O_TRUNC, 0600);          fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1438          if (fd == -1)          if (fd == -1)
1439          {          {
1440                  perror(tmppath);                  perror(tmppath);
# Line 653  save_licence(unsigned char *data, int le Line 1456  save_licence(unsigned char *data, int le
1456          xfree(tmppath);          xfree(tmppath);
1457          xfree(path);          xfree(path);
1458  }  }
1459    
1460    /* Create the bitmap cache directory */
1461    BOOL
1462    rd_pstcache_mkdir(void)
1463    {
1464            char *home;
1465            char bmpcache_dir[256];
1466    
1467            home = getenv("HOME");
1468    
1469            if (home == NULL)
1470                    return False;
1471    
1472            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1473    
1474            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1475            {
1476                    perror(bmpcache_dir);
1477                    return False;
1478            }
1479    
1480            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1481    
1482            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1483            {
1484                    perror(bmpcache_dir);
1485                    return False;
1486            }
1487    
1488            return True;
1489    }
1490    
1491    /* open a file in the .rdesktop directory */
1492    int
1493    rd_open_file(char *filename)
1494    {
1495            char *home;
1496            char fn[256];
1497            int fd;
1498    
1499            home = getenv("HOME");
1500            if (home == NULL)
1501                    return -1;
1502            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1503            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1504            if (fd == -1)
1505                    perror(fn);
1506            return fd;
1507    }
1508    
1509    /* close file */
1510    void
1511    rd_close_file(int fd)
1512    {
1513            close(fd);
1514    }
1515    
1516    /* read from file*/
1517    int
1518    rd_read_file(int fd, void *ptr, int len)
1519    {
1520            return read(fd, ptr, len);
1521    }
1522    
1523    /* write to file */
1524    int
1525    rd_write_file(int fd, void *ptr, int len)
1526    {
1527            return write(fd, ptr, len);
1528    }
1529    
1530    /* move file pointer */
1531    int
1532    rd_lseek_file(int fd, int offset)
1533    {
1534            return lseek(fd, offset, SEEK_SET);
1535    }
1536    
1537    /* do a write lock on a file */
1538    BOOL
1539    rd_lock_file(int fd, int start, int len)
1540    {
1541            struct flock lock;
1542    
1543            lock.l_type = F_WRLCK;
1544            lock.l_whence = SEEK_SET;
1545            lock.l_start = start;
1546            lock.l_len = len;
1547            if (fcntl(fd, F_SETLK, &lock) == -1)
1548                    return False;
1549            return True;
1550    }

Legend:
Removed from v.376  
changed lines
  Added in v.1089

  ViewVC Help
Powered by ViewVC 1.1.26