Index: sash-3.7/cmds.c
===================================================================
--- sash-3.7.orig/cmds.c	2010-04-04 11:45:33.864951850 +0200
+++ sash-3.7/cmds.c	2010-04-04 12:29:17.184954241 +0200
@@ -26,7 +26,7 @@
 #endif
 
 
-void
+int
 do_echo(int argc, const char ** argv)
 {
 	BOOL	first;
@@ -43,10 +43,11 @@
 	}
 
 	fputc('\n', stdout);
+	return 0;
 }
 
 
-void
+int
 do_pwd(int argc, const char ** argv)
 {
 	char	buf[PATH_LEN];
@@ -55,14 +56,15 @@
 	{
 		fprintf(stderr, "Cannot get current directory\n");
 
-		return;
+		return 1;
 	}
 
 	printf("%s\n", buf);
+	return 0;
 }
 
 
-void
+int
 do_cd(int argc, const char ** argv)
 {
 	const char *	path;
@@ -77,29 +79,38 @@
 		{
 			fprintf(stderr, "No HOME environment variable\n");
 
-			return;
+			return 1;
 		}
 	}
 
 	if (chdir(path) < 0)
+	{
 		perror(path);
+		return 1;
+	}
+	return 0;
 }
 
 
-void
+int
 do_mkdir(int argc, const char ** argv)
 {
+	int r = 0;
 	while (argc-- > 1)
 	{
 		if (mkdir(argv[1], 0777) < 0)
+		{
 			perror(argv[1]);
+			r = 1;
+		}
 
 		argv++;
 	}
+	return r;
 }
 
 
-void
+int
 do_mknod(int argc, const char ** argv)
 {
 	const char *	cp;
@@ -117,7 +128,7 @@
 	{
 		fprintf(stderr, "Bad device type\n");
 
-		return;
+		return 1;
 	}
 
 	major = 0;
@@ -130,7 +141,7 @@
 	{
 		fprintf(stderr, "Bad major number\n");
 
-		return;
+		return 1;
 	}
 
 	minor = 0;
@@ -143,53 +154,70 @@
 	{
 		fprintf(stderr, "Bad minor number\n");
 
-		return;
+		return 1;
 	}
 
 	if (mknod(argv[1], mode, major * 256 + minor) < 0)
+	{
 		perror(argv[1]);
+		return 1;
+	}
+	return 0;
 }
 
 
-void
+int
 do_rmdir(int argc, const char ** argv)
 {
+	int r = 0;
 	while (argc-- > 1)
 	{
 		if (rmdir(argv[1]) < 0)
+		{
 			perror(argv[1]);
+			r = 1;
+		}
 
 		argv++;
 	}
+	return r;
 }
 
 
-void
+int
 do_sync(int argc, const char ** argv)
 {
 	sync();
+	return 0;
 }
 
 
-void
+int
 do_rm(int argc, const char ** argv)
 {
+	int r = 0;
 	while (argc-- > 1)
 	{
 		if (unlink(argv[1]) < 0)
+		{
 			perror(argv[1]);
+			r = 1;
+		}
 
 		argv++;
 	}
+	return r;
 }
 
 
-void
+int
 do_chmod(int argc, const char ** argv)
 {
 	const char *	cp;
 	int		mode;
+	int		r;
 
+	r = 0;
 	mode = 0;
 	cp = argv[1];
 
@@ -200,7 +228,7 @@
 	{
 		fprintf(stderr, "Mode must be octal\n");
 
-		return;
+		return 1;
 	}
 
 	argc--;
@@ -209,21 +237,27 @@
 	while (argc-- > 1)
 	{
 		if (chmod(argv[1], mode) < 0)
+		{
 			perror(argv[1]);
+			r = 1;
+		}
 
 		argv++;
 	}
+	return r;
 }
 
 
-void
+int
 do_chown(int argc, const char ** argv)
 {
 	const char *	cp;
 	int		uid;
 	struct passwd *	pwd;
 	struct stat	statBuf;
+	int		r;
 
+	r = 0;
 	cp = argv[1];
 
 	if (isDecimal(*cp))
@@ -237,7 +271,7 @@
 		{
 			fprintf(stderr, "Bad uid value\n");
 
-			return;
+			return 1;
 		}
 	} else {
 		pwd = getpwnam(cp);
@@ -246,7 +280,7 @@
 		{
 			fprintf(stderr, "Unknown user name\n");
 
-			return;
+			return 1;
 		}
 
 		uid = pwd->pw_uid;
@@ -263,19 +297,23 @@
 			(chown(*argv, uid, statBuf.st_gid) < 0))
 		{
 			perror(*argv);
+			r = 1;
 		}
 	}
+	return r;
 }
 
 
-void
+int
 do_chgrp(int argc, const char ** argv)
 {
 	const char *	cp;
 	int		gid;
 	struct group *	grp;
 	struct stat	statBuf;
+	int		r;
 
+	r = 0;
 	cp = argv[1];
 
 	if (isDecimal(*cp))
@@ -289,7 +327,7 @@
 		{
 			fprintf(stderr, "Bad gid value\n");
 
-			return;
+			return 1;
 		}
 	}
 	else
@@ -300,7 +338,7 @@
 		{
 			fprintf(stderr, "Unknown group name\n");
 
-			return;
+			return 1;
 		}
 
 		gid = grp->gr_gid;
@@ -317,18 +355,22 @@
 			(chown(*argv, statBuf.st_uid, gid) < 0))
 		{
 			perror(*argv);
+			r = 1;
 		}
 	}
+	return r;
 }
 
 
-void
+int
 do_touch(int argc, const char ** argv)
 {
 	const char *	name;
 	int		fd;
 	struct utimbuf	now;
+	int		r;
 
+	r = 0;
 	time(&now.actime);
 	now.modtime = now.actime;
 
@@ -347,23 +389,30 @@
 
 		if (errno != EEXIST) {
 			perror(name);
+			r = 1;
 			continue;
 		}
 
 		if (utime(name, &now) < 0)
+		{
 			perror(name);
+			r = 1;
+		}
 	}
+	return r;
 }
 
 
-void
+int
 do_mv(int argc, const char ** argv)
 {
 	const char *	srcName;
 	const char *	destName;
 	const char *	lastArg;
 	BOOL		dirFlag;
+	int		r;
 
+	r = 0;
 	lastArg = argv[argc - 1];
 
 	dirFlag = isDirectory(lastArg);
@@ -372,7 +421,7 @@
 	{
 		fprintf(stderr, "%s: not a directory\n", lastArg);
 
-		return;
+		return 1;
 	}
 
 	while (!intFlag && (argc-- > 2))
@@ -382,6 +431,7 @@
 		if (access(srcName, 0) < 0)
 		{
 			perror(srcName);
+			r = 1;
 
 			continue;
 		}
@@ -397,6 +447,7 @@
 		if (errno != EXDEV)
 		{
 			perror(destName);
+			r = 1;
 
 			continue;
 		}
@@ -405,18 +456,25 @@
 			continue;
 
 		if (unlink(srcName) < 0)
+		{
 			perror(srcName);
+			r = 1;
+		}
 	}
+	return r;
 }
 
 
-void
+int
 do_ln(int argc, const char ** argv)
 {
 	const char *	srcName;
 	const char *	destName;
 	const char *	lastArg;
 	BOOL		dirFlag;
+	int		r;
+
+	r = 0;
 
 	if (argv[1][0] == '-')
 	{
@@ -424,23 +482,27 @@
 		{
 			fprintf(stderr, "Unknown option\n");
 
-			return;
+			return 1;
 		}
 
 		if (argc != 4)
 		{
 			fprintf(stderr, "Wrong number of arguments for symbolic link\n");
 
-			return;
+			return 1;
 		}
 
 #ifdef	S_ISLNK
 		if (symlink(argv[2], argv[3]) < 0)
+		{
 			perror(argv[3]);
+			return 1;
+		}
+		return 0;
 #else
 		fprintf(stderr, "Symbolic links are not allowed\n");
+		return 1;
 #endif
-		return;
 	}
 
 	/*
@@ -453,7 +515,7 @@
 	{
 		fprintf(stderr, "%s: not a directory\n", lastArg);
 
-		return;
+		return 1;
 	}
 
 	while (argc-- > 2)
@@ -463,6 +525,7 @@
 		if (access(srcName, 0) < 0)
 		{
 			perror(srcName);
+			r = 1;
 
 			continue;
 		}
@@ -475,21 +538,25 @@
 		if (link(srcName, destName) < 0)
 		{
 			perror(destName);
+			r = 1;
 
 			continue;
 		}
 	}
+	return r;
 }
 
 
-void
+int
 do_cp(int argc, const char ** argv)
 {
 	const char *	srcName;
 	const char *	destName;
 	const char *	lastArg;
 	BOOL		dirFlag;
+	int		r;
 
+	r = 0;
 	lastArg = argv[argc - 1];
 
 	dirFlag = isDirectory(lastArg);
@@ -498,7 +565,7 @@
 	{
 		fprintf(stderr, "%s: not a directory\n", lastArg);
 
-		return;
+		return 1;
 	}
 
 	while (!intFlag && (argc-- > 2))
@@ -509,12 +576,14 @@
 		if (dirFlag)
 			destName = buildName(destName, srcName);
 
-		(void) copyFile(srcName, destName, FALSE);
+		if (!copyFile(srcName, destName, FALSE))
+			r = 1;
 	}
+	return r;
 }
 
 
-void
+int
 do_mount(int argc, const char ** argv)
 {
 	const char *	str;
@@ -544,7 +613,7 @@
 				{
 					fprintf(stderr, "Missing file system type\n");
 
-					return;
+					return 1;
 				}
 
 				type = *argv++;
@@ -584,7 +653,7 @@
 			default:
 				fprintf(stderr, "Unknown option\n");
 
-				return;
+				return 1;
 		}
 	}
 
@@ -592,14 +661,16 @@
 	{
 		fprintf(stderr, "Wrong number of arguments for mount\n");
 
-		return;
+		return 1;
 	}
 
 #if	HAVE_LINUX_MOUNT
 
- 	if (mount(argv[0], argv[1], type, flags, 0) < 0)
- 		perror("mount failed");
-
+	if (mount(argv[0], argv[1], type, flags, 0) < 0)
+	{
+		perror("mount failed");
+		return 1;
+	}
 #elif	HAVE_BSD_MOUNT
 	{
 		struct	    ufs_args ufs;
@@ -622,22 +693,29 @@
 			fprintf(stderr, "Unknown filesystem type: %s", type);
 			fprintf(stderr,
 			    "Supported: ffs ufs adosfs cd9660 mfs msdos\n");
-			return;
+			return 1;
 		}
 
 		if (mount(type, argv[1], flags, args) < 0)
-		        perror(argv[0]);
+		{
+			perror(argv[0]);
+			return 1;
+		}
 	}
 #endif
+	return 0;
 }
 
 
-void
+int
 do_umount(int argc, const char ** argv)
 {
 #if	HAVE_LINUX_MOUNT
 	if (umount(argv[1]) < 0)
+	{
 		perror(argv[1]);
+		return 1;
+	}
 #elif	HAVE_BSD_MOUNT
 	{
 		const char *	str;
@@ -659,13 +737,17 @@
 		}
 
 		if (unmount(argv[0], flags) < 0)
+		{
 			perror(argv[0]);
+			return 1;
+		}
 	}
 #endif
+	return 0;
 }
 
 
-void
+int
 do_cmp(int argc, const char ** argv)
 {
 	int		fd1;
@@ -679,19 +761,22 @@
 	char		buf2[BUF_SIZE];
 	struct	stat	statBuf1;
 	struct	stat	statBuf2;
+	int		r;
+
+	r = 0;
 
 	if (stat(argv[1], &statBuf1) < 0)
 	{
 		perror(argv[1]);
 
-		return;
+		return 1;
 	}
 
 	if (stat(argv[2], &statBuf2) < 0)
 	{
 		perror(argv[2]);
 
-		return;
+		return 1;
 	}
 
 	if ((statBuf1.st_dev == statBuf2.st_dev) &&
@@ -699,14 +784,14 @@
 	{
 		printf("Files are links to each other\n");
 
-		return;
+		return 0;
 	}
 
 	if (statBuf1.st_size != statBuf2.st_size)
 	{
 		printf("Files are different sizes\n");
 
-		return;
+		return 1;
 	}
 
 	fd1 = open(argv[1], O_RDONLY);
@@ -715,7 +800,7 @@
 	{
 		perror(argv[1]);
 
-		return;
+		return 1;
 	}
 
 	fd2 = open(argv[2], O_RDONLY);
@@ -725,7 +810,7 @@
 		perror(argv[2]);
 		close(fd1);
 
-		return;
+		return 1;
 	}
 
 	pos = 0;
@@ -740,6 +825,7 @@
 		if (cc1 < 0)
 		{
 			perror(argv[1]);
+			r = 1;
 			goto closefiles;
 		}
 
@@ -748,24 +834,28 @@
 		if (cc2 < 0)
 		{
 			perror(argv[2]);
+			r = 1;
 			goto closefiles;
 		}
 
 		if ((cc1 == 0) && (cc2 == 0))
 		{
 			printf("Files are identical\n");
+			r = 0;
 			goto closefiles;
 		}
 
 		if (cc1 < cc2)
 		{
 			printf("First file is shorter than second\n");
+			r = 1;
 			goto closefiles;
 		}
 
 		if (cc1 > cc2)
 		{
 			printf("Second file is shorter than first\n");
+			r = 1;
 			goto closefiles;
 		}
 
@@ -783,6 +873,7 @@
 			pos++;
 
 		printf("Files differ at byte position %ld\n", pos);
+		r = 1;
 
 		goto closefiles;
 	}
@@ -790,10 +881,11 @@
 closefiles:
 	close(fd1);
 	close(fd2);
+	return r;
 }
 
 
-void
+int
 do_more(int argc, const char ** argv)
 {
 	FILE *		fp;
@@ -841,7 +933,7 @@
 		{
 			perror(name);
 
-			return;
+			return 1;
 		}
 
 		printf("<< %s >>\n", name);
@@ -896,7 +988,7 @@
 				if (fp)
 					fclose(fp);
 
-				return;
+				return 0;
 			}
 
 			ch = buf[0];
@@ -916,7 +1008,7 @@
 				case 'q':
 					fclose(fp);
 
-					return;
+					return 0;
 			}
 
 			col = 0;
@@ -926,10 +1018,11 @@
 		if (fp)
 			fclose(fp);
 	}
+	return 0;
 }
 
 
-void
+int
 do_sum(int argc, const char ** argv)
 {
 	const char *	name;
@@ -939,9 +1032,11 @@
 	int		i;
 	unsigned long	checksum;
 	char		buf[BUF_SIZE];
+	int		r;
 
 	argc--;
 	argv++;
+	r = 0;
 
 	while (argc-- > 0)
 	{
@@ -952,6 +1047,7 @@
 		if (fd < 0)
 		{
 			perror(name);
+			r = 1;
 
 			continue;
 		}
@@ -976,6 +1072,7 @@
 		if (cc < 0)
 		{
 			perror(name);
+			r = 1;
 
 			(void) close(fd);
 
@@ -986,10 +1083,11 @@
 
 		printf("%05lu %s\n", checksum, name);
 	}
+	return r;
 }
 
 
-void
+int
 do_exit(int argc, const char ** argv)
 {
 	int r = 0;
@@ -997,17 +1095,18 @@
 	{
 		fprintf(stderr, "You are the INIT process!\n");
 
-		return;
+		return 1;
 	}
 	if (argc == 2)
 	{
 		r = atoi(argv[1]);
 	}
 	exit(r);
+	return r;
 }
 
 
-void
+int
 do_setenv(int argc, const char ** argv)
 {
 	const char *	name;
@@ -1027,7 +1126,7 @@
 	{
 		fprintf(stderr, "Cannot allocate memory\n");
 
-		return;
+		return 1;
 	}
 
 	strcpy(str, name);
@@ -1035,10 +1134,11 @@
 	strcat(str, value);
 
 	putenv(str);
+	return 0;
 }
 
 
-void
+int
 do_printenv(int argc, const char ** argv)
 {
 	const char **	env;
@@ -1052,7 +1152,7 @@
 		while (*env)
 			printf("%s\n", *env++);
 
-		return;
+		return 0;
 	}
 
 	len = strlen(argv[1]);
@@ -1064,14 +1164,15 @@
 		{
 			printf("%s\n", &env[0][len+1]);
 
-			return;
+			return 0;
 		}
 		env++;
 	}
+	return 0;
 }
 
 
-void
+int
 do_umask(int argc, const char ** argv)
 {
 	const char *	cp;
@@ -1083,7 +1184,7 @@
 		umask(mask);
 		printf("%03o\n", mask);
 
-		return;
+		return 0;
 	}
 
 	mask = 0;
@@ -1096,20 +1197,24 @@
 	{
 		fprintf(stderr, "Bad umask value\n");
 
-		return;
+		return 1;
 	}
 
 	umask(mask);
+	return 0;
+
 }
 
 
-void
+int
 do_kill(int argc, const char ** argv)
 {
 	const char *	cp;
 	int		sig;
 	int		pid;
+	int		r;
 
+	r = 0;
 	sig = SIGTERM;
 
 	if (argv[1][0] == '-')
@@ -1145,7 +1250,7 @@
 			{
 				fprintf(stderr, "Unknown signal\n");
 
-				return;
+				return 1;
 			}
 		}
 
@@ -1165,16 +1270,20 @@
 		{
 			fprintf(stderr, "Non-numeric pid\n");
 
-			return;
+			return 1;
 		}
 
 		if (kill(pid, sig) < 0)
+		{
 			perror(*argv);
+			r = 1;
+		}
 	}
+	return r;
 }
 
 
-void
+int
 do_where(int argc, const char ** argv)
 {
 	const char *	program;
@@ -1183,6 +1292,7 @@
 	char *		endPath;
 	char *		fullPath;
 	BOOL		found;
+	int		r;
 
 	found = FALSE;
 	program = argv[1];
@@ -1191,7 +1301,7 @@
 	{
 		fprintf(stderr, "Program name cannot include a path\n");
 
-		return;
+		return 1;
 	}
 
 	path = getenv("PATH");
@@ -1203,7 +1313,7 @@
 	{
 		fprintf(stderr, "Memory allocation failed\n");
 
-		return;
+		return 1;
 	}
 
 	/*
@@ -1243,7 +1353,10 @@
 		if (access(fullPath, X_OK) < 0)
 		{
 			if (errno != ENOENT)
-				printf("%s: %s\n", fullPath, strerror(errno));
+			{
+				perror(fullPath);
+				r = 1;
+			}
 
 			continue;
 		}
@@ -1253,7 +1366,11 @@
 	}
 
 	if (!found)
+	{
 		printf("Program \"%s\" not found in PATH\n", program);
+		r = 1;
+	}
+	return r;
 }
 
 /* END CODE */
Index: sash-3.7/sash.h
===================================================================
--- sash-3.7.orig/sash.h	2010-04-04 11:45:33.888951646 +0200
+++ sash-3.7/sash.h	2010-04-04 11:46:22.112949938 +0200
@@ -58,56 +58,56 @@
 /*
  * Built-in command functions.
  */
-extern	void	do_alias(int argc, const char ** argv);
-extern	void	do_aliasall(int argc, const char ** argv);
-extern	void	do_cd(int argc, const char ** argv);
-extern	void	do_exec(int argc, const char ** argv);
-extern	void	do_exit(int argc, const char ** argv);
-extern	void	do_prompt(int argc, const char ** argv);
-extern	void	do_source(int argc, const char ** argv);
-extern	void	do_umask(int argc, const char ** argv);
-extern	void	do_unalias(int argc, const char ** argv);
-extern	void	do_help(int argc, const char ** argv);
-extern	void	do_ln(int argc, const char ** argv);
-extern	void	do_cp(int argc, const char ** argv);
-extern	void	do_mv(int argc, const char ** argv);
-extern	void	do_rm(int argc, const char ** argv);
-extern	void	do_chmod(int argc, const char ** argv);
-extern	void	do_mkdir(int argc, const char ** argv);
-extern	void	do_rmdir(int argc, const char ** argv);
-extern	void	do_mknod(int argc, const char ** argv);
-extern	void	do_chown(int argc, const char ** argv);
-extern	void	do_chgrp(int argc, const char ** argv);
-extern	void	do_sum(int argc, const char ** argv);
-extern	void	do_sync(int argc, const char ** argv);
-extern	void	do_printenv(int argc, const char ** argv);
-extern	void	do_more(int argc, const char ** argv);
-extern	void	do_cmp(int argc, const char ** argv);
-extern	void	do_touch(int argc, const char ** argv);
-extern	void	do_ls(int argc, const char ** argv);
-extern	void	do_dd(int argc, const char ** argv);
-extern	void	do_tar(int argc, const char ** argv);
-extern	void	do_ar(int argc, const char ** argv);
-extern	void	do_mount(int argc, const char ** argv);
-extern	void	do_umount(int argc, const char ** argv);
-extern	void	do_setenv(int argc, const char ** argv);
-extern	void	do_pwd(int argc, const char ** argv);
-extern	void	do_echo(int argc, const char ** argv);
-extern	void	do_kill(int argc, const char ** argv);
-extern	void	do_grep(int argc, const char ** argv);
-extern	void	do_file(int argc, const char ** argv);
-extern	void	do_find(int argc, const char ** argv);
-extern	void	do_ed(int argc, const char ** argv);
-extern	void	do_where(int argc, const char ** argv);
+extern	int	do_alias(int argc, const char ** argv);
+extern	int	do_aliasall(int argc, const char ** argv);
+extern	int	do_cd(int argc, const char ** argv);
+extern	int	do_exec(int argc, const char ** argv);
+extern	int	do_exit(int argc, const char ** argv);
+extern	int	do_prompt(int argc, const char ** argv);
+extern	int	do_source(int argc, const char ** argv);
+extern	int	do_umask(int argc, const char ** argv);
+extern	int	do_unalias(int argc, const char ** argv);
+extern	int	do_help(int argc, const char ** argv);
+extern	int	do_ln(int argc, const char ** argv);
+extern	int	do_cp(int argc, const char ** argv);
+extern	int	do_mv(int argc, const char ** argv);
+extern	int	do_rm(int argc, const char ** argv);
+extern	int	do_chmod(int argc, const char ** argv);
+extern	int	do_mkdir(int argc, const char ** argv);
+extern	int	do_rmdir(int argc, const char ** argv);
+extern	int	do_mknod(int argc, const char ** argv);
+extern	int	do_chown(int argc, const char ** argv);
+extern	int	do_chgrp(int argc, const char ** argv);
+extern	int	do_sum(int argc, const char ** argv);
+extern	int	do_sync(int argc, const char ** argv);
+extern	int	do_printenv(int argc, const char ** argv);
+extern	int	do_more(int argc, const char ** argv);
+extern	int	do_cmp(int argc, const char ** argv);
+extern	int	do_touch(int argc, const char ** argv);
+extern	int	do_ls(int argc, const char ** argv);
+extern	int	do_dd(int argc, const char ** argv);
+extern	int	do_tar(int argc, const char ** argv);
+extern	int	do_ar(int argc, const char ** argv);
+extern	int	do_mount(int argc, const char ** argv);
+extern	int	do_umount(int argc, const char ** argv);
+extern	int	do_setenv(int argc, const char ** argv);
+extern	int	do_pwd(int argc, const char ** argv);
+extern	int	do_echo(int argc, const char ** argv);
+extern	int	do_kill(int argc, const char ** argv);
+extern	int	do_grep(int argc, const char ** argv);
+extern	int	do_file(int argc, const char ** argv);
+extern	int	do_find(int argc, const char ** argv);
+extern	int	do_ed(int argc, const char ** argv);
+extern	int	do_where(int argc, const char ** argv);
 
 #if	HAVE_GZIP
-extern	void	do_gzip(int argc, const char ** argv);
-extern	void	do_gunzip(int argc, const char ** argv);
+extern	int	do_gzip(int argc, const char ** argv);
+extern	int	do_gunzip(int argc, const char ** argv);
 #endif
 
 #if	HAVE_LINUX_ATTR
-extern	void	do_lsattr(int argc, const char ** argv);
-extern	void	do_chattr(int argc, const char ** argv);
+extern	int	do_lsattr(int argc, const char ** argv);
+extern	int	do_chattr(int argc, const char ** argv);
 #endif
 
 
Index: sash-3.7/sash.c
===================================================================
--- sash-3.7.orig/sash.c	2010-04-04 11:45:33.876960339 +0200
+++ sash-3.7/sash.c	2010-04-04 11:46:22.116952745 +0200
@@ -31,7 +31,7 @@
 typedef struct
 {
 	const char *	name;
-	void		(*func)(int argc, const char ** argv);
+	int		(*func)(int argc, const char ** argv);
 	int		minArgs;
 	int		maxArgs;
 	const char *	description;
@@ -375,10 +375,10 @@
  */
 static	void	catchInt(int);
 static	void	catchQuit(int);
-static	void	readFile(const char * name);
-static	void	command(const char * cmd);
-static	BOOL	tryBuiltIn(const char * cmd);
-static	void	runCmd(const char * cmd);
+static	int	readFile(const char * name);
+static	int	command(const char * cmd);
+static	int	tryBuiltIn(const char * cmd);
+static	int	runCmd(const char * cmd);
 static	void	childProcess(const char * cmd);
 static	void	showPrompt(void);
 static	void	usage(void);
@@ -571,19 +571,20 @@
  * Read commands from the specified file.
  * A null name pointer indicates to read from stdin.
  */
-static void
+static int
 readFile(const char * name)
 {
 	FILE *	fp;
 	int	cc;
 	BOOL	ttyFlag;
 	char	buf[CMD_LEN];
+	int	r = 0;
 
 	if (sourceCount >= MAX_SOURCE)
 	{
 		fprintf(stderr, "Too many source files\n");
 
-		return;
+		return 1;
 	}
 
 	fp = stdin;
@@ -596,7 +597,7 @@
 		{
 			perror(name);
 
-			return;
+			return 1;
 		}
 	}
 
@@ -614,7 +615,7 @@
 			fclose(fp);
 			sourceCount--;
 
-			return;
+			return 1;
 		}
 	
 		if (fgets(buf, CMD_LEN - 1, fp) == NULL)
@@ -639,7 +640,7 @@
 
 		buf[cc] = '\0';
 
-		command(buf);
+		r = command(buf);
 	}
 
 	if (ferror(fp))
@@ -656,6 +657,7 @@
 		fclose(fp);
 
 	sourceCount--;
+	return r;
 }
 
 
@@ -664,13 +666,14 @@
  * This breaks the command line up into words, checks to see if the
  * command is an alias, and expands wildcards.
  */
-static void
+static int
 command(const char * cmd)
 {
 	const char *	endCmd;
 	const Alias *	alias;
 	char		newCommand[CMD_LEN];
 	char		cmdName[CMD_LEN];
+	int		r = -1;
 
 	/*
 	 * Rest the interrupt flag and free any memory chunks that
@@ -690,7 +693,7 @@
 	 * If the command is empty or is a comment then ignore it.
 	 */
 	if ((*cmd == '\0') || (*cmd == '#'))
-		return;
+		return 0;
 
 	/*
 	 * Look for the end of the command name and then copy the
@@ -725,14 +728,15 @@
 	 * Now look for the command in the builtin table, and execute
 	 * the command if found.
 	 */
-	if (tryBuiltIn(cmd))
-		return;
+	r = tryBuiltIn(cmd);
+	if (r >= 0)
+		return r;
 
 	/*
 	 * The command is not a built-in, so run the program along
 	 * the PATH list.
 	 */
-	runCmd(cmd);
+	return runCmd(cmd);
 }
 
 
@@ -741,7 +745,7 @@
  * Returns TRUE if the command is a built in, whether or not the
  * command succeeds.  Returns FALSE if this is not a built-in command.
  */
-static BOOL
+static int
 tryBuiltIn(const char * cmd)
 {
 	const char *		endCmd;
@@ -776,14 +780,14 @@
 	 * If the command is not a built-in, return indicating that.
 	 */
 	if (entry->name == NULL)
-		return FALSE;
+		return -1;
 
 	/*
 	 * The command is a built-in.
 	 * Break the command up into arguments and expand wildcards.
 	 */
 	if (!makeArgs(cmd, &argc, &argv))
-		return TRUE;
+		return 0;
 
 	/*
 	 * Give a usage string if the number of arguments is too large
@@ -793,15 +797,13 @@
 	{
 		fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage);
 
-		return TRUE;
+		return 0;
 	}
 
 	/*
 	 * Call the built-in function with the argument list.
 	 */
-	entry->func(argc, argv);
-
-	return TRUE;
+	return entry->func(argc, argv);
 }
 
 
@@ -809,7 +811,7 @@
  * Execute the specified command either by forking and executing
  * the program ourself, or else by using the shell.
  */
-static void
+static int
 runCmd(const char * cmd)
 {
 	const char *	cp;
@@ -854,9 +856,7 @@
 	 */
 	if (magic)
 	{
-		system(cmd);
-
-		return;
+		return system(cmd);
 	}
 
 	/*
@@ -869,7 +869,7 @@
 	{
 		perror("fork failed");
 
-		return;
+		return -1;
 	}
 
 	/*
@@ -894,7 +894,7 @@
 	{
 		fprintf(stderr, "Error from waitpid: %s", strerror(errno));
 
-		return;
+		return -1;
 	}
 
 	if (WIFSIGNALED(status))
@@ -902,6 +902,7 @@
 		fprintf(stderr, "pid %ld: killed by signal %d\n",
 			(long) pid, WTERMSIG(status));
 	}
+	return WEXITSTATUS(status);
 }
 
 
@@ -958,7 +959,7 @@
 }
 
 
-void
+int
 do_help(int argc, const char ** argv)
 {
 	const CommandEntry *	entry;
@@ -983,7 +984,7 @@
 				printf("usage: %s %s\n", entry->name,
 					entry->usage);
 
-				return;
+				return 0;
 			}
 		}
 	}
@@ -1000,10 +1001,11 @@
 			printf("%-10s %s\n", entry->name, entry->usage);
 		}
 	}
+	return 0;
 }
 
 
-void
+int
 do_alias(int argc, const char ** argv)
 {
 	const char *	name;
@@ -1019,7 +1021,7 @@
 		for (alias = aliasTable; count-- > 0; alias++)
 			printf("%s\t%s\n", alias->name, alias->value);
 
-		return;
+		return 0;
 	}
 
 	name = argv[1];
@@ -1029,22 +1031,26 @@
 		alias = findAlias(name);
 
 		if (alias)
+		{
 			printf("%s\n", alias->value);
+			return 0;
+		}
 		else
+		{
 			fprintf(stderr, "Alias \"%s\" is not defined\n", name);
-
-		return;	
+			return 1;
+		}
 	}
 
 	if (strcmp(name, "alias") == 0)
 	{
 		fprintf(stderr, "Cannot alias \"alias\"\n");
 
-		return;
+		return 1;
 	}
 
 	if (!makeString(argc - 2, argv + 2, buf, CMD_LEN))
-		return;
+		return -1;
 
 	value = malloc(strlen(buf) + 1);
 
@@ -1052,7 +1058,7 @@
 	{
 		fprintf(stderr, "No memory for alias value\n");
 
-		return;
+		return 1;
 	}
 
 	strcpy(value, buf);
@@ -1064,7 +1070,7 @@
 		free(alias->value);
 		alias->value = value;
 
-		return;
+		return 0;
 	}
 
 	if ((aliasCount % ALIAS_ALLOC) == 0)
@@ -1084,7 +1090,7 @@
 			free(value);
 			fprintf(stderr, "No memory for alias table\n");
 
-			return;
+			return 1;
 		}
 
 		aliasTable = alias;
@@ -1099,12 +1105,13 @@
 		free(value);
 		fprintf(stderr, "No memory for alias name\n");
 
-		return;
+		return 1;
 	}
 
 	strcpy(alias->name, name);
 	alias->value = value;
 	aliasCount++;
+	return 0;
 }
 
 
@@ -1112,12 +1119,13 @@
  * Build aliases for all of the built-in commands which start with a dash,
  * using the names without the dash.
  */
-void
+int
 do_aliasall(int argc, const char **argv)
 {
 	const CommandEntry *	entry;
 	const char *		name;
 	const char *		newArgv[4];
+	int			r;
 
 	for (entry = commandEntryTable; entry->name; entry++)
 	{
@@ -1131,8 +1139,13 @@
 		newArgv[2] = name;
 		newArgv[3] = NULL;
 
-		do_alias(3, newArgv);
+		r = do_alias(3, newArgv);
+		if (r != 0)
+		{
+			return r;
+		}
 	}
+	return 0;
 }
 
 
@@ -1158,14 +1171,14 @@
 }
 
 
-void
+int
 do_source(int argc, const char ** argv)
 {
-	readFile(argv[1]);
+	return readFile(argv[1]);
 }
 
 
-void
+int
 do_exec(int argc, const char ** argv)
 {
 	const char *	name;
@@ -1182,17 +1195,18 @@
 
 	execvp(name, (char **) argv + 1);
 	perror(name);
+	return 127;
 }
 
 
-void
+int
 do_prompt(int argc, const char ** argv)
 {
 	char *	cp;
 	char	buf[CMD_LEN];
 
 	if (!makeString(argc - 1, argv + 1, buf, CMD_LEN))
-		return;
+		return 1;
 
 	cp = malloc(strlen(buf) + 2);
 
@@ -1200,7 +1214,7 @@
 	{
 		fprintf(stderr, "No memory for prompt\n");
 
-		return;
+		return 1;
 	}
 
 	strcpy(cp, buf);
@@ -1210,10 +1224,11 @@
 		free(prompt);
 
 	prompt = cp;
+	return 0;
 }
 
 
-void
+int
 do_unalias(int argc, const char ** argv)
 {
 	Alias *	alias;
@@ -1231,6 +1246,7 @@
 		alias->name = aliasTable[aliasCount].name;
 		alias->value = aliasTable[aliasCount].value;	
 	}
+	return 0;
 }
 
 
Index: sash-3.7/cmd_dd.c
===================================================================
--- sash-3.7.orig/cmd_dd.c	2010-04-04 12:29:35.236953933 +0200
+++ sash-3.7/cmd_dd.c	2010-04-04 12:32:57.081955729 +0200
@@ -40,7 +40,7 @@
 static	long	getNum(const char * cp);
 
 
-void
+int
 do_dd(int argc, const char ** argv)
 {
 	const char *	str;
@@ -62,6 +62,7 @@
 	long		outPartial;
 	char *		buf;
 	char		localBuf[BUF_SIZE];
+	int		r;
 
 	inFile = NULL;
 	outFile = NULL;
@@ -69,6 +70,7 @@
 	skipVal = 0;
 	blockSize = 512;
 	count = -1;
+	r = 0;
 
 	while (--argc > 0)
 	{
@@ -79,7 +81,7 @@
 		{
 			fprintf(stderr, "Bad dd argument\n");
 
-			return;
+			return 1;
 		}
 
 		*cp++ = '\0';
@@ -97,7 +99,7 @@
 				{
 					fprintf(stderr, "Multiple input files illegal\n");
 
-					return;
+					return 1;
 				}
 	
 				inFile = cp;
@@ -108,7 +110,7 @@
 				{
 					fprintf(stderr, "Multiple output files illegal\n");
 
-					return;
+					return 1;
 				}
 
 				outFile = cp;
@@ -121,7 +123,7 @@
 				{
 					fprintf(stderr, "Bad block size value\n");
 
-					return;
+					return 1;
 				}
 
 				break;
@@ -133,7 +135,7 @@
 				{
 					fprintf(stderr, "Bad count value\n");
 
-					return;
+					return 1;
 				}
 
 				break;
@@ -145,7 +147,7 @@
 				{
 					fprintf(stderr, "Bad seek value\n");
 
-					return;
+					return 1;
 				}
 
 				break;
@@ -157,7 +159,7 @@
 				{
 					fprintf(stderr, "Bad skip value\n");
 
-					return;
+					return 1;
 				}
 
 				break;
@@ -165,7 +167,7 @@
 			default:
 				fprintf(stderr, "Unknown dd parameter\n");
 
-				return;
+				return 1;
 		}
 	}
 
@@ -173,14 +175,14 @@
 	{
 		fprintf(stderr, "No input file specified\n");
 
-		return;
+		return 1;
 	}
 
 	if (outFile == NULL)
 	{
 		fprintf(stderr, "No output file specified\n");
 
-		return;
+		return 1;
 	}
 
 	buf = localBuf;
@@ -193,7 +195,7 @@
 		{
 			fprintf(stderr, "Cannot allocate buffer\n");
 
-			return;
+			return 1;
 		}
 	}
 
@@ -211,7 +213,7 @@
 		if (buf != localBuf)
 			free(buf);
 
-		return;
+		return 1;
 	}
 
 	outFd = creat(outFile, 0666);
@@ -224,7 +226,7 @@
 		if (buf != localBuf)
 			free(buf);
 
-		return;
+		return 1;
 	}
 
 	if (skipVal)
@@ -238,12 +240,14 @@
 				if (inCc < 0)
 				{
 					perror(inFile);
+					r = 1;
 					goto cleanup;
 				}
 
 				if (inCc == 0)
 				{
 					fprintf(stderr, "End of file while skipping\n");
+					r = 1;
 					goto cleanup;
 				}
 			}
@@ -255,7 +259,7 @@
 		if (lseek(outFd, seekVal * blockSize, 0) < 0)
 		{
 			perror(outFile);
-
+			r = 1;
 			goto cleanup;
 		}
 	}
@@ -274,6 +278,7 @@
 		if (intFlag)
 		{
 			fprintf(stderr, "Interrupted\n");
+			r = 1;
 			goto cleanup;
 		}
 
@@ -284,6 +289,7 @@
 			if (outCc < 0)
 			{
 				perror(outFile);
+				r = 1;
 				goto cleanup;
 			}
 
@@ -303,7 +309,10 @@
 	close(inFd);
 
 	if (close(outFd) < 0)
+	{
 		perror(outFile);
+		r = 1;
+	}
 
 	if (buf != localBuf)
 		free(buf);
@@ -311,6 +320,7 @@
 	printf("%ld+%ld records in\n", inFull, inPartial);
 
 	printf("%ld+%ld records out\n", outFull, outPartial);
+	return r;
 }
 
 
Index: sash-3.7/cmd_ed.c
===================================================================
--- sash-3.7.orig/cmd_ed.c	2010-04-04 12:33:11.076954419 +0200
+++ sash-3.7/cmd_ed.c	2010-04-04 12:34:01.244953056 +0200
@@ -60,11 +60,11 @@
 	(const LINE * lp, const char * str, LEN len, LEN offset);
 
 
-void
+int
 do_ed(int argc, const char ** argv)
 {
 	if (!initEdit())
-		return;
+		return 1;
 
 	if (argc > 1)
 	{
@@ -75,14 +75,14 @@
 			fprintf(stderr, "No memory\n");
 			termEdit();
 
-			return;
+			return 1;
 		}
 
 		if (!readLines(fileName, 1))
 		{
 			termEdit();
 
-			return;
+			return 1;
 		}
 
 		if (lastNum)
@@ -94,6 +94,7 @@
 	doCommands();
 
 	termEdit();
+	return 0;
 }
 
 
Index: sash-3.7/cmd_grep.c
===================================================================
--- sash-3.7.orig/cmd_grep.c	2010-04-04 12:34:30.320951181 +0200
+++ sash-3.7/cmd_grep.c	2010-04-04 12:38:36.524986801 +0200
@@ -15,7 +15,7 @@
 	(const char * string, const char * word, BOOL ignoreCase);
 
 
-void
+int
 do_grep(int argc, const char ** argv)
 {
 	FILE *		fp;
@@ -27,7 +27,9 @@
 	BOOL		tellLine;
 	long		line;
 	char		buf[BUF_SIZE];
+	int		r;
 
+	r = 1;
 	ignoreCase = FALSE;
 	tellLine = FALSE;
 
@@ -52,7 +54,7 @@
 			default:
 				fprintf(stderr, "Unknown option\n");
 
-				return;
+				return 1;
 		}
 	}
 
@@ -70,6 +72,7 @@
 		if (fp == NULL)
 		{
 			perror(name);
+			r = 1;
 
 			continue;
 		}
@@ -82,7 +85,7 @@
 			{
 				fclose(fp);
 
-				return;
+				return 1;
 			}
 
 			line++;
@@ -94,6 +97,7 @@
 
 			if (search(buf, word, ignoreCase))
 			{
+				r = 0;
 				if (tellName)
 					printf("%s: ", name);
 
@@ -109,6 +113,7 @@
 
 		fclose(fp);
 	}
+	return r;
 }
 
 
Index: sash-3.7/cmd_ls.c
===================================================================
--- sash-3.7.orig/cmd_ls.c	2010-04-04 12:38:46.364975686 +0200
+++ sash-3.7/cmd_ls.c	2010-04-04 12:40:32.424951492 +0200
@@ -59,7 +59,7 @@
 static	void	clearListNames(void);
 
 
-void
+int
 do_ls(int argc, const char ** argv)
 {
 	const char *	cp;
@@ -72,6 +72,7 @@
 	struct dirent *	dp;
 	char		fullName[PATH_LEN];
 	struct	stat	statBuf;
+	int		r;
 
 	static const char *	def[] = {"."};
 
@@ -105,7 +106,7 @@
 			default:
 				fprintf(stderr, "Unknown option -%c\n", cp[-1]);
 
-				return;
+				return 1;
 		}
 	}
 
@@ -153,7 +154,7 @@
 		if ((flags & LSF_DIR) || !isDirectory(argv[i]))
 		{
 			if (!addListName(argv[i]))
-				return;
+				return 1;
 		}
 	}
 
@@ -167,7 +168,7 @@
 	 * If directories were being listed as themselves, then we are done.
 	 */
 	if (flags & LSF_DIR)
-		return;
+		return r;
 
 	/*
 	 * Now iterate over the file names processing the directories.
@@ -180,6 +181,7 @@
 		if (LSTAT(name, &statBuf) < 0)
 		{
 			perror(name);
+			r = 1;
 
 			continue;
 		}
@@ -226,7 +228,7 @@
 			{
 				closedir(dirp);
 
-				return;
+				return 1;
 			}
 		}
 
@@ -239,6 +241,7 @@
 		listAllFiles(flags, displayWidth);
 		clearListNames();
 	}
+	return r;
 }
 
 
Index: sash-3.7/cmd_tar.c
===================================================================
--- sash-3.7.orig/cmd_tar.c	2010-04-04 12:40:41.588964080 +0200
+++ sash-3.7/cmd_tar.c	2010-04-04 12:41:56.960954363 +0200
@@ -119,7 +119,7 @@
 
 
 
-void
+int
 do_tar(int argc, const char ** argv)
 {
 	const char *	options;
@@ -131,7 +131,7 @@
 	{
 		fprintf(stderr, "Too few arguments for tar\n");
 
-		return;
+		return 1;
 	}
 
 	extractFlag = FALSE;
@@ -158,7 +158,7 @@
 				{
 					fprintf(stderr, "Only one 'f' option allowed\n");
 
-					return;
+					return 1;
 				}
 
 				tarName = *argv++;
@@ -185,7 +185,7 @@
 			default:
 				fprintf(stderr, "Unknown tar flag '%c'\n", *options);
 
-				return;
+				return 1;
 		}
 	}
 
@@ -196,14 +196,14 @@
 	{
 		fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n");
 
-		return;
+		return 1;
 	}
 
 	if (tarName == NULL)
 	{
 		fprintf(stderr, "The 'f' flag must be specified\n");
 
-		return;
+		return 1;
 	}
 
 	/*
@@ -211,9 +211,9 @@
 	 * command line arguments as the list of files to process.
 	 */
 	if (createFlag)
-		writeTarFile(argc, argv);
+		return writeTarFile(argc, argv);
 	else
-		readTarFile(argc, argv);
+		return readTarFile(argc, argv);
 }
 
 
@@ -221,7 +221,7 @@
  * Read a tar file and extract or list the specified files within it.
  * If the list is empty than all files are extracted or listed.
  */
-static void
+static int
 readTarFile(int fileCount, const char ** fileTable)
 {
 	const char *	cp;
@@ -250,7 +250,7 @@
 	{
 		perror(tarName);
 
-		return;
+		return 1;
 	}
 
 	/*
