diff --git a/cache.c b/cache.c index 45ed891..e3c9d8f 100644 --- a/cache.c +++ b/cache.c @@ -95,7 +95,7 @@ cache_rebuild_bmpcache_linked_list(uint8 id, sint16 * idx, int count) { error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c, g_bmpcache_count[id]); - exit(1); + exit(EX_SOFTWARE); } } diff --git a/configure.ac b/configure.ac index 006f1b1..d59bef1 100644 --- a/configure.ac +++ b/configure.ac @@ -36,6 +36,7 @@ AC_CHECK_HEADER(sys/filio.h, AC_DEFINE(HAVE_SYS_FILIO_H)) AC_CHECK_HEADER(sys/strtio.h, AC_DEFINE(HAVE_SYS_STRTIO_H)) AC_CHECK_HEADER(locale.h, AC_DEFINE(HAVE_LOCALE_H)) AC_CHECK_HEADER(langinfo.h, AC_DEFINE(HAVE_LANGINFO_H)) +AC_CHECK_HEADER(sysexits.h, AC_DEFINE(HAVE_SYSEXITS_H)) AC_CHECK_TOOL(STRIP, strip, :) diff --git a/constants.h b/constants.h index 902c4a5..0185504 100644 --- a/constants.h +++ b/constants.h @@ -408,6 +408,7 @@ enum RDP_INPUT_DEVICE #define exDiscReasonOutOfMemory 0x0006 #define exDiscReasonServerDeniedConnection 0x0007 #define exDiscReasonServerDeniedConnectionFips 0x0008 +#define exDiscReasonWindows7Disconnect 0x000b /* unofficial */ #define exDiscReasonLicenseInternal 0x0100 #define exDiscReasonLicenseNoLicenseServer 0x0101 #define exDiscReasonLicenseNoLicense 0x0102 diff --git a/disk.c b/disk.c index bf299fa..96b135f 100644 --- a/disk.c +++ b/disk.c @@ -480,7 +480,7 @@ disk_create(uint32 device_id, uint32 accessmask, uint32 sharemode, uint32 create { error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n", handle); - exit(1); + exit(EX_SOFTWARE); } if (dirp) diff --git a/doc/rdesktop.1 b/doc/rdesktop.1 index 68f2139..9850b2e 100644 --- a/doc/rdesktop.1 +++ b/doc/rdesktop.1 @@ -220,6 +220,64 @@ Use RDP version 4. .BR "-5" Use RDP version 5 (default). .PP +.SH "EXIT VALUES" +.PP +.IP "\fB0\fP" +RDP session terminated normally +.IP "\fB1\fP" +Server initiated disconnect +.IP "\fB2\fP" +Server initiated logoff +.IP "\fB3\fP" +Server idle timeout reached +.IP "\fB4\fP" +Server logon timeout reached +.IP "\fB5\fP" +The session was replaced +.IP "\fB6\fP" +The server is out of memory +.IP "\fB7\fP" +The server denied the connection +.IP "\fB8\fP" +The server denied the connection for security reason +.IP "\fB16\fP" +Internal licensing error +.IP "\fB17\fP" +No license server available +.IP "\fB18\fP" +No valid license available +.IP "\fB19\fP" +Invalid licensing message +.IP "\fB20\fP" +Hardware id doesn't match software license +.IP "\fB21\fP" +Client license error +.IP "\fB22\fP" +Network error during licensing protocol +.IP "\fB23\fP" +Licensing protocol was not completed +.IP "\fB24\fP" +Incorrect client license enryption +.IP "\fB25\fP" +Can't upgrade license +.IP "\fB26\fP" +The server is not licensed to accept remote connections +.IP "\fB62\fP" +The local client window was closed +.IP "\fB63\fP" +Some other, unknown error occured +.IP "\fB64\fP" +Command line usage error +.IP "\fB69\fP" +A service or resource (such as memory) is unavailable +.IP "\fB70\fP" +An internal software error has been detected +.IP "\fB71\fP" +Operating system error +.IP "\fB76\fP" +Protocol error or unable to connect to remote host. + +.PP .SH LINKS Main website of rdesktop .br diff --git a/rdesktop.c b/rdesktop.c index e8c632c..f1652ce 100644 --- a/rdesktop.c +++ b/rdesktop.c @@ -91,6 +91,7 @@ RD_BOOL g_lspci_enabled = False; RD_BOOL g_owncolmap = False; RD_BOOL g_ownbackstore = True; /* We can't rely on external BackingStore */ RD_BOOL g_seamless_rdp = False; +RD_BOOL g_user_quit = False; uint32 g_embed_wnd; uint32 g_rdp5_performanceflags = RDP5_NO_WALLPAPER | RDP5_NO_FULLWINDOWDRAG | RDP5_NO_MENUANIMATIONS; @@ -213,91 +214,116 @@ usage(char *program) fprintf(stderr, " -5: use RDP version 5 (default)\n"); } -static void -print_disconnect_reason(uint16 reason) +static int +handle_disconnect_reason(RD_BOOL deactivated, uint16 reason) { char *text; + int retval; switch (reason) { case exDiscReasonNoInfo: text = "No information available"; + if (deactivated) + retval = EX_OK; + else + retval = EXRD_UNKNOWN; break; case exDiscReasonAPIInitiatedDisconnect: + case exDiscReasonWindows7Disconnect: text = "Server initiated disconnect"; + retval = EXRD_API_DISCONNECT; break; case exDiscReasonAPIInitiatedLogoff: text = "Server initiated logoff"; + retval = EXRD_API_LOGOFF; break; case exDiscReasonServerIdleTimeout: text = "Server idle timeout reached"; + retval = EXRD_IDLE_TIMEOUT; break; case exDiscReasonServerLogonTimeout: text = "Server logon timeout reached"; + retval = EXRD_LOGON_TIMEOUT; break; case exDiscReasonReplacedByOtherConnection: text = "The session was replaced"; + retval = EXRD_REPLACED; break; case exDiscReasonOutOfMemory: text = "The server is out of memory"; + retval = EXRD_OUT_OF_MEM; break; case exDiscReasonServerDeniedConnection: text = "The server denied the connection"; + retval = EXRD_DENIED; break; case exDiscReasonServerDeniedConnectionFips: text = "The server denied the connection for security reason"; + retval = EXRD_DENIED_FIPS; break; case exDiscReasonLicenseInternal: text = "Internal licensing error"; + retval = EXRD_LIC_INTERNAL; break; case exDiscReasonLicenseNoLicenseServer: text = "No license server available"; + retval = EXRD_LIC_NOSERVER; break; case exDiscReasonLicenseNoLicense: text = "No valid license available"; + retval = EXRD_LIC_NOLICENSE; break; case exDiscReasonLicenseErrClientMsg: text = "Invalid licensing message"; + retval = EXRD_LIC_MSG; break; case exDiscReasonLicenseHwidDoesntMatchLicense: text = "Hardware id doesn't match software license"; + retval = EXRD_LIC_HWID; break; case exDiscReasonLicenseErrClientLicense: text = "Client license error"; + retval = EXRD_LIC_CLIENT; break; case exDiscReasonLicenseCantFinishProtocol: text = "Network error during licensing protocol"; + retval = EXRD_LIC_NET; break; case exDiscReasonLicenseClientEndedProtocol: text = "Licensing protocol was not completed"; + retval = EXRD_LIC_PROTO; break; case exDiscReasonLicenseErrClientEncryption: text = "Incorrect client license enryption"; + retval = EXRD_LIC_ENC; break; case exDiscReasonLicenseCantUpgradeLicense: text = "Can't upgrade license"; + retval = EXRD_LIC_UPGRADE; break; case exDiscReasonLicenseNoRemoteConnections: text = "The server is not licensed to accept remote connections"; + retval = EXRD_LIC_NOREMOTE; break; default: @@ -309,8 +335,12 @@ print_disconnect_reason(uint16 reason) { text = "Unknown reason"; } + retval = EXRD_UNKNOWN; } - fprintf(stderr, "disconnect: %s.\n", text); + if (reason != exDiscReasonNoInfo) + fprintf(stderr, "disconnect: %s.\n", text); + + return retval; } static void @@ -535,7 +565,7 @@ main(int argc, char *argv[]) if (g_width <= 0) { error("invalid geometry\n"); - return 1; + return EX_USAGE; } if (*p == 'x') @@ -544,7 +574,7 @@ main(int argc, char *argv[]) if (g_height <= 0) { error("invalid geometry\n"); - return 1; + return EX_USAGE; } if (*p == '%') @@ -613,7 +643,7 @@ main(int argc, char *argv[]) if (*p) { error("invalid button size\n"); - return 1; + return EX_USAGE; } break; @@ -638,7 +668,7 @@ main(int argc, char *argv[]) && g_server_depth != 32) { error("Invalid server colour depth.\n"); - return 1; + return EX_USAGE; } break; @@ -789,14 +819,14 @@ main(int argc, char *argv[]) case '?': default: usage(argv[0]); - return 1; + return EX_USAGE; } } if (argc - optind != 1) { usage(argv[0]); - return 1; + return EX_USAGE; } STRNCPY(server, argv[optind], sizeof(server)); @@ -807,33 +837,33 @@ main(int argc, char *argv[]) if (g_win_button_size) { error("You cannot use -S and -A at the same time\n"); - return 1; + return EX_USAGE; } g_rdp5_performanceflags &= ~RDP5_NO_FULLWINDOWDRAG; if (geometry_option) { error("You cannot use -g and -A at the same time\n"); - return 1; + return EX_USAGE; } if (g_fullscreen) { error("You cannot use -f and -A at the same time\n"); - return 1; + return EX_USAGE; } if (g_hide_decorations) { error("You cannot use -D and -A at the same time\n"); - return 1; + return EX_USAGE; } if (g_embed_wnd) { error("You cannot use -X and -A at the same time\n"); - return 1; + return EX_USAGE; } if (!g_use_rdp5) { error("You cannot use -4 and -A at the same time\n"); - return 1; + return EX_USAGE; } g_width = -100; g_grab_keyboard = False; @@ -845,7 +875,7 @@ main(int argc, char *argv[]) if ((pw == NULL) || (pw->pw_name == NULL)) { error("could not determine username, use -u\n"); - return 1; + return EX_OSERR; } /* +1 for trailing \0 */ int pwlen = strlen(pw->pw_name) + 1; @@ -872,7 +902,7 @@ main(int argc, char *argv[]) if (gethostname(fullhostname, sizeof(fullhostname)) == -1) { error("could not determine local hostname, use -n\n"); - return 1; + return EX_OSERR; } p = strchr(fullhostname, '.'); @@ -908,11 +938,11 @@ main(int argc, char *argv[]) #ifdef RDP2VNC rdp2vnc_connect(server, flags, domain, password, shell, directory); - return 0; + return EX_OK; #else if (!ui_init()) - return 1; + return EX_OSERR; #ifdef WITH_RDPSND if (g_rdpsnd) @@ -934,11 +964,11 @@ main(int argc, char *argv[]) if (run_count == 0) { if (!rdp_connect(server, flags, domain, password, shell, directory)) - return 1; + return EX_PROTOCOL; } else if (!rdp_reconnect (server, flags, domain, password, shell, directory, g_redirect_cookie)) - return 1; + return EX_PROTOCOL; /* By setting encryption to False here, we have an encrypted login packet but unencrypted transfer of other packets */ @@ -987,28 +1017,10 @@ main(int argc, char *argv[]) cache_save_state(); ui_deinit(); - if (ext_disc_reason >= 2) - print_disconnect_reason(ext_disc_reason); + if (g_user_quit) + return EXRD_WINDOW_CLOSED; - if (deactivated) - { - /* clean disconnect */ - return 0; - } - else - { - if (ext_disc_reason == exDiscReasonAPIInitiatedDisconnect - || ext_disc_reason == exDiscReasonAPIInitiatedLogoff) - { - /* not so clean disconnect, but nothing to worry about */ - return 0; - } - else - { - /* return error */ - return 2; - } - } + return handle_disconnect_reason(deactivated, ext_disc_reason); #endif if (g_redirect_username) @@ -1108,7 +1120,7 @@ xmalloc(int size) if (mem == NULL) { error("xmalloc %d\n", size); - exit(1); + exit(EX_UNAVAILABLE); } return mem; } @@ -1120,7 +1132,7 @@ exit_if_null(void *ptr) if (ptr == NULL) { error("unexpected null pointer. Out of memory?\n"); - exit(1); + exit(EX_UNAVAILABLE); } } @@ -1132,7 +1144,7 @@ xstrdup(const char *s) if (mem == NULL) { perror("strdup"); - exit(1); + exit(EX_UNAVAILABLE); } return mem; } @@ -1149,7 +1161,7 @@ xrealloc(void *oldmem, size_t size) if (mem == NULL) { error("xrealloc %ld\n", size); - exit(1); + exit(EX_UNAVAILABLE); } return mem; } diff --git a/rdesktop.h b/rdesktop.h index 31ed64e..4a86d02 100644 --- a/rdesktop.h +++ b/rdesktop.h @@ -38,9 +38,87 @@ #endif #endif #include /* PATH_MAX */ +#ifdef HAVE_SYSEXITS_H +#include +#endif #define VERSION "1.6.0" +/* standard exit codes */ +#ifndef EX_OK +#define EX_OK 0 +#endif +#ifndef EX_USAGE +#define EX_USAGE 64 +#endif +#ifndef EX_DATAERR +#define EX_DATAERR 65 +#endif +#ifndef EX_NOINPUT +#define EX_NOINPUT 66 +#endif +#ifndef EX_NOUSER +#define EX_NOUSER 67 +#endif +#ifndef EX_NOHOST +#define EX_NOHOST 68 +#endif +#ifndef EX_UNAVAILABLE +#define EX_UNAVAILABLE 69 +#endif +#ifndef EX_SOFTWARE +#define EX_SOFTWARE 70 +#endif +#ifndef EX_OSERR +#define EX_OSERR 71 +#endif +#ifndef EX_OSFILE +#define EX_OSFILE 72 +#endif +#ifndef EX_CANTCREAT +#define EX_CANTCREAT 73 +#endif +#ifndef EX_IOERR +#define EX_IOERR 74 +#endif +#ifndef EX_TEMPFAIL +#define EX_TEMPFAIL 75 +#endif +#ifndef EX_PROTOCOL +#define EX_PROTOCOL 76 +#endif +#ifndef EX_NOPERM +#define EX_NOPERM 77 +#endif +#ifndef EX_CONFIG +#define EX_CONFIG 78 +#endif + +/* rdesktop specific exit codes, lined up with disconnect PDU reasons */ +#define EXRD_API_DISCONNECT 1 +#define EXRD_API_LOGOFF 2 +#define EXRD_IDLE_TIMEOUT 3 +#define EXRD_LOGON_TIMEOUT 4 +#define EXRD_REPLACED 5 +#define EXRD_OUT_OF_MEM 6 +#define EXRD_DENIED 7 +#define EXRD_DENIED_FIPS 8 +#define EXRD_LIC_INTERNAL 16 +#define EXRD_LIC_NOSERVER 17 +#define EXRD_LIC_NOLICENSE 18 +#define EXRD_LIC_MSG 19 +#define EXRD_LIC_HWID 20 +#define EXRD_LIC_CLIENT 21 +#define EXRD_LIC_NET 22 +#define EXRD_LIC_PROTO 23 +#define EXRD_LIC_ENC 24 +#define EXRD_LIC_UPGRADE 25 +#define EXRD_LIC_NOREMOTE 26 + +/* other exit codes */ +#define EXRD_WINDOW_CLOSED 62 +#define EXRD_UNKNOWN 63 + #ifdef WITH_DEBUG #define DEBUG(args) printf args; #else diff --git a/tcp.c b/tcp.c index 1971ad7..5e1adab 100644 --- a/tcp.c +++ b/tcp.c @@ -56,6 +56,7 @@ static int g_sock; static struct stream g_in; static struct stream g_out[STREAM_COUNT]; int g_tcp_port_rdp = TCP_PORT_RDP; +extern RD_BOOL g_user_quit; /* wait till socket is ready to write or timeout */ static RD_BOOL @@ -173,8 +174,11 @@ tcp_recv(STREAM s, uint32 length) while (length > 0) { if (!ui_select(g_sock)) + { /* User quit */ + g_user_quit = True; return NULL; + } rcvd = recv(g_sock, s->end, length, 0); if (rcvd < 0)