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

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

Legend:
Removed from v.81  
changed lines
  Added in v.980

  ViewVC Help
Powered by ViewVC 1.1.26