--- sourceforge.net/trunk/rdesktop/rdesktop.c 2004/04/29 19:40:40 685 +++ sourceforge.net/trunk/rdesktop/rdesktop.c 2005/04/16 11:42:34 886 @@ -1,7 +1,7 @@ /* -*- c-basic-offset: 8 -*- rdesktop: A Remote Desktop Protocol client. Entrypoint and utility functions - Copyright (C) Matthew Chapman 1999-2003 + Copyright (C) Matthew Chapman 1999-2005 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -30,22 +30,28 @@ #include #include "rdesktop.h" +#ifdef HAVE_ICONV +#ifdef HAVE_LOCALE_H +#include +#endif +#ifdef HAVE_LANGINFO_H +#include +#endif +#endif + #ifdef EGD_SOCKET +#include #include /* socket connect */ #include /* sockaddr_un */ #endif -#ifdef WITH_OPENSSL #include -#else -#include "crypto/md5.h" -#endif char g_title[64] = ""; char g_username[64]; -char hostname[16]; +char g_hostname[16]; char keymapname[16]; -int keylayout = 0x409; /* Defaults to US keyboard layout */ +int g_keylayout = 0x409; /* Defaults to US keyboard layout */ int g_width = 800; /* width is special: If 0, the geometry will be fetched from @@ -53,15 +59,24 @@ absolute value specifies the percent of the whole screen. */ int g_height = 600; -int tcp_port_rdp = TCP_PORT_RDP; +int g_xpos = 0; +int g_ypos = 0; +int g_pos = 0; /* 0 position unspecified, + 1 specified, + 2 xpos neg, + 4 ypos neg */ +extern int g_tcp_port_rdp; int g_server_bpp = 8; int g_win_button_size = 0; /* If zero, disable single app mode */ BOOL g_bitmap_compression = True; BOOL g_sendmotion = True; BOOL g_bitmap_cache = True; +BOOL g_bitmap_cache_persist_enable = False; +BOOL g_bitmap_cache_precache = True; BOOL g_encryption = True; BOOL packet_encryption = True; -BOOL g_desktop_save = True; +BOOL g_desktop_save = True; /* desktop save order */ +BOOL g_polygon_ellipse_orders = True; /* polygon / ellipse orders */ BOOL g_fullscreen = False; BOOL g_grab_keyboard = True; BOOL g_hide_decorations = False; @@ -70,6 +85,7 @@ BOOL g_numlock_sync = False; BOOL g_owncolmap = False; BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */ +BOOL g_rdp_compression = False; uint32 g_embed_wnd; uint32 g_rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; @@ -78,6 +94,10 @@ BOOL g_rdpsnd = False; #endif +#ifdef HAVE_ICONV +char g_codepage[16] = ""; +#endif + extern RDPDR_DEVICE g_rdpdr_device[]; extern uint32 g_num_devices; extern char *g_rdpdr_clientname; @@ -94,7 +114,7 @@ usage(char *program) { fprintf(stderr, "rdesktop: A Remote Desktop Protocol client.\n"); - fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2003 Matt Chapman.\n"); + fprintf(stderr, "Version " VERSION ". Copyright (C) 1999-2005 Matt Chapman.\n"); fprintf(stderr, "See http://www.rdesktop.org/ for more information.\n\n"); fprintf(stderr, "Usage: %s [options] server[:port]\n", program); @@ -112,6 +132,9 @@ fprintf(stderr, " -g: desktop geometry (WxH)\n"); fprintf(stderr, " -f: full-screen mode\n"); fprintf(stderr, " -b: force bitmap updates\n"); +#ifdef HAVE_ICONV + fprintf(stderr, " -L: local codepage\n"); +#endif fprintf(stderr, " -B: use BackingStore of X-server (if available)\n"); fprintf(stderr, " -e: disable encryption (French TS)\n"); fprintf(stderr, " -E: disable encryption from client to server\n"); @@ -124,15 +147,16 @@ fprintf(stderr, " -N: enable numlock syncronization\n"); fprintf(stderr, " -X: embed into another window with a given id.\n"); fprintf(stderr, " -a: connection colour depth\n"); - fprintf(stderr, - " -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex number)\n"); + fprintf(stderr, " -z: enable rdp compression\n"); + fprintf(stderr, " -x: RDP5 experience (m[odem 28.8], b[roadband], l[an] or hex nr.)\n"); + fprintf(stderr, " -P: use persistent bitmap caching\n"); fprintf(stderr, " -r: enable specified device redirection (this flag can be repeated)\n"); fprintf(stderr, " '-r comport:COM1=/dev/ttyS0': enable serial redirection of /dev/ttyS0 to COM1\n"); fprintf(stderr, " or COM1=/dev/ttyS0,COM2=/dev/ttyS1\n"); fprintf(stderr, - " '-r disk:A=/mnt/floppy': enable redirection of /mnt/floppy to A:\n"); - fprintf(stderr, " or A=/mnt/floppy,D=/mnt/cdrom'\n"); + " '-r disk:floppy=/mnt/floppy': enable redirection of /mnt/floppy to 'floppy' share\n"); + fprintf(stderr, " or 'floppy=/mnt/floppy,cdrom=/mnt/cdrom'\n"); fprintf(stderr, " '-r clientname=': Set the client name displayed\n"); fprintf(stderr, " for redirected disks\n"); fprintf(stderr, @@ -305,7 +329,7 @@ if (*server == '[' && p != NULL) { if (*(p + 1) == ':' && *(p + 2) != '\0') - tcp_port_rdp = strtol(p + 2, NULL, 10); + g_tcp_port_rdp = strtol(p + 2, NULL, 10); /* remove the port number and brackets from the address */ *p = '\0'; strncpy(server, server + 1, strlen(server)); @@ -317,7 +341,7 @@ p = strchr(server, ':'); if (p != NULL) { - tcp_port_rdp = strtol(p + 1, NULL, 10); + g_tcp_port_rdp = strtol(p + 1, NULL, 10); *p = 0; } } @@ -325,7 +349,7 @@ p = strchr(server, ':'); if (p != NULL) { - tcp_port_rdp = strtol(p + 1, NULL, 10); + g_tcp_port_rdp = strtol(p + 1, NULL, 10); *p = 0; } #endif /* IPv6 */ @@ -364,7 +388,8 @@ #define VNCOPT #endif - while ((c = getopt(argc, argv, VNCOPT "u:d:s:c:p:n:k:g:fbBeEmCDKS:T:NX:a:x:r:045h?")) != -1) + while ((c = getopt(argc, argv, + VNCOPT "u:L:d:s:c:p:n:k:g:fbBeEmzCDKS:T:NX:a:x:Pr:045h?")) != -1) { switch (c) { @@ -387,6 +412,14 @@ username_option = 1; break; + case 'L': +#ifdef HAVE_ICONV + STRNCPY(g_codepage, optarg, sizeof(g_codepage)); +#else + error("iconv support not available\n"); +#endif + break; + case 'd': STRNCPY(domain, optarg, sizeof(domain)); break; @@ -416,7 +449,7 @@ break; case 'n': - STRNCPY(hostname, optarg, sizeof(hostname)); + STRNCPY(g_hostname, optarg, sizeof(g_hostname)); break; case 'k': @@ -439,7 +472,7 @@ } if (*p == 'x') - g_height = strtol(p + 1, NULL, 10); + g_height = strtol(p + 1, &p, 10); if (g_height <= 0) { @@ -448,7 +481,22 @@ } if (*p == '%') + { g_width = -g_width; + p++; + } + + if (*p == '+' || *p == '-') + { + g_pos |= (*p == '-') ? 2 : 1; + g_xpos = strtol(p, &p, 10); + + } + if (*p == '+' || *p == '-') + { + g_pos |= (*p == '-') ? 4 : 1; + g_ypos = strtol(p, NULL, 10); + } break; @@ -512,7 +560,7 @@ break; case 'X': - g_embed_wnd = strtol(optarg, NULL, 10); + g_embed_wnd = strtol(optarg, NULL, 0); break; case 'a': @@ -525,8 +573,13 @@ } break; - case 'x': + case 'z': + DEBUG(("rdp compression enabled\n")); + flags |= RDP_COMPRESSION; + g_rdp_compression = True; + break; + case 'x': if (strncmp("modem", optarg, 1) == 0) { g_rdp5_performanceflags = @@ -547,6 +600,10 @@ } break; + case 'P': + g_bitmap_cache_persist_enable = True; + break; + case 'r': if (strncmp("sound", optarg, 5) == 0) @@ -565,14 +622,14 @@ #ifdef WITH_RDPSND g_rdpsnd = True; #else - warning("Not compiled with sound support"); + warning("Not compiled with sound support\n"); #endif if (strncmp("off", optarg, 3) == 0) #ifdef WITH_RDPSND g_rdpsnd = False; #else - warning("Not compiled with sound support"); + warning("Not compiled with sound support\n"); #endif optarg = p; @@ -583,7 +640,7 @@ #ifdef WITH_RDPSND g_rdpsnd = True; #else - warning("Not compiled with sound support"); + warning("Not compiled with sound support\n"); #endif } } @@ -656,7 +713,21 @@ STRNCPY(g_username, pw->pw_name, sizeof(g_username)); } - if (hostname[0] == 0) +#ifdef HAVE_ICONV + if (g_codepage[0] == 0) + { + if (setlocale(LC_CTYPE, "")) + { + STRNCPY(g_codepage, nl_langinfo(CODESET), sizeof(g_codepage)); + } + else + { + STRNCPY(g_codepage, DEFAULT_CODEPAGE, sizeof(g_codepage)); + } + } +#endif + + if (g_hostname[0] == 0) { if (gethostname(fullhostname, sizeof(fullhostname)) == -1) { @@ -668,7 +739,7 @@ if (p != NULL) *p = 0; - STRNCPY(hostname, fullhostname, sizeof(hostname)); + STRNCPY(g_hostname, fullhostname, sizeof(g_hostname)); } if (prompt_password && read_password(password, sizeof(password))) @@ -714,6 +785,7 @@ DEBUG(("Disconnecting...\n")); rdp_disconnect(); + cache_save_state(); ui_deinit(); if (ext_disc_reason >= 2) @@ -843,7 +915,11 @@ void * xrealloc(void *oldmem, int size) { - void *mem = realloc(oldmem, size); + void *mem; + + if (size < 1) + size = 1; + mem = realloc(oldmem, size); if (mem == NULL) { error("xrealloc %d\n", size); @@ -1056,8 +1132,8 @@ if (home == NULL) return -1; - path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence.")); - sprintf(path, "%s/.rdesktop/licence.%s", home, hostname); + path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence.")); + sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname); fd = open(path, O_RDONLY); if (fd == -1) @@ -1083,7 +1159,7 @@ if (home == NULL) return; - path = (char *) xmalloc(strlen(home) + strlen(hostname) + sizeof("/.rdesktop/licence.")); + path = (char *) xmalloc(strlen(home) + strlen(g_hostname) + sizeof("/.rdesktop/licence.")); sprintf(path, "%s/.rdesktop", home); if ((mkdir(path, 0700) == -1) && errno != EEXIST) @@ -1094,7 +1170,7 @@ /* write licence to licence.hostname.new, then atomically rename to licence.hostname */ - sprintf(path, "%s/.rdesktop/licence.%s", home, hostname); + sprintf(path, "%s/.rdesktop/licence.%s", home, g_hostname); tmppath = (char *) xmalloc(strlen(path) + sizeof(".new")); strcpy(tmppath, path); strcat(tmppath, ".new"); @@ -1121,3 +1197,95 @@ xfree(tmppath); xfree(path); } + +/* Create the bitmap cache directory */ +BOOL +rd_pstcache_mkdir(void) +{ + char *home; + char bmpcache_dir[256]; + + home = getenv("HOME"); + + if (home == NULL) + return False; + + sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop"); + + if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + perror(bmpcache_dir); + return False; + } + + sprintf(bmpcache_dir, "%s/%s", home, ".rdesktop/cache"); + + if ((mkdir(bmpcache_dir, S_IRWXU) == -1) && errno != EEXIST) + { + perror(bmpcache_dir); + return False; + } + + return True; +} + +/* open a file in the .rdesktop directory */ +int +rd_open_file(char *filename) +{ + char *home; + char fn[256]; + int fd; + + home = getenv("HOME"); + if (home == NULL) + return -1; + sprintf(fn, "%s/.rdesktop/%s", home, filename); + fd = open(fn, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); + if (fd == -1) + perror(fn); + return fd; +} + +/* close file */ +void +rd_close_file(int fd) +{ + close(fd); +} + +/* read from file*/ +int +rd_read_file(int fd, void *ptr, int len) +{ + return read(fd, ptr, len); +} + +/* write to file */ +int +rd_write_file(int fd, void *ptr, int len) +{ + return write(fd, ptr, len); +} + +/* move file pointer */ +int +rd_lseek_file(int fd, int offset) +{ + return lseek(fd, offset, SEEK_SET); +} + +/* do a write lock on a file */ +BOOL +rd_lock_file(int fd, int start, int len) +{ + struct flock lock; + + lock.l_type = F_WRLCK; + lock.l_whence = SEEK_SET; + lock.l_start = start; + lock.l_len = len; + if (fcntl(fd, F_SETLK, &lock) == -1) + return False; + return True; +}