/[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 25 by matty, Sat Jan 6 03:47:04 2001 UTC revision 1035 by astrand, Fri Dec 30 20:32:06 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-2000     Copyright (C) Matthew Chapman 1999-2005
5      
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.     (at your option) any later version.
10      
11     This program is distributed in the hope that it will be useful,     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.     GNU General Public License for more details.
15      
16     You should have received a copy of the GNU General Public License     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software     along with this program; if not, write to the Free Software
18     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */  */
20    
21  #include <stdlib.h>             /* malloc realloc free */  #include <stdarg.h>             /* va_list va_start va_end */
22  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */  #include <unistd.h>             /* read close getuid getgid getpid getppid gethostname */
23  #include <fcntl.h>              /* open */  #include <fcntl.h>              /* open */
24  #include <pwd.h>                /* getpwuid */  #include <pwd.h>                /* getpwuid */
25    #include <termios.h>            /* tcgetattr tcsetattr */
26  #include <sys/stat.h>           /* stat */  #include <sys/stat.h>           /* stat */
27  #include <sys/time.h>           /* gettimeofday */  #include <sys/time.h>           /* gettimeofday */
28  #include <sys/times.h>          /* times */  #include <sys/times.h>          /* times */
29    #include <ctype.h>              /* toupper */
30    #include <errno.h>
31  #include "rdesktop.h"  #include "rdesktop.h"
32    
33  char username[16];  #ifdef HAVE_LOCALE_H
34  char hostname[16];  #include <locale.h>
35  int width = 800;  #endif
36  int height = 600;  #ifdef HAVE_ICONV
37  int keylayout = 0x409;  #ifdef HAVE_LANGINFO_H
38  BOOL motion = True;  #include <langinfo.h>
39  BOOL orders = True;  #endif
40  BOOL licence = True;  #endif
41    
42    #ifdef EGD_SOCKET
43    #include <sys/types.h>
44    #include <sys/socket.h>         /* socket connect */
45    #include <sys/un.h>             /* sockaddr_un */
46    #endif
47    
48    #include <openssl/md5.h>
49    
50    char g_title[64] = "";
51    char g_username[64];
52    char g_hostname[16];
53    char g_keymapname[PATH_MAX] = "";
54    unsigned int g_keylayout = 0x409;       /* Defaults to US keyboard layout */
55    int g_keyboard_type = 0x4;      /* Defaults to US keyboard layout */
56    int g_keyboard_subtype = 0x0;   /* Defaults to US keyboard layout */
57    int g_keyboard_functionkeys = 0xc;      /* Defaults to US keyboard layout */
58    
59    int g_width = 800;              /* width is special: If 0, the
60                                       geometry will be fetched from
61                                       _NET_WORKAREA. If negative,
62                                       absolute value specifies the
63                                       percent of the whole screen. */
64    int g_height = 600;
65    int g_xpos = 0;
66    int g_ypos = 0;
67    int g_pos = 0;                  /* 0 position unspecified,
68                                       1 specified,
69                                       2 xpos neg,
70                                       4 ypos neg  */
71    extern int g_tcp_port_rdp;
72    int g_server_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          STATUS("Usage: %s [options] server\n", program);          fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n");
127          STATUS("   -u: user name\n");          fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n");
128          STATUS("   -d: domain\n");          fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n");
129          STATUS("   -s: shell\n");  
130          STATUS("   -c: working directory\n");          fprintf(stderr, "Usage: %s [options] server[:port]\n", program);
131          STATUS("   -p: password (autologon)\n");  #ifdef RDP2VNC
132          STATUS("   -n: client hostname\n");          fprintf(stderr, "   -V: vnc port\n");
133          STATUS("   -w: desktop width\n");          fprintf(stderr, "   -Q: defer time (ms)\n");
134          STATUS("   -h: desktop height\n");  #endif
135          STATUS("   -k: keyboard layout (hex)\n");          fprintf(stderr, "   -u: user name\n");
136          STATUS("   -b: force bitmap updates\n");          fprintf(stderr, "   -d: domain\n");
137          STATUS("   -m: do not send motion events\n");          fprintf(stderr, "   -s: shell\n");
138          STATUS("   -l: do not request licence\n\n");          fprintf(stderr, "   -c: working directory\n");
139            fprintf(stderr, "   -p: password (- to prompt)\n");
140            fprintf(stderr, "   -n: client hostname\n");
141            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          struct passwd *pw;          char server[64];
380          char *server;          char fullhostname[64];
         uint32 flags;  
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;
387            uint32 flags, ext_disc_reason = 0;
388            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          STATUS("rdesktop: A Remote Desktop Protocol client.\n");  #endif
         STATUS("Version " VERSION  
                ". Copyright (C) 1999-2000 Matt Chapman.\n");  
         STATUS("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            g_embed_wnd = 0;
408    
409            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, "u:d:s:c:p:n:w:h:k:bml?")) != -1)          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;                                  break;
440    
441                          case 'd':                          case 'L':
442                                  strncpy(domain, optarg, sizeof(domain));  #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 'p':                          case 'd':
450                                  flags |= RDP_LOGON_AUTO;                                  STRNCPY(domain, optarg, sizeof(domain));
                                 strncpy(password, optarg, sizeof(password));  
451                                  break;                                  break;
452    
453                          case 's':                          case 's':
454                                  strncpy(shell, optarg, sizeof(shell));                                  STRNCPY(shell, optarg, sizeof(shell));
455                                  break;                                  break;
456    
457                          case 'c':                          case 'c':
458                                  strncpy(directory, optarg, sizeof(directory));                                  STRNCPY(directory, optarg, sizeof(directory));
459                                    break;
460    
461                            case 'p':
462                                    if ((optarg[0] == '-') && (optarg[1] == 0))
463                                    {
464                                            prompt_password = True;
465                                            break;
466                                    }
467    
468                                    STRNCPY(password, optarg, sizeof(password));
469                                    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 'w':                          case 'k':
482                                  width = strtol(optarg, NULL, 10);                                  STRNCPY(g_keymapname, optarg, sizeof(g_keymapname));
483                                  break;                                  break;
484    
485                          case 'h':                          case 'g':
486                                  height = strtol(optarg, NULL, 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')
501                                            g_height = strtol(p + 1, &p, 10);
502    
503                                    if (g_height <= 0)
504                                    {
505                                            error("invalid geometry\n");
506                                            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 'k':                          case 'f':
530                                  keylayout = strtol(optarg, NULL, 16);                                  g_fullscreen = True;
531                                  break;                                  break;
532    
533                            case 'b':
534                                    g_bitmap_cache = False;
535                                    break;
536    
537                            case 'B':
538                                    g_ownbackstore = False;
539                                    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                                  motion = False;                                  g_sendmotion = False;
549                                  break;                                  break;
550    
551                          case 'b':                          case 'C':
552                                  orders = False;                                  g_owncolmap = True;
553                                  break;                                  break;
554    
555                          case 'l':                          case 'D':
556                                  licence = False;                                  g_hide_decorations = True;
557                                  break;                                  break;
558    
559                            case 'K':
560                                    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 (str_startswith(optarg, "m"))        /* modem */
609                                    {
610                                            g_rdp5_performanceflags =
611                                                    RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG |
612                                                    RDP5_NO_MENUANIMATIONS | RDP5_NO_THEMING;
613                                    }
614                                    else if (str_startswith(optarg, "b"))   /* broadband */
615                                    {
616                                            g_rdp5_performanceflags = RDP5_NO_WALLPAPER;
617                                    }
618                                    else if (str_startswith(optarg, "l"))   /* lan */
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 (str_startswith(optarg, "sound"))
635                                    {
636                                            optarg += 5;
637    
638                                            if (*optarg == ':')
639                                            {
640                                                    *optarg++;
641                                                    while ((p = next_arg(optarg, ',')))
642                                                    {
643                                                            if (str_startswith(optarg, "remote"))
644                                                                    flags |= RDP_LOGON_LEAVE_AUDIO;
645    
646                                                            if (str_startswith(optarg, "local"))
647    #ifdef WITH_RDPSND
648                                                                    g_rdpsnd = True;
649    #else
650                                                                    warning("Not compiled with sound support\n");
651    #endif
652    
653                                                            if (str_startswith(optarg, "off"))
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 (str_startswith(optarg, "disk"))
673                                    {
674                                            /* -r disk:h:=/mnt/floppy */
675                                            disk_enum_devices(&g_num_devices, optarg + 4);
676                                    }
677                                    else if (str_startswith(optarg, "comport"))
678                                    {
679                                            serial_enum_devices(&g_num_devices, optarg + 7);
680                                    }
681                                    else if (str_startswith(optarg, "lptport"))
682                                    {
683                                            parallel_enum_devices(&g_num_devices, optarg + 7);
684                                    }
685                                    else if (str_startswith(optarg, "printer"))
686                                    {
687                                            printer_enum_devices(&g_num_devices, optarg + 7);
688                                    }
689                                    else if (str_startswith(optarg, "clientname"))
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;
711    
712                            case 'h':
713                          case '?':                          case '?':
714                          default:                          default:
715                                  usage(argv[0]);                                  usage(argv[0]);
# Line 137  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))
733                  {                  {
734                          STATUS("Could not determine user name.\n");                          error("could not determine username, use -u\n");
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    #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 (hostname[0] == 0)          if (g_hostname[0] == 0)
756          {          {
757                  if (gethostname(hostname, sizeof(hostname)) == -1)                  if (gethostname(fullhostname, sizeof(fullhostname)) == -1)
758                  {                  {
759                          STATUS("Could not determine host name.\n");                          error("could not determine local hostname, use -n\n");
760                          return 1;                          return 1;
761                  }                  }
762    
763                    p = strchr(fullhostname, '.');
764                    if (p != NULL)
765                            *p = 0;
766    
767                    STRNCPY(g_hostname, fullhostname, sizeof(g_hostname));
768          }          }
769    
770          if (!rdp_connect(server, flags, domain, password, shell, directory))          if (g_keymapname[0] == 0)
771                  return 1;          {
772                    if (locale && xkeymap_from_locale(locale))
773                    {
774                            fprintf(stderr, "Autoselected keyboard map %s\n", g_keymapname);
775                    }
776                    else
777                    {
778                            STRNCPY(g_keymapname, "en-us", sizeof(g_keymapname));
779                    }
780            }
781            if (locale)
782                    xfree(locale);
783    
         STATUS("Connection successful.\n");  
784    
785          strcpy(title, "rdesktop - ");          if (prompt_password && read_password(password, sizeof(password)))
786          strncat(title, server, sizeof(title));                  flags |= RDP_LOGON_AUTO;
787    
788          if (ui_create_window(title))          if (g_title[0] == 0)
789          {          {
790                  rdp_main_loop();                  strcpy(g_title, "rdesktop - ");
791                  ui_destroy_window();                  strncat(g_title, server, sizeof(g_title) - sizeof("rdesktop - "));
792          }          }
793    
794          rdp_disconnect();  #ifdef RDP2VNC
795            rdp2vnc_connect(server, flags, domain, password, shell, directory);
796          return 0;          return 0;
797    #else
798    
799            if (!ui_init())
800                    return 1;
801    
802    #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    
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                    /* clean disconnect */
870                    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    #endif
888    
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          /* If we have a kernel random device, use it. */  
939          if ((fd = open("/dev/urandom", O_RDONLY)) != -1)          /* If we have a kernel random device, try that first */
940            if (((fd = open("/dev/urandom", O_RDONLY)) != -1)
941                || ((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 210  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 219  xmalloc(int size) Line 978  xmalloc(int size)
978          void *mem = malloc(size);          void *mem = malloc(size);
979          if (mem == NULL)          if (mem == NULL)
980          {          {
981                  ERROR("xmalloc %d\n", size);                  error("xmalloc %d\n", size);
982                    exit(1);
983            }
984            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);                  exit(1);
996          }          }
997          return mem;          return mem;
# Line 229  xmalloc(int size) Line 1001  xmalloc(int size)
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);
1012                  exit(1);                  exit(1);
1013          }          }
1014          return mem;          return mem;
# Line 245  xfree(void *mem) Line 1021  xfree(void *mem)
1021          free(mem);          free(mem);
1022  }  }
1023    
1024  /* Produce a hex dump */  /* report an error */
1025    void
1026    error(char *format, ...)
1027    {
1028            va_list ap;
1029    
1030            fprintf(stderr, "ERROR: ");
1031    
1032            va_start(ap, format);
1033            vfprintf(stderr, format, ap);
1034            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 */
1051    void
1052    unimpl(char *format, ...)
1053    {
1054            va_list ap;
1055    
1056            fprintf(stderr, "NOT IMPLEMENTED: ");
1057    
1058            va_start(ap, format);
1059            vfprintf(stderr, format, ap);
1060            va_end(ap);
1061    }
1062    
1063    /* produce a hex dump */
1064  void  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          {          {
1072                  STATUS("%04x ", offset);                  printf("%04x ", offset);
1073                  thisline = len - offset;                  thisline = len - offset;
1074                  if (thisline > 16)                  if (thisline > 16)
1075                          thisline = 16;                          thisline = 16;
1076    
1077                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1078                          STATUS("%02x ", line[i]) for (; i < 16; i++)                          printf("%02x ", line[i]);
1079                                  STATUS("   ");  
1080                    for (; i < 16; i++)
1081                            printf("   ");
1082    
1083                  for (i = 0; i < thisline; i++)                  for (i = 0; i < thisline; i++)
1084                          STATUS("%c",                          printf("%c", (line[i] >= 0x20 && line[i] < 0x7f) ? line[i] : '.');
                                (line[i] >= 0x20  
                                 && line[i] < 0x7f) ? line[i] : '.');  
1085    
1086                  STATUS("\n");                  printf("\n");
1087                  offset += thisline;                  offset += thisline;
1088                  line += thisline;                  line += thisline;
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    BOOL
1174    str_startswith(const char *s, const char *prefix)
1175    {
1176            return (strncmp(s, prefix, strlen(prefix)) == 0);
1177    }
1178    
1179    
1180    /* not all clibs got ltoa */
1181    #define LTOA_BUFSIZE (sizeof(long) * 8 + 1)
1182    
1183    char *
1184    l_to_a(long N, int base)
1185    {
1186            static char ret[LTOA_BUFSIZE];
1187    
1188            char *head = ret, buf[LTOA_BUFSIZE], *tail = buf + sizeof(buf);
1189    
1190            register int divrem;
1191    
1192            if (base < 36 || 2 > base)
1193                    base = 10;
1194    
1195            if (N < 0)
1196            {
1197                    *head++ = '-';
1198                    N = -N;
1199            }
1200    
1201            tail = buf + sizeof(buf);
1202            *--tail = 0;
1203    
1204            do
1205            {
1206                    divrem = N % base;
1207                    *--tail = (divrem <= 9) ? divrem + '0' : divrem + 'a' - 10;
1208                    N /= base;
1209            }
1210            while (N);
1211    
1212            strcpy(head, tail);
1213            return ret;
1214    }
1215    
1216    
1217    int
1218    load_licence(unsigned char **data)
1219    {
1220            char *home, *path;
1221            struct stat st;
1222            int fd, length;
1223    
1224            home = getenv("HOME");
1225            if (home == NULL)
1226                    return -1;
1227    
1228            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1229            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1230    
1231            fd = open(path, O_RDONLY);
1232            if (fd == -1)
1233                    return -1;
1234    
1235            if (fstat(fd, &st))
1236                    return -1;
1237    
1238            *data = (uint8 *) xmalloc(st.st_size);
1239            length = read(fd, *data, st.st_size);
1240            close(fd);
1241            xfree(path);
1242            return length;
1243    }
1244    
1245    void
1246    save_licence(unsigned char *data, int length)
1247    {
1248            char *home, *path, *tmppath;
1249            int fd;
1250    
1251            home = getenv("HOME");
1252            if (home == NULL)
1253                    return;
1254    
1255            path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence."));
1256    
1257            sprintf(path, "%s/.rdesktop", home);
1258            if ((mkdir(path, 0700) == -1) && errno != EEXIST)
1259            {
1260                    perror(path);
1261                    return;
1262            }
1263    
1264            /* write licence to licence.hostname.new, then atomically rename to licence.hostname */
1265    
1266            sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname);
1267            tmppath = (char *) xmalloc(strlen(path) + sizeof(".new"));
1268            strcpy(tmppath, path);
1269            strcat(tmppath, ".new");
1270    
1271            fd = open(tmppath, O_WRONLY | O_CREAT | O_TRUNC, 0600);
1272            if (fd == -1)
1273            {
1274                    perror(tmppath);
1275                    return;
1276            }
1277    
1278            if (write(fd, data, length) != length)
1279            {
1280                    perror(tmppath);
1281                    unlink(tmppath);
1282            }
1283            else if (rename(tmppath, path) == -1)
1284            {
1285                    perror(path);
1286                    unlink(tmppath);
1287            }
1288    
1289            close(fd);
1290            xfree(tmppath);
1291            xfree(path);
1292    }
1293    
1294    /* Create the bitmap cache directory */
1295    BOOL
1296    rd_pstcache_mkdir(void)
1297    {
1298            char *home;
1299            char bmpcache_dir[256];
1300    
1301            home = getenv("HOME");
1302    
1303            if (home == NULL)
1304                    return False;
1305    
1306            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop");
1307    
1308            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1309            {
1310                    perror(bmpcache_dir);
1311                    return False;
1312            }
1313    
1314            sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache");
1315    
1316            if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST)
1317            {
1318                    perror(bmpcache_dir);
1319                    return False;
1320            }
1321    
1322            return True;
1323    }
1324    
1325    /* open a file in the .rdesktop directory */
1326    int
1327    rd_open_file(char *filename)
1328    {
1329            char *home;
1330            char fn[256];
1331            int fd;
1332    
1333            home = getenv("HOME");
1334            if (home == NULL)
1335                    return -1;
1336            sprintf(fn, "%s/.rdesktop/%s", home, filename);
1337            fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
1338            if (fd == -1)
1339                    perror(fn);
1340            return fd;
1341    }
1342    
1343    /* close file */
1344    void
1345    rd_close_file(int fd)
1346    {
1347            close(fd);
1348    }
1349    
1350    /* read from file*/
1351    int
1352    rd_read_file(int fd, void *ptr, int len)
1353    {
1354            return read(fd, ptr, len);
1355    }
1356    
1357    /* write to file */
1358    int
1359    rd_write_file(int fd, void *ptr, int len)
1360    {
1361            return write(fd, ptr, len);
1362    }
1363    
1364    /* move file pointer */
1365    int
1366    rd_lseek_file(int fd, int offset)
1367    {
1368            return lseek(fd, offset, SEEK_SET);
1369    }
1370    
1371    /* do a write lock on a file */
1372    BOOL
1373    rd_lock_file(int fd, int start, int len)
1374    {
1375            struct flock lock;
1376    
1377            lock.l_type = F_WRLCK;
1378            lock.l_whence = SEEK_SET;
1379            lock.l_start = start;
1380            lock.l_len = len;
1381            if (fcntl(fd, F_SETLK, &lock) == -1)
1382                    return False;
1383            return True;
1384    }

Legend:
Removed from v.25  
changed lines
  Added in v.1035

  ViewVC Help
Powered by ViewVC 1.1.26