Patch: Document and clean up return values

Peter Åstrand <[email protected]>
Newsgroups gmane.network.rdesktop.devel
Message-ID <[email protected]>
Hi. Below is a patch that cleans up and documents the rdesktop return 
values. It is trying to solve a number of problem with the current 
implementation:

* The current return values have been selected pretty much without any 
thought. Basically, the value 1 is used for all different kinds of errors, 
except for a corner case where the server doesn't send a 
RDP_PDU_DEACTIVATE in combination with a few special "reasons", where the 
value 2 is used instead.

* rdesktop will currently also return with 2 if the user is closing the 
rdesktop window, which is somewhat strange.

* The main principle of my patch is to utilize more of the available 256 
return codes. We are currently only using 3 values out of 256. This is 
bad; rdesktop should expose more information to the caller about error 
conditions if it can.

Besides using the standardized exit codes for generic errors such as 
EX_USAGE for command line usage errors, I've also exposed the "extended 
disconnect reasons" from RDP. This allows for, for example, to be able to 
distinguish between a logoff and a disconnect.

The patch has been tested against:

Windows XP
Windows Server 2003
Windows Vista
Windows 7

Comments?

Best regards, 
---
Peter Åstrand		ThinLinc Chief Developer
Cendio AB		http://www.cendio.com
Wallenbergs gata 4
583 30 Linköping	Phone: +46-13-21 46 00

------------------------------------------------------------------------------
Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day 
trial. Simplify your report design, integration and deployment - and focus on 
what you do best, core application coding. Discover what's new with 
Crystal Reports now.  http://p.sf.net/sfu/bobj-july

_______________________________________________
rdesktop-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/rdesktop-devel
retvalues1.patch (text/plain, 13.6 KB)
Index: configure.ac
===================================================================
--- configure.ac	(revision 1509)
+++ configure.ac	(arbetskopia)
@@ -36,6 +36,7 @@
 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, :)
 
Index: doc/rdesktop.1
===================================================================
--- doc/rdesktop.1	(revision 1509)
+++ doc/rdesktop.1	(arbetskopia)
@@ -220,6 +220,60 @@
 .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 "\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
Index: rdesktop.c
===================================================================
--- rdesktop.c	(revision 1509)
+++ rdesktop.c	(arbetskopia)
@@ -91,6 +91,7 @@
 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 @@
 	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 @@
 			{
 				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 @@
 				if (g_width <= 0)
 				{
 					error("invalid geometry\n");
-					return 1;
+					return EX_USAGE;
 				}
 
 				if (*p == 'x')
@@ -544,7 +574,7 @@
 				if (g_height <= 0)
 				{
 					error("invalid geometry\n");
-					return 1;
+					return EX_USAGE;
 				}
 
 				if (*p == '%')
@@ -613,7 +643,7 @@
 				if (*p)
 				{
 					error("invalid button size\n");
-					return 1;
+					return EX_USAGE;
 				}
 
 				break;
@@ -638,7 +668,7 @@
 				    && g_server_depth != 32)
 				{
 					error("Invalid server colour depth.\n");
-					return 1;
+					return EX_USAGE;
 				}
 				break;
 
@@ -789,14 +819,14 @@
 			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 @@
 		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 @@
 		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 @@
 		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 @@
 
 #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 @@
 		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 @@
 	cache_save_state();
 	ui_deinit();
 
-	if (ext_disc_reason >= 2)
-		print_disconnect_reason(ext_disc_reason);
+	if (g_user_quit)
+		return EX_OK;
 
-	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 @@
 	if (mem == NULL)
 	{
 		error("xmalloc %d\n", size);
-		exit(1);
+		exit(EX_UNAVAILABLE);
 	}
 	return mem;
 }
@@ -1120,7 +1132,7 @@
 	if (ptr == NULL)
 	{
 		error("unexpected null pointer. Out of memory?\n");
-		exit(1);
+		exit(EX_UNAVAILABLE);
 	}
 }
 
@@ -1132,7 +1144,7 @@
 	if (mem == NULL)
 	{
 		perror("strdup");
-		exit(1);
+		exit(EX_UNAVAILABLE);
 	}
 	return mem;
 }
@@ -1149,7 +1161,7 @@
 	if (mem == NULL)
 	{
 		error("xrealloc %ld\n", size);
-		exit(1);
+		exit(EX_UNAVAILABLE);
 	}
 	return mem;
 }
Index: rdesktop.h
===================================================================
--- rdesktop.h	(revision 1509)
+++ rdesktop.h	(arbetskopia)
@@ -38,9 +38,84 @@
 #endif
 #endif
 #include <limits.h>		/* PATH_MAX */
+#ifdef HAVE_SYSEXITS_H
+#include <sysexits.h>
+#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
+#define EXRD_UNKNOWN 63
+
 #ifdef WITH_DEBUG
 #define DEBUG(args)	printf args;
 #else
Index: tcp.c
===================================================================
--- tcp.c	(revision 1509)
+++ tcp.c	(arbetskopia)
@@ -56,6 +56,7 @@
 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 @@
 	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)
Index: constants.h
===================================================================
--- constants.h	(revision 1509)
+++ constants.h	(arbetskopia)
@@ -408,6 +408,7 @@
 #define exDiscReasonOutOfMemory				0x0006
 #define exDiscReasonServerDeniedConnection		0x0007
 #define exDiscReasonServerDeniedConnectionFips		0x0008
+#define exDiscReasonWindows7Disconnect                  0x000b	/* unofficial */
 #define exDiscReasonLicenseInternal			0x0100
 #define exDiscReasonLicenseNoLicenseServer		0x0101
 #define exDiscReasonLicenseNoLicense			0x0102
Index: disk.c
===================================================================
--- disk.c	(revision 1509)
+++ disk.c	(arbetskopia)
@@ -480,7 +480,7 @@
 	{
 		error("Maximum number of open files (%s) reached. Increase MAX_OPEN_FILES!\n",
 		      handle);
-		exit(1);
+		exit(EX_SOFTWARE);
 	}
 
 	if (dirp)
Index: cache.c
===================================================================
--- cache.c	(revision 1509)
+++ cache.c	(arbetskopia)
@@ -95,7 +95,7 @@
 	{
 		error("Oops. %d in bitmap cache linked list, %d in ui cache...\n", c,
 		      g_bmpcache_count[id]);
-		exit(1);
+		exit(EX_SOFTWARE);
 	}
 }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.