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

Diff of /sourceforge.net/trunk/rdesktop/rdesktop.c

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

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

Legend:
Removed from v.96  
changed lines
  Added in v.977

  ViewVC Help
Powered by ViewVC 1.1.26