From: Tollef Fog Heen Date: Sun, 4 Apr 2010 08:25:57 +0000 (+0200) Subject: Imported Debian patch 3.7-10 X-Git-Tag: debian/3.7-10 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7f76bd5f9d6bee84d0cef4b4730adebdfe5a2f4e;p=sash Imported Debian patch 3.7-10 --- diff --git a/Makefile b/Makefile index f7e2e3c..bd8358e 100644 --- a/Makefile +++ b/Makefile @@ -13,12 +13,13 @@ HAVE_LINUX_MOUNT = 1 HAVE_BSD_MOUNT = 0 MOUNT_TYPE = '"ext3"' -DEFS = -DHAVE_GZIP=$(HAVE_GZIP) \ + +CFLAGS = -O3 -Wall -Wmissing-prototypes \ + -DHAVE_GZIP=$(HAVE_GZIP) \ -DHAVE_LINUX_ATTR=$(HAVE_LINUX_ATTR) \ -DHAVE_LINUX_MOUNT=$(HAVE_LINUX_MOUNT) \ -DHAVE_BSD_MOUNT=$(HAVE_BSD_MOUNT) \ -DMOUNT_TYPE=$(MOUNT_TYPE) -CFLAGS = -O3 -Wall -Wmissing-prototypes -g $(DEFS) LDFLAGS = -static -s LIBS = -lz @@ -42,7 +43,4 @@ install: sash cp sash $(BINDIR)/sash cp sash.1 $(MANDIR)/sash.1 -%.o: %.c - $(CC) $(CFLAGS) $(DEFS) -c $< - $(OBJS): sash.h diff --git a/cmd_chattr.c b/cmd_chattr.c index 9f697ea..5fc43c2 100644 --- a/cmd_chattr.c +++ b/cmd_chattr.c @@ -12,7 +12,7 @@ #include #include -#include +#include #include "sash.h" diff --git a/cmds.c b/cmds.c index a576269..ec85539 100644 --- a/cmds.c +++ b/cmds.c @@ -337,9 +337,12 @@ do_touch(int argc, const char ** argv) if (fd >= 0) { close(fd); - } else { - perror(name); + + continue; } + + if (utime(name, &now) < 0) + perror(name); } } @@ -990,18 +993,14 @@ do_sum(int argc, const char ** argv) void do_exit(int argc, const char ** argv) { - int r = 0; if (getpid() == 1) { fprintf(stderr, "You are the INIT process!\n"); return; } - if (argc == 2) - { - r = atoi(argv[1]); - } - exit(r); + + exit(0); } diff --git a/debian/changelog b/debian/changelog index 8df708b..0d3ddae 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,3 +1,15 @@ +sash (3.7-10) unstable; urgency=low + + * Switch to 3.0 (quilt) as the source format and convert patches. + * Fix up debian/patches/touch_error_handling to actually update the + timestamp of the file, something that has been broken for more than + ten years. + * Add kFreeBSD build fixes from Axel Beckert. Closes: #565539 + * When exiting the shell, use the exit status of the last command as our + exit status. Closes: #281728 + + -- Tollef Fog Heen Sun, 04 Apr 2010 10:25:57 +0200 + sash (3.7-9) unstable; urgency=low * Drop dependency on lockfile-progs, no longer needed. diff --git a/debian/control b/debian/control index e5be88e..0efef3a 100644 --- a/debian/control +++ b/debian/control @@ -3,7 +3,9 @@ Section: shells Priority: optional Maintainer: Tollef Fog Heen Standards-Version: 3.8.0 -Build-Depends: zlib1g-dev (>= 1:1.2.2-7), debhelper (>= 7), e2fslibs-dev +Build-Depends: zlib1g-dev (>= 1:1.2.2-7), debhelper (>= 7), + e2fslibs-dev [!kfreebsd-amd64 !kfreebsd-i386], + kfreebsd-kernel-headers [kfreebsd-amd64 kfreebsd-i386] Package: sash Architecture: any diff --git a/debian/patches/__inactive__exit_with_command_status b/debian/patches/__inactive__exit_with_command_status new file mode 100644 index 0000000..8190b99 --- /dev/null +++ b/debian/patches/__inactive__exit_with_command_status @@ -0,0 +1,1976 @@ +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; + } + + /* diff --git a/debian/patches/buildsystem b/debian/patches/buildsystem new file mode 100644 index 0000000..ee0ed89 --- /dev/null +++ b/debian/patches/buildsystem @@ -0,0 +1,28 @@ +Index: sash-3.7/Makefile +=================================================================== +--- sash-3.7.orig/Makefile 2010-04-04 10:13:55.176949485 +0200 ++++ sash-3.7/Makefile 2010-04-04 10:14:03.300968030 +0200 +@@ -13,13 +13,12 @@ + HAVE_BSD_MOUNT = 0 + MOUNT_TYPE = '"ext3"' + +- +-CFLAGS = -O3 -Wall -Wmissing-prototypes \ +- -DHAVE_GZIP=$(HAVE_GZIP) \ ++DEFS = -DHAVE_GZIP=$(HAVE_GZIP) \ + -DHAVE_LINUX_ATTR=$(HAVE_LINUX_ATTR) \ + -DHAVE_LINUX_MOUNT=$(HAVE_LINUX_MOUNT) \ + -DHAVE_BSD_MOUNT=$(HAVE_BSD_MOUNT) \ + -DMOUNT_TYPE=$(MOUNT_TYPE) ++CFLAGS = -O3 -Wall -Wmissing-prototypes -g $(DEFS) + + LDFLAGS = -static -s + LIBS = -lz +@@ -43,4 +42,7 @@ + cp sash $(BINDIR)/sash + cp sash.1 $(MANDIR)/sash.1 + ++%.o: %.c ++ $(CC) $(CFLAGS) $(DEFS) -c $< ++ + $(OBJS): sash.h diff --git a/debian/patches/debian-changes-3.7-10 b/debian/patches/debian-changes-3.7-10 new file mode 100644 index 0000000..9474294 --- /dev/null +++ b/debian/patches/debian-changes-3.7-10 @@ -0,0 +1,1324 @@ +Description: Upstream changes introduced in version 3.7-10 + This patch has been created by dpkg-source during the package build. + Here's the last changelog entry, hopefully it gives details on why + those changes were made: + . + sash (3.7-10) unstable; urgency=low + . + * Switch to 3.0 (quilt) as the source format and convert patches. + * Fix up debian/patches/touch_error_handling to actually update the + timestamp of the file, something that has been broken for more than + ten years. + * Add kFreeBSD build fixes from Axel Beckert. Closes: #565539 + * When exiting the shell, use the exit status of the last command as our + exit status. Closes: #281728 + . + The person named in the Author field signed this changelog entry. +Author: Tollef Fog Heen +Bug-Debian: http://bugs.debian.org/281728 +Bug-Debian: http://bugs.debian.org/565539 + +--- +The information above should follow the Patch Tagging Guidelines, please +checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here +are templates for supplementary fields that you might want to add: + +Origin: , +Bug: +Bug-Debian: http://bugs.debian.org/ +Forwarded: +Reviewed-By: +Last-Update: + +--- /dev/null ++++ sash-3.7/sash.c.old +@@ -0,0 +1,1289 @@ ++/* ++ * Copyright (c) 2004 by David I. Bell ++ * Permission is granted to use, distribute, or modify this source, ++ * provided that this copyright notice remains intact. ++ * ++ * Stand-alone shell for system maintainance for Linux. ++ * This program should NOT be built using shared libraries. ++ */ ++ ++#include ++#include ++#include ++#include ++ ++#include "sash.h" ++ ++ ++static const char * const version = "3.7"; ++ ++ ++/* ++ * The special maximum argument value which means that there is ++ * no limit to the number of arguments on the command line. ++ */ ++#define INFINITE_ARGS 0x7fffffff ++ ++ ++/* ++ * One entry of the command table. ++ */ ++typedef struct ++{ ++ const char * name; ++ void (*func)(int argc, const char ** argv); ++ int minArgs; ++ int maxArgs; ++ const char * description; ++ const char * usage; ++} CommandEntry; ++ ++ ++/* ++ * The table of built-in commands. ++ * This is terminated wih an entry containing NULL values. ++ */ ++static const CommandEntry commandEntryTable[] = ++{ ++ { ++ "alias", do_alias, 1, INFINITE_ARGS, ++ "Define a command alias", ++ "[name [command]]" ++ }, ++ ++ { ++ "aliasall", do_aliasall, 1, 1, ++ "Define aliases for all of the build-in commands", ++ "" ++ }, ++ ++ { ++ "-ar", do_ar, 3, INFINITE_ARGS, ++ "Extract or list files from an AR file", ++ "[txp]v arFileName fileName ..." ++ }, ++ ++ { ++ "cd", do_cd, 1, 2, ++ "Change current directory", ++ "[dirName]" ++ }, ++ ++#if HAVE_LINUX_ATTR ++ { ++ "-chattr", do_chattr, 3, INFINITE_ARGS, ++ "Change ext2 file attributes", ++ "[+i] [-i] [+a] [-a] fileName ..." ++ }, ++#endif ++ ++ { ++ "-chgrp", do_chgrp, 3, INFINITE_ARGS, ++ "Change the group id of some files", ++ "gid fileName ..." ++ }, ++ ++ { ++ "-chmod", do_chmod, 3, INFINITE_ARGS, ++ "Change the protection of some files", ++ "mode fileName ..." ++ }, ++ ++ { ++ "-chown", do_chown, 3, INFINITE_ARGS, ++ "Change the owner id of some files", ++ "uid fileName ..." ++ }, ++ ++ { ++ "-cmp", do_cmp, 3, 3, ++ "Compare two files for equality", ++ "fileName1 fileName2" ++ }, ++ ++ { ++ "-cp", do_cp, 3, INFINITE_ARGS, ++ "Copy files", ++ "srcName ... destName" ++ }, ++ ++ { ++ "-dd", do_dd, 3, INFINITE_ARGS, ++ "Copy data between two files", ++ "if=name of=name [bs=n] [count=n] [skip=n] [seek=n]" ++ }, ++ ++ { ++ "-echo", do_echo, 1, INFINITE_ARGS, ++ "Echo the arguments", ++ "[args] ..." ++ }, ++ ++ { ++ "-ed", do_ed, 1, 2, ++ "Edit a fileName using simple line mode commands", ++ "[fileName]" ++ }, ++ ++ { ++ "exec", do_exec, 2, INFINITE_ARGS, ++ "Execute another program in place of this sash process", ++ "fileName [args]" ++ }, ++ ++ { ++ "exit", do_exit, 1, 2, ++ "Exit from sash", ++ "[exit value]" ++ }, ++ ++ { ++ "-file", do_file, 1, INFINITE_ARGS, ++ "Describe information about files", ++ "fileName ..." ++ }, ++ ++ { ++ "-find", do_find, 2, INFINITE_ARGS, ++ "Find files in a directory tree meeting some conditions", ++ "dirName [-xdev] [-type chars] [-name pattern] [-size minSize]" ++ }, ++ ++ { ++ "-grep", do_grep, 3, INFINITE_ARGS, ++ "Look for lines containing a word in some files", ++ "[-in] word fileName ..." ++ }, ++ ++#if HAVE_GZIP ++ { ++ "-gunzip", do_gunzip, 2, INFINITE_ARGS, ++ "Uncompress files which were saved in GZIP or compress format", ++ "fileName ... [-o outputPath]" ++ }, ++ ++ { ++ "-gzip", do_gzip, 2, INFINITE_ARGS, ++ "Compress files into GZIP format", ++ "fileName ... [-o outputPath]" ++ }, ++#endif ++ ++ { ++ "help", do_help, 1, 2, ++ "Print help about a command", ++ "[word]" ++ }, ++ ++ { ++ "-kill", do_kill, 2, INFINITE_ARGS, ++ "Send a signal to the specified process", ++ "[-sig] pid ..." ++ }, ++ ++ { ++ "-ln", do_ln, 3, INFINITE_ARGS, ++ "Link one fileName to another", ++ "[-s] srcName ... destName" ++ }, ++ ++ { ++ "-ls", do_ls, 1, INFINITE_ARGS, ++ "List information about files or directories", ++ "[-lidFC] fileName ..." ++ }, ++ ++#if HAVE_LINUX_ATTR ++ { ++ "-lsattr", do_lsattr, 2, INFINITE_ARGS, ++ "List ext2 file attributes", ++ "fileName ..." ++ }, ++#endif ++ ++ { ++ "-mkdir", do_mkdir, 2, INFINITE_ARGS, ++ "Create a directory", ++ "dirName ..." ++ }, ++ ++ { ++ "-mknod", do_mknod, 5, 5, ++ "Create a special type of file", ++ "fileName type major minor" ++ }, ++ ++ { ++ "-more", do_more, 2, INFINITE_ARGS, ++ "Type file contents page by page", ++ "fileName ..." ++ }, ++ ++ { ++ "-mount", do_mount, 3, INFINITE_ARGS, ++ "Mount or remount a filesystem on a directory", ++#if HAVE_LINUX_MOUNT ++ "[-t type] [-r] [-s] [-e] [-m] devName dirName" ++#elif HAVE_BSD_MOUNT ++ "[-t type] [-r] [-s] [-e] devName dirName" ++#else ++ "[-t type] devName dirName" ++#endif ++ }, ++ ++ { ++ "-mv", do_mv, 3, INFINITE_ARGS, ++ "Move or rename files", ++ "srcName ... destName" ++ }, ++ ++ { ++ "-printenv", do_printenv, 1, 2, ++ "Print environment variables", ++ "[name]" ++ }, ++ ++ { ++ "prompt", do_prompt, 2, INFINITE_ARGS, ++ "Set the prompt string for sash", ++ "string" ++ }, ++ ++ { ++ "-pwd", do_pwd, 1, 1, ++ "Print the current working directory", ++ "" ++ }, ++ ++ { ++ "quit", do_exit, 1, 1, ++ "Exit from sash", ++ "" ++ }, ++ ++ { ++ "-rm", do_rm, 2, INFINITE_ARGS, ++ "Remove the specified files", ++ "fileName ..." ++ }, ++ ++ { ++ "-rmdir", do_rmdir, 2, INFINITE_ARGS, ++ "Remove the specified empty directories", ++ "dirName ..." ++ }, ++ ++ { ++ "setenv", do_setenv, 3, 3, ++ "Set an environment variable value", ++ "name value" ++ }, ++ ++ { ++ "source", do_source, 2, 2, ++ "Read commands from the specified file", ++ "fileName" ++ }, ++ ++ { ++ "-sum", do_sum, 2, INFINITE_ARGS, ++ "Calculate checksums of the specified files", ++ "fileName ..." ++ }, ++ ++ { ++ "-sync", do_sync, 1, 1, ++ "Sync the disks to force cached data to them", ++ "" ++ }, ++ ++ { ++ "-tar", do_tar, 2, INFINITE_ARGS, ++ "Create, extract, or list files from a TAR file", ++ "[cxtv]f tarFileName fileName ..." ++ }, ++ ++ { ++ "-touch", do_touch, 2, INFINITE_ARGS, ++ "Update times or create the specified files", ++ "fileName ..." ++ }, ++ ++ { ++ "umask", do_umask, 1, 2, ++ "Set the umask value for file protections", ++ "[mask]" ++ }, ++ ++ { ++#if HAVE_BSD_MOUNT ++ "-umount", do_umount, 2, 3, ++ "Unmount a filesystem", ++ "[-f] fileName" ++#else ++ "-umount", do_umount, 2, 2, ++ "Unmount a filesystem", ++ "fileName" ++#endif ++ }, ++ ++ { ++ "unalias", do_unalias, 2, 2, ++ "Remove a command alias", ++ "name" ++ }, ++ ++ { ++ "-where", do_where, 2, 2, ++ "Type the location of a program", ++ "program" ++ }, ++ ++ { ++ NULL, 0, 0, 0, ++ NULL, ++ NULL ++ } ++}; ++ ++ ++/* ++ * The definition of an command alias. ++ */ ++typedef struct ++{ ++ char * name; ++ char * value; ++} Alias; ++ ++ ++/* ++ * Local data. ++ */ ++static Alias * aliasTable; ++static int aliasCount; ++ ++static FILE * sourcefiles[MAX_SOURCE]; ++static int sourceCount; ++ ++static BOOL intCrlf = TRUE; ++static char * prompt; ++ ++ ++/* ++ * Local procedures. ++ */ ++static void catchInt(int); ++static void catchQuit(int); ++static int readFile(const char * name); ++static int command(const char * cmd); ++static BOOL tryBuiltIn(const char * cmd); ++static int runCmd(const char * cmd); ++static void childProcess(const char * cmd); ++static void showPrompt(void); ++static void usage(void); ++static Alias * findAlias(const char * name); ++ ++ ++/* ++ * Global interrupt flag. ++ */ ++BOOL intFlag; ++ ++ ++int ++main(int argc, const char ** argv) ++{ ++ const char * cp; ++ const char * singleCommand; ++ const char * commandFile; ++ BOOL quietFlag; ++ BOOL aliasFlag; ++ BOOL interactiveFlag; ++ char buf[PATH_LEN]; ++ ++ singleCommand = NULL; ++ commandFile = NULL; ++ quietFlag = FALSE; ++ aliasFlag = FALSE; ++ interactiveFlag = FALSE; ++ ++ /* ++ * Look for options. ++ */ ++ argv++; ++ argc--; ++ ++ while ((argc > 0) && (**argv == '-')) ++ { ++ cp = *argv++ + 1; ++ argc--; ++ ++ while (*cp) switch (*cp++) ++ { ++ case '-': ++ /* ++ * Ignore. This is so that we can be ++ * run from login. ++ */ ++ break; ++ case 'c': ++ /* ++ * Execute specified command. ++ */ ++ if ((argc != 1) || singleCommand || interactiveFlag) ++ usage(); ++ ++ singleCommand = *argv++; ++ argc--; ++ ++ break; ++ ++ case 'f': ++ /* ++ * Execute commands from file. ++ * This is used for sash script files. ++ * The quiet flag is also set. ++ */ ++ if ((argc != 1) || commandFile) ++ usage(); ++ ++ quietFlag = TRUE; ++ commandFile = *argv++; ++ argc--; ++ ++ break; ++ ++ case 'i': ++ /* ++ * Be an interactive shell ++ * ..is a no-op, but some contexts require this ++ * ..interactiveFlag is to avoid -ic as a legacy ++ */ ++ if (singleCommand) ++ usage(); ++ ++ interactiveFlag = TRUE; ++ break; ++ ++ case 'p': ++ /* ++ * Set the prompt string. ++ */ ++ if ((argc <= 0) || (**argv == '-')) ++ usage(); ++ ++ if (prompt) ++ free(prompt); ++ ++ prompt = strdup(*argv++); ++ argc--; ++ ++ break; ++ ++ case 'q': ++ quietFlag = TRUE; ++ break; ++ ++ case 'a': ++ aliasFlag = TRUE; ++ break; ++ ++ case 'h': ++ case '?': ++ usage(); ++ break; ++ ++ default: ++ fprintf(stderr, "Unknown option -%c\n", cp[-1]); ++ ++ return 1; ++ } ++ } ++ ++ /* ++ * No more arguments are allowed. ++ */ ++ if (argc > 0) ++ usage(); ++ ++ /* ++ * Default our path if it is not set. ++ */ ++ if (getenv("PATH") == NULL) ++ putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc"); ++ ++ /* ++ * If the alias flag is set then define all aliases. ++ */ ++ if (aliasFlag) ++ do_aliasall(0, NULL); ++ ++ /* ++ * If we are to execute a single command, then do so and exit. ++ */ ++ if (singleCommand) ++ { ++ return command(singleCommand); ++ } ++ ++ /* ++ * Print a hello message unless we are told to be silent. ++ */ ++ if (!quietFlag && isatty(STDIN)) ++ { ++ printf("Stand-alone shell (version %s)\n", version); ++ ++ if (aliasFlag) ++ printf("Built-in commands are aliased to standard commands\n"); ++ } ++ ++ signal(SIGINT, catchInt); ++ signal(SIGQUIT, catchQuit); ++ ++ /* ++ * Execute the user's alias file if present. ++ */ ++ cp = getenv("HOME"); ++ ++ if (cp) ++ { ++ strcpy(buf, cp); ++ strcat(buf, "/"); ++ strcat(buf, ".aliasrc"); ++ ++ if ((access(buf, 0) == 0) || (errno != ENOENT)) ++ readFile(buf); ++ } ++ ++ /* ++ * Read commands from stdin or from a command file. ++ */ ++ return readFile(commandFile); ++ ++} ++ ++ ++/* ++ * Read commands from the specified file. ++ * A null name pointer indicates to read from stdin. ++ */ ++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 1; ++ } ++ ++ fp = stdin; ++ ++ if (name) ++ { ++ fp = fopen(name, "r"); ++ ++ if (fp == NULL) ++ { ++ perror(name); ++ ++ return 1; ++ } ++ } ++ ++ sourcefiles[sourceCount++] = fp; ++ ++ ttyFlag = isatty(fileno(fp)); ++ ++ while (TRUE) ++ { ++ if (ttyFlag) ++ showPrompt(); ++ ++ if (intFlag && !ttyFlag && (fp != stdin)) ++ { ++ fclose(fp); ++ sourceCount--; ++ ++ return 1; ++ } ++ ++ if (fgets(buf, CMD_LEN - 1, fp) == NULL) ++ { ++ if (ferror(fp) && (errno == EINTR)) ++ { ++ clearerr(fp); ++ ++ continue; ++ } ++ ++ break; ++ } ++ ++ cc = strlen(buf); ++ ++ if (buf[cc - 1] == '\n') ++ cc--; ++ ++ while ((cc > 0) && isBlank(buf[cc - 1])) ++ cc--; ++ ++ buf[cc] = '\0'; ++ ++ r = command(buf); ++ } ++ ++ if (ferror(fp)) ++ { ++ perror("Reading command line"); ++ ++ if (fp == stdin) ++ exit(1); ++ } ++ ++ clearerr(fp); ++ ++ if (fp != stdin) ++ fclose(fp); ++ ++ sourceCount--; ++ return r; ++} ++ ++ ++/* ++ * Parse and execute one null-terminated command line string. ++ * This breaks the command line up into words, checks to see if the ++ * command is an alias, and expands wildcards. ++ */ ++static int ++command(const char * cmd) ++{ ++ const char * endCmd; ++ const Alias * alias; ++ char newCommand[CMD_LEN]; ++ char cmdName[CMD_LEN]; ++ ++ /* ++ * Rest the interrupt flag and free any memory chunks that ++ * were allocated by the previous command. ++ */ ++ intFlag = FALSE; ++ ++ freeChunks(); ++ ++ /* ++ * Skip leading blanks. ++ */ ++ while (isBlank(*cmd)) ++ cmd++; ++ ++ /* ++ * If the command is empty or is a comment then ignore it. ++ */ ++ if ((*cmd == '\0') || (*cmd == '#')) ++ return 0; ++ ++ /* ++ * Look for the end of the command name and then copy the ++ * command name to a buffer so we can null terminate it. ++ */ ++ endCmd = cmd; ++ ++ while (*endCmd && !isBlank(*endCmd)) ++ endCmd++; ++ ++ memcpy(cmdName, cmd, endCmd - cmd); ++ ++ cmdName[endCmd - cmd] = '\0'; ++ ++ /* ++ * Search for the command name in the alias table. ++ * If it is found, then replace the command name with ++ * the alias value, and append the current command ++ * line arguments to that. ++ */ ++ alias = findAlias(cmdName); ++ ++ if (alias) ++ { ++ strcpy(newCommand, alias->value); ++ strcat(newCommand, endCmd); ++ ++ cmd = newCommand; ++ } ++ ++ /* ++ * Now look for the command in the builtin table, and execute ++ * the command if found. ++ */ ++ if (tryBuiltIn(cmd)) ++ return 0; /* This is a blatant lie */ ++ ++ /* ++ * The command is not a built-in, so run the program along ++ * the PATH list. ++ */ ++ return runCmd(cmd); ++} ++ ++ ++/* ++ * Try to execute a built-in command. ++ * 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 ++tryBuiltIn(const char * cmd) ++{ ++ const char * endCmd; ++ const CommandEntry * entry; ++ int argc; ++ const char ** argv; ++ char cmdName[CMD_LEN]; ++ ++ /* ++ * Look for the end of the command name and then copy the ++ * command name to a buffer so we can null terminate it. ++ */ ++ endCmd = cmd; ++ ++ while (*endCmd && !isBlank(*endCmd)) ++ endCmd++; ++ ++ memcpy(cmdName, cmd, endCmd - cmd); ++ ++ cmdName[endCmd - cmd] = '\0'; ++ ++ /* ++ * Search the command table looking for the command name. ++ */ ++ for (entry = commandEntryTable; entry->name != NULL; entry++) ++ { ++ if (strcmp(entry->name, cmdName) == 0) ++ break; ++ } ++ ++ /* ++ * If the command is not a built-in, return indicating that. ++ */ ++ if (entry->name == NULL) ++ return FALSE; ++ ++ /* ++ * The command is a built-in. ++ * Break the command up into arguments and expand wildcards. ++ */ ++ if (!makeArgs(cmd, &argc, &argv)) ++ return TRUE; ++ ++ /* ++ * Give a usage string if the number of arguments is too large ++ * or too small. ++ */ ++ if ((argc < entry->minArgs) || (argc > entry->maxArgs)) ++ { ++ fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage); ++ ++ return TRUE; ++ } ++ ++ /* ++ * Call the built-in function with the argument list. ++ */ ++ entry->func(argc, argv); ++ ++ return TRUE; ++} ++ ++ ++/* ++ * Execute the specified command either by forking and executing ++ * the program ourself, or else by using the shell. ++ */ ++static int ++runCmd(const char * cmd) ++{ ++ const char * cp; ++ BOOL magic; ++ pid_t pid; ++ int status; ++ ++ /* ++ * Check the command for any magic shell characters ++ * except for quoting. ++ */ ++ magic = FALSE; ++ ++ for (cp = cmd; *cp; cp++) ++ { ++ if ((*cp >= 'a') && (*cp <= 'z')) ++ continue; ++ ++ if ((*cp >= 'A') && (*cp <= 'Z')) ++ continue; ++ ++ if (isDecimal(*cp)) ++ continue; ++ ++ if (isBlank(*cp)) ++ continue; ++ ++ if ((*cp == '.') || (*cp == '/') || (*cp == '-') || ++ (*cp == '+') || (*cp == '=') || (*cp == '_') || ++ (*cp == ':') || (*cp == ',') || (*cp == '\'') || ++ (*cp == '"')) ++ { ++ continue; ++ } ++ ++ magic = TRUE; ++ } ++ ++ /* ++ * If there were any magic characters used then run the ++ * command using the shell. ++ */ ++ if (magic) ++ { ++ return system(cmd); ++ } ++ ++ /* ++ * No magic characters were in the command, so we can do the fork ++ * and exec ourself. ++ */ ++ pid = fork(); ++ ++ if (pid < 0) ++ { ++ perror("fork failed"); ++ ++ return -1; ++ } ++ ++ /* ++ * If we are the child process, then go execute the program. ++ */ ++ if (pid == 0) ++ childProcess(cmd); ++ ++ /* ++ * We are the parent process. ++ * Wait for the child to complete. ++ */ ++ status = 0; ++ intCrlf = FALSE; ++ ++ while (((pid = waitpid(pid, &status, 0)) < 0) && (errno == EINTR)) ++ ; ++ ++ intCrlf = TRUE; ++ ++ if (pid < 0) ++ { ++ fprintf(stderr, "Error from waitpid: %s", strerror(errno)); ++ ++ return -1; ++ } ++ ++ if (WIFSIGNALED(status)) ++ { ++ fprintf(stderr, "pid %ld: killed by signal %d\n", ++ (long) pid, WTERMSIG(status)); ++ } ++ return WEXITSTATUS(status); ++} ++ ++ ++/* ++ * Here as the child process to try to execute the command. ++ * This is only called if there are no meta-characters in the command. ++ * This procedure never returns. ++ */ ++static void ++childProcess(const char * cmd) ++{ ++ const char ** argv; ++ int argc; ++ ++ /* ++ * Close any extra file descriptors we have opened. ++ */ ++ while (--sourceCount >= 0) ++ { ++ if (sourcefiles[sourceCount] != stdin) ++ fclose(sourcefiles[sourceCount]); ++ } ++ ++ /* ++ * Break the command line up into individual arguments. ++ * If this fails, then run the shell to execute the command. ++ */ ++ if (!makeArgs(cmd, &argc, &argv)) ++ { ++ system(cmd); ++ exit(0); ++ } ++ ++ /* ++ * Try to execute the program directly. ++ */ ++ execvp(argv[0], (char **) argv); ++ ++ /* ++ * The exec failed, so try to run the command using the shell ++ * in case it is a shell script. ++ */ ++ if (errno == ENOEXEC) ++ { ++ system(cmd); ++ exit(0); ++ } ++ ++ /* ++ * There was something else wrong, complain and exit. ++ */ ++ perror(argv[0]); ++ exit(1); ++} ++ ++ ++void ++do_help(int argc, const char ** argv) ++{ ++ const CommandEntry * entry; ++ const char * str; ++ ++ str = NULL; ++ ++ if (argc == 2) ++ str = argv[1]; ++ ++ /* ++ * Check for an exact match, in which case describe the program. ++ */ ++ if (str) ++ { ++ for (entry = commandEntryTable; entry->name; entry++) ++ { ++ if (strcmp(str, entry->name) == 0) ++ { ++ printf("%s\n", entry->description); ++ ++ printf("usage: %s %s\n", entry->name, ++ entry->usage); ++ ++ return; ++ } ++ } ++ } ++ ++ /* ++ * Print short information about commands which contain the ++ * specified word. ++ */ ++ for (entry = commandEntryTable; entry->name; entry++) ++ { ++ if ((str == NULL) || (strstr(entry->name, str) != NULL) || ++ (strstr(entry->usage, str) != NULL)) ++ { ++ printf("%-10s %s\n", entry->name, entry->usage); ++ } ++ } ++} ++ ++ ++void ++do_alias(int argc, const char ** argv) ++{ ++ const char * name; ++ char * value; ++ Alias * alias; ++ int count; ++ char buf[CMD_LEN]; ++ ++ if (argc < 2) ++ { ++ count = aliasCount; ++ ++ for (alias = aliasTable; count-- > 0; alias++) ++ printf("%s\t%s\n", alias->name, alias->value); ++ ++ return; ++ } ++ ++ name = argv[1]; ++ ++ if (argc == 2) ++ { ++ alias = findAlias(name); ++ ++ if (alias) ++ printf("%s\n", alias->value); ++ else ++ fprintf(stderr, "Alias \"%s\" is not defined\n", name); ++ ++ return; ++ } ++ ++ if (strcmp(name, "alias") == 0) ++ { ++ fprintf(stderr, "Cannot alias \"alias\"\n"); ++ ++ return; ++ } ++ ++ if (!makeString(argc - 2, argv + 2, buf, CMD_LEN)) ++ return; ++ ++ value = malloc(strlen(buf) + 1); ++ ++ if (value == NULL) ++ { ++ fprintf(stderr, "No memory for alias value\n"); ++ ++ return; ++ } ++ ++ strcpy(value, buf); ++ ++ alias = findAlias(name); ++ ++ if (alias) ++ { ++ free(alias->value); ++ alias->value = value; ++ ++ return; ++ } ++ ++ if ((aliasCount % ALIAS_ALLOC) == 0) ++ { ++ count = aliasCount + ALIAS_ALLOC; ++ ++ if (aliasTable) ++ { ++ alias = (Alias *) realloc(aliasTable, ++ sizeof(Alias) * count); ++ } ++ else ++ alias = (Alias *) malloc(sizeof(Alias) * count); ++ ++ if (alias == NULL) ++ { ++ free(value); ++ fprintf(stderr, "No memory for alias table\n"); ++ ++ return; ++ } ++ ++ aliasTable = alias; ++ } ++ ++ alias = &aliasTable[aliasCount]; ++ ++ alias->name = malloc(strlen(name) + 1); ++ ++ if (alias->name == NULL) ++ { ++ free(value); ++ fprintf(stderr, "No memory for alias name\n"); ++ ++ return; ++ } ++ ++ strcpy(alias->name, name); ++ alias->value = value; ++ aliasCount++; ++} ++ ++ ++/* ++ * Build aliases for all of the built-in commands which start with a dash, ++ * using the names without the dash. ++ */ ++void ++do_aliasall(int argc, const char **argv) ++{ ++ const CommandEntry * entry; ++ const char * name; ++ const char * newArgv[4]; ++ ++ for (entry = commandEntryTable; entry->name; entry++) ++ { ++ name = entry->name; ++ ++ if (*name != '-') ++ continue; ++ ++ newArgv[0] = "alias"; ++ newArgv[1] = name + 1; ++ newArgv[2] = name; ++ newArgv[3] = NULL; ++ ++ do_alias(3, newArgv); ++ } ++} ++ ++ ++/* ++ * Look up an alias name, and return a pointer to it. ++ * Returns NULL if the name does not exist. ++ */ ++static Alias * ++findAlias(const char * name) ++{ ++ Alias * alias; ++ int count; ++ ++ count = aliasCount; ++ ++ for (alias = aliasTable; count-- > 0; alias++) ++ { ++ if (strcmp(name, alias->name) == 0) ++ return alias; ++ } ++ ++ return NULL; ++} ++ ++ ++void ++do_source(int argc, const char ** argv) ++{ ++ readFile(argv[1]); ++} ++ ++ ++void ++do_exec(int argc, const char ** argv) ++{ ++ const char * name; ++ ++ name = argv[1]; ++ ++ while (--sourceCount >= 0) ++ { ++ if (sourcefiles[sourceCount] != stdin) ++ fclose(sourcefiles[sourceCount]); ++ } ++ ++ argv[argc] = NULL; ++ ++ execvp(name, (char **) argv + 1); ++ perror(name); ++} ++ ++ ++void ++do_prompt(int argc, const char ** argv) ++{ ++ char * cp; ++ char buf[CMD_LEN]; ++ ++ if (!makeString(argc - 1, argv + 1, buf, CMD_LEN)) ++ return; ++ ++ cp = malloc(strlen(buf) + 2); ++ ++ if (cp == NULL) ++ { ++ fprintf(stderr, "No memory for prompt\n"); ++ ++ return; ++ } ++ ++ strcpy(cp, buf); ++ strcat(cp, " "); ++ ++ if (prompt) ++ free(prompt); ++ ++ prompt = cp; ++} ++ ++ ++void ++do_unalias(int argc, const char ** argv) ++{ ++ Alias * alias; ++ ++ while (--argc > 0) ++ { ++ alias = findAlias(*++argv); ++ ++ if (alias == NULL) ++ continue; ++ ++ free(alias->name); ++ free(alias->value); ++ aliasCount--; ++ alias->name = aliasTable[aliasCount].name; ++ alias->value = aliasTable[aliasCount].value; ++ } ++} ++ ++ ++/* ++ * Display the prompt string. ++ */ ++static void ++showPrompt(void) ++{ ++ const char * cp; ++ ++ cp = "> "; ++ ++ if (prompt) ++ cp = prompt; ++ ++ write(STDOUT, cp, strlen(cp)); ++} ++ ++ ++static void ++catchInt(int val) ++{ ++ signal(SIGINT, catchInt); ++ ++ intFlag = TRUE; ++ ++ if (intCrlf) ++ write(STDOUT, "\n", 1); ++} ++ ++ ++static void ++catchQuit(int val) ++{ ++ signal(SIGQUIT, catchQuit); ++ ++ intFlag = TRUE; ++ ++ if (intCrlf) ++ write(STDOUT, "\n", 1); ++} ++ ++ ++/* ++ * Print the usage information and quit. ++ */ ++static void ++usage(void) ++{ ++ fprintf(stderr, "Stand-alone shell (version %s)\n", version); ++ fprintf(stderr, "\n"); ++ fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt] [-i]\n"); ++ ++ exit(1); ++} ++ ++/* END CODE */ diff --git a/debian/patches/e2fslibs_chattr_include b/debian/patches/e2fslibs_chattr_include new file mode 100644 index 0000000..add1ffc --- /dev/null +++ b/debian/patches/e2fslibs_chattr_include @@ -0,0 +1,17 @@ +Subject: Use includes from e2fslibs rather than the kernel +From: Tollef Fog Heen +Bug-Debian: #223203 +Last-updated: 2010-04-04 +Index: sash-3.7/cmd_chattr.c +=================================================================== +--- sash-3.7.orig/cmd_chattr.c 2010-04-04 10:40:52.644957438 +0200 ++++ sash-3.7/cmd_chattr.c 2010-04-04 10:41:11.084974379 +0200 +@@ -12,7 +12,7 @@ + + #include + #include +-#include ++#include + + #include "sash.h" + diff --git a/debian/patches/exit_with_argument b/debian/patches/exit_with_argument new file mode 100644 index 0000000..86e520e --- /dev/null +++ b/debian/patches/exit_with_argument @@ -0,0 +1,44 @@ +Subject: Let exit have an optional argument +From: Tollef Fog Heen +Last-updated: 2010-04-04 +Index: sash-3.7/cmds.c +=================================================================== +--- sash-3.7.orig/cmds.c 2002-07-22 00:28:19.000000000 +0200 ++++ sash-3.7/cmds.c 2010-04-04 10:58:51.604971262 +0200 +@@ -993,14 +993,18 @@ + void + do_exit(int argc, const char ** argv) + { ++ int r = 0; + if (getpid() == 1) + { + fprintf(stderr, "You are the INIT process!\n"); + + return; + } +- +- exit(0); ++ if (argc == 2) ++ { ++ r = atoi(argv[1]); ++ } ++ exit(r); + } + + +Index: sash-3.7/sash.c +=================================================================== +--- sash-3.7.orig/sash.c 2004-01-14 06:08:03.000000000 +0100 ++++ sash-3.7/sash.c 2010-04-04 10:58:51.604971262 +0200 +@@ -132,9 +132,9 @@ + }, + + { +- "exit", do_exit, 1, 1, ++ "exit", do_exit, 1, 2, + "Exit from sash", +- "" ++ "[exit value]" + }, + + { diff --git a/debian/patches/exit_with_command_status b/debian/patches/exit_with_command_status new file mode 100644 index 0000000..89454cc --- /dev/null +++ b/debian/patches/exit_with_command_status @@ -0,0 +1,178 @@ +Index: sash-3.7/sash.c +=================================================================== +--- sash-3.7.orig/sash.c 2010-04-04 14:56:47.964954627 +0200 ++++ sash-3.7/sash.c 2010-04-04 14:57:03.932954934 +0200 +@@ -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 int readFile(const char * name); ++static int command(const char * cmd); + static BOOL tryBuiltIn(const char * cmd); +-static void runCmd(const char * cmd); ++static int runCmd(const char * cmd); + static void childProcess(const char * cmd); + static void showPrompt(void); + static void usage(void); +@@ -524,9 +524,7 @@ + */ + if (singleCommand) + { +- command(singleCommand); +- +- return 0; ++ return command(singleCommand); + } + + /* +@@ -561,9 +559,8 @@ + /* + * Read commands from stdin or from a command file. + */ +- readFile(commandFile); ++ return readFile(commandFile); + +- return 0; + } + + +@@ -571,19 +568,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 +594,7 @@ + { + perror(name); + +- return; ++ return 1; + } + } + +@@ -614,7 +612,7 @@ + fclose(fp); + sourceCount--; + +- return; ++ return 1; + } + + if (fgets(buf, CMD_LEN - 1, fp) == NULL) +@@ -639,7 +637,7 @@ + + buf[cc] = '\0'; + +- command(buf); ++ r = command(buf); + } + + if (ferror(fp)) +@@ -656,6 +654,7 @@ + fclose(fp); + + sourceCount--; ++ return r; + } + + +@@ -664,7 +663,7 @@ + * 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; +@@ -690,7 +689,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 +@@ -726,13 +725,13 @@ + * the command if found. + */ + if (tryBuiltIn(cmd)) +- return; ++ return 0; /* This is a blatant lie */ + + /* + * The command is not a built-in, so run the program along + * the PATH list. + */ +- runCmd(cmd); ++ return runCmd(cmd); + } + + +@@ -809,7 +808,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 +853,7 @@ + */ + if (magic) + { +- system(cmd); +- +- return; ++ return system(cmd); + } + + /* +@@ -869,7 +866,7 @@ + { + perror("fork failed"); + +- return; ++ return -1; + } + + /* +@@ -894,7 +891,7 @@ + { + fprintf(stderr, "Error from waitpid: %s", strerror(errno)); + +- return; ++ return -1; + } + + if (WIFSIGNALED(status)) +@@ -902,6 +899,7 @@ + fprintf(stderr, "pid %ld: killed by signal %d\n", + (long) pid, WTERMSIG(status)); + } ++ return WEXITSTATUS(status); + } + + diff --git a/debian/patches/fix_exec b/debian/patches/fix_exec new file mode 100644 index 0000000..4cec306 --- /dev/null +++ b/debian/patches/fix_exec @@ -0,0 +1,30 @@ +Subject: Don't check permissions before trying to execute a command +From: Unknown +Last-updated: 2010-04-04 +Index: sash-3.7/sash.c +=================================================================== +--- sash-3.7.orig/sash.c 2010-04-04 10:12:57.228978742 +0200 ++++ sash-3.7/sash.c 2010-04-04 10:13:04.008985124 +0200 +@@ -1172,13 +1172,6 @@ + + name = argv[1]; + +- if (access(name, 4)) +- { +- perror(name); +- +- return; +- } +- + while (--sourceCount >= 0) + { + if (sourcefiles[sourceCount] != stdin) +@@ -1188,7 +1181,7 @@ + argv[argc] = NULL; + + execvp(name, (char **) argv + 1); +- exit(1); ++ perror(name); + } + + diff --git a/debian/patches/freebsd_build b/debian/patches/freebsd_build new file mode 100644 index 0000000..b614c10 --- /dev/null +++ b/debian/patches/freebsd_build @@ -0,0 +1,67 @@ +Subject: Build fixes for Debian GNU/kFreeBSD +From: Axel Beckert +Bug-Debian: #565539 +Last-updated: 2010-04-04 +Index: sash-3.7/Makefile +=================================================================== +--- sash-3.7.orig/Makefile 2010-04-04 11:13:36.005953632 +0200 ++++ sash-3.7/Makefile 2010-04-04 11:38:19.300955689 +0200 +@@ -9,9 +9,16 @@ + # + HAVE_GZIP = 1 + HAVE_LINUX_ATTR = 1 ++ifeq (Linux,$(shell uname -s)) + HAVE_LINUX_MOUNT = 1 + HAVE_BSD_MOUNT = 0 + MOUNT_TYPE = '"ext3"' ++endif ++ifeq (kFreeBSD,$(shell uname -s)) ++HAVE_LINUX_MOUNT = 0 ++HAVE_BSD_MOUNT = 1 ++MOUNT_TYPE = '"ufs"' ++endif + + DEFS = -DHAVE_GZIP=$(HAVE_GZIP) \ + -DHAVE_LINUX_ATTR=$(HAVE_LINUX_ATTR) \ +Index: sash-3.7/cmds.c +=================================================================== +--- sash-3.7.orig/cmds.c 2010-04-04 11:13:36.025952857 +0200 ++++ sash-3.7/cmds.c 2010-04-04 11:37:59.160966064 +0200 +@@ -19,6 +19,10 @@ + + #if HAVE_LINUX_MOUNT + #include ++#elif HAVE_BSD_MOUNT ++#include ++#include ++#include + #endif + + +@@ -599,26 +603,16 @@ + #elif HAVE_BSD_MOUNT + { + struct ufs_args ufs; +- struct adosfs_args adosfs; + struct iso_args iso; +- struct mfs_args mfs; + struct msdosfs_args msdosfs; + void * args; + + if(!strcmp(type, "ffs") || !strcmp(type, "ufs")) { + ufs.fspec = (char*) argv[0]; + args = &ufs; +- } else if(!strcmp(type, "adosfs")) { +- adosfs.fspec = (char*) argv[0]; +- adosfs.uid = 0; +- adosfs.gid = 0; +- args = &adosfs; + } else if(!strcmp(type, "cd9660")) { + iso.fspec = (char*) argv[0]; + args = &iso; +- } else if(!strcmp(type, "mfs")) { +- mfs.fspec = (char*) argv[0]; +- args = &mfs; + } else if(!strcmp(type, "msdos")) { + msdosfs.fspec = (char*) argv[0]; + msdosfs.uid = 0; diff --git a/debian/patches/interactive_flag b/debian/patches/interactive_flag new file mode 100644 index 0000000..83d034f --- /dev/null +++ b/debian/patches/interactive_flag @@ -0,0 +1,70 @@ +Subject: Add -i option +From: Michael Meskes +Bug-Debian: #19656 +Last-updated: 2010-04-04 +Index: sash-3.7/sash.c +=================================================================== +--- sash-3.7.orig/sash.c 2010-04-04 10:35:51.268950839 +0200 ++++ sash-3.7/sash.c 2010-04-04 10:36:42.572973204 +0200 +@@ -399,12 +399,14 @@ + const char * commandFile; + BOOL quietFlag; + BOOL aliasFlag; ++ BOOL interactiveFlag; + char buf[PATH_LEN]; + + singleCommand = NULL; + commandFile = NULL; + quietFlag = FALSE; + aliasFlag = FALSE; ++ interactiveFlag = FALSE; + + /* + * Look for options. +@@ -419,11 +421,17 @@ + + while (*cp) switch (*cp++) + { ++ case '-': ++ /* ++ * Ignore. This is so that we can be ++ * run from login. ++ */ ++ break; + case 'c': + /* + * Execute specified command. + */ +- if ((argc != 1) || singleCommand) ++ if ((argc != 1) || singleCommand || interactiveFlag) + usage(); + + singleCommand = *argv++; +@@ -446,6 +454,18 @@ + + break; + ++ case 'i': ++ /* ++ * Be an interactive shell ++ * ..is a no-op, but some contexts require this ++ * ..interactiveFlag is to avoid -ic as a legacy ++ */ ++ if (singleCommand) ++ usage(); ++ ++ interactiveFlag = TRUE; ++ break; ++ + case 'p': + /* + * Set the prompt string. +@@ -1263,7 +1290,7 @@ + { + fprintf(stderr, "Stand-alone shell (version %s)\n", version); + fprintf(stderr, "\n"); +- fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt]\n"); ++ fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt] [-i]\n"); + + exit(1); + } diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..ab43127 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,9 @@ +exit_with_argument +e2fslibs_chattr_include +touch_error_handling +interactive_flag +fix_exec +buildsystem +freebsd_build +exit_with_command_status +debian-changes-3.7-10 diff --git a/debian/patches/touch_error_handling b/debian/patches/touch_error_handling new file mode 100644 index 0000000..d567c2a --- /dev/null +++ b/debian/patches/touch_error_handling @@ -0,0 +1,20 @@ +Subject: Correct error message when touching non-existent file in non-writeable directory +From: Tollef Fog Heen , Raul Miller +Bug-Debian: #43428 +Last-updated: 2010-04-04 +Index: sash-3.7/cmds.c +=================================================================== +--- sash-3.7.orig/cmds.c 2010-04-04 10:58:51.000000000 +0200 ++++ sash-3.7/cmds.c 2010-04-04 11:04:55.185955708 +0200 +@@ -341,6 +341,11 @@ + continue; + } + ++ if (errno != EEXIST) { ++ perror(name); ++ continue; ++ } ++ + if (utime(name, &now) < 0) + perror(name); + } diff --git a/debian/source/format b/debian/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/debian/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/debian/stamp-makefile-build b/debian/stamp-makefile-build new file mode 100644 index 0000000..e69de29 diff --git a/sash.c b/sash.c index 6041bed..ee444a6 100644 --- a/sash.c +++ b/sash.c @@ -132,9 +132,9 @@ static const CommandEntry commandEntryTable[] = }, { - "exit", do_exit, 1, 2, + "exit", do_exit, 1, 1, "Exit from sash", - "[exit value]" + "" }, { @@ -399,14 +399,12 @@ main(int argc, const char ** argv) const char * commandFile; BOOL quietFlag; BOOL aliasFlag; - BOOL interactiveFlag; char buf[PATH_LEN]; singleCommand = NULL; commandFile = NULL; quietFlag = FALSE; aliasFlag = FALSE; - interactiveFlag = FALSE; /* * Look for options. @@ -421,17 +419,11 @@ main(int argc, const char ** argv) while (*cp) switch (*cp++) { - case '-': - /* - * Ignore. This is so that we can be - * run from login. - */ - break; case 'c': /* * Execute specified command. */ - if ((argc != 1) || singleCommand || interactiveFlag) + if ((argc != 1) || singleCommand) usage(); singleCommand = *argv++; @@ -454,18 +446,6 @@ main(int argc, const char ** argv) break; - case 'i': - /* - * Be an interactive shell - * ..is a no-op, but some contexts require this - * ..interactiveFlag is to avoid -ic as a legacy - */ - if (singleCommand) - usage(); - - interactiveFlag = TRUE; - break; - case 'p': /* * Set the prompt string. @@ -1172,6 +1152,13 @@ do_exec(int argc, const char ** argv) name = argv[1]; + if (access(name, 4)) + { + perror(name); + + return; + } + while (--sourceCount >= 0) { if (sourcefiles[sourceCount] != stdin) @@ -1181,7 +1168,7 @@ do_exec(int argc, const char ** argv) argv[argc] = NULL; execvp(name, (char **) argv + 1); - perror(name); + exit(1); } @@ -1283,7 +1270,7 @@ usage(void) { fprintf(stderr, "Stand-alone shell (version %s)\n", version); fprintf(stderr, "\n"); - fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt] [-i]\n"); + fprintf(stderr, "Usage: sash [-a] [-q] [-f fileName] [-c command] [-p prompt]\n"); exit(1); }