--- sash/Makefile +++ sash/Makefile @@ -3,29 +3,36 @@ # # The HAVE_GZIP definition adds the -gzip and -gunzip commands. # The HAVE_EXT2 definition adds the -chattr and -lsattr comamnds. +# The WITH_READLINE definition adds readline support. # -CFLAGS = -O3 -Wall -Wmissing-prototypes -DHAVE_GZIP -DHAVE_EXT2 -LDFLAGS = -static -s -LIBS = -lz +MKDIR = mkdir -p +INSTALL = install -p +CFLAGS = $(RPM_OPT_FLAGS) -D_GNU_SOURCE -DHAVE_GZIP -DHAVE_EXT2 -DWITH_READLINE +LDFLAGS = -static +LIBS = -lz -lreadline -ltinfo -BINDIR = /bin -MANDIR = /usr/man/man1 +sbindir = /sbin +mandir = /usr/share/man +mansubdir = man1 +OBJS = sash.o message.o getline.o utils.o \ + cmds.o cmd_dd.o cmd_ed.o cmd_grep.o cmd_ls.o cmd_tar.o \ + cmd_gzip.o cmd_find.o cmd_file.o cmd_chattr.o cmd_ar.o -OBJS = sash.o cmds.o cmd_dd.o cmd_ed.o cmd_grep.o cmd_ls.o cmd_tar.o \ - cmd_gzip.o cmd_find.o cmd_file.o cmd_chattr.o cmd_ar.o utils.o +TARGET = sash +$(TARGET): $(OBJS) + $(CC) $(LDFLAGS) $(OBJS) $(LIBS) -o $@ -sash: $(OBJS) - $(CC) $(LDFLAGS) -o sash $(OBJS) $(LIBS) +install: $(TARGET) + $(MKDIR) $(sbindir) + $(INSTALL) sash $(sbindir)/sash + $(MKDIR) $(mandir)/$(mansubdir) + $(INSTALL) -m644 sash.1 $(mandir)/$(mansubdir)/sash.1 clean: - rm -f $(OBJS) sash - -install: sash - cp sash $(BINDIR)/sash - cp sash.1 $(MANDIR)/sash.1 + rm -f $(OBJS) $(TARGET) $(OBJS): sash.h --- sash/cmd_ar.c +++ sash/cmd_ar.c @@ -16,14 +16,9 @@ #include #include #include -#include -#include -#include -#include -#include -#include #include +#include "message.h" #include "sash.h" @@ -70,14 +65,14 @@ static int shortNameMatches44BSD(const char * name); static int shortNameMatchesSysV(const char * name); static BOOL wantMember(const Archive * arch, int n_names, - const char ** names); + const char *const *names); static BOOL getNumber(const char * s, unsigned base, int max_digits, unsigned long * ul); void -do_ar(int argc, const char ** argv) +do_ar(int argc, const char *const *argv) { const char * options; const char * archiveName; @@ -94,8 +89,7 @@ do_ar(int argc, const char ** argv) if (argc < 3) { - fprintf(stderr, "Too few arguments for ar\n"); - + errmsg( "ar: too few arguments." ); return; } @@ -135,22 +129,18 @@ do_ar(int argc, const char ** argv) break; case 'd': case 'm': case 'q': case 'r': - fprintf(stderr, "Writing ar files is not supported\n"); - + errmsg( "writing ar files is not supported." ); return; default: - fprintf(stderr, "Unknown ar flag: %c\n", *options); - + errmsg( "ar: unknown flag: %c", *options ); return; } } if (doExtract + doTable + doPrint != 1) { - fprintf(stderr, - "Exactly one of 'x', 'p' or 't' must be specified\n"); - + errmsg( "ar: exactly one of 'x', 'p' or 't' must be specified." ); return; } @@ -230,9 +220,7 @@ do_ar(int argc, const char ** argv) if (close(outfd) == -1) { - fprintf(stderr, "Can't close %s: %s\n", - arch.name, strerror(errno)); - + errmsg( "ar: failed to close %s: %s", arch.name, strerror(errno) ); break; } @@ -241,7 +229,7 @@ do_ar(int argc, const char ** argv) } else { - fprintf(stderr, "Oops -- I don't know what to do\n"); + errmsg( "ar: Oops -- I don't know what to do..." ); break; } } @@ -264,9 +252,7 @@ createFile(const Archive * arch) if (fd == -1) { - fprintf(stderr, "Can't create \"%s\": %s\n", - arch->name, strerror(errno)); - + errmsg( "ar: cannot create \"%s\": %s", arch->name, strerror(errno) ); return -1; } @@ -288,7 +274,7 @@ createFile(const Archive * arch) * file names, or else that the specified list of file names is empty. */ static BOOL -wantMember(const Archive * arch, int n_names, const char ** name) +wantMember(const Archive * arch, int n_names, const char *const *name) { int i; @@ -395,9 +381,7 @@ openArchive(const char * name, Archive * arch) if (arch->fd == -1) { - fprintf(stderr, "Can't open archive file %s: %s\n", - name, strerror(errno)); - + errmsg( "ar: cannot open archive file %s: %s", name, strerror(errno) ); return FALSE; } @@ -405,23 +389,19 @@ openArchive(const char * name, Archive * arch) if (cc == -1) { - fprintf(stderr, "Error reading archive header: %s\n", - strerror(errno)); - + errmsg( "ar: %s: error reading archive header: %s", name, strerror(errno) ); goto close_and_out; } if (cc != SARMAG) { - fprintf(stderr, "Short read of archive header\n"); - + errmsg( "ar: %s: archive header too short", name ); goto close_and_out; } if (memcmp(buf, ARMAG, SARMAG)) { - fprintf(stderr, "Invalid archive header\n"); - + errmsg( "ar: %s: invalid archive header", name ); goto close_and_out; } @@ -472,9 +452,7 @@ readMember(Archive * arch, struct ar_hdr * hdr) if (cc < 0) { - fprintf(stderr, "Error reading member header: %s\n", - strerror(errno)); - + errmsg( "ar: error reading member header: %s", strerror(errno) ); return FALSE; } @@ -487,15 +465,13 @@ readMember(Archive * arch, struct ar_hdr * hdr) if (cc != sizeof(*hdr)) { - fprintf(stderr, "Short read of member header\n"); - + errmsg( "ar: member header too short" ); return FALSE; } if (memcmp(hdr->ar_fmag, ARFMAG, sizeof(hdr->ar_fmag))) { - fprintf(stderr, "Invalid member header\n"); - + errmsg( "ar: invalid member header" ); return FALSE; } @@ -585,7 +561,7 @@ shortNameMatchesSysV(const char * name) arch->name = malloc(n); \ if (!arch->name) \ { \ - fprintf(stderr, "Out of memory\n"); \ + errmsg( "malloc: %s", strerror(errno) ); \ return FALSE; \ } \ } while (0); @@ -631,16 +607,13 @@ canonicalize(Archive * arch, const struct ar_hdr * hdr) if (cc == -1) { - fprintf(stderr, "Error reading longname: %s\n", - strerror(errno)); - + errmsg( "ar: error reading longname: %s", strerror(errno) ); goto free_and_out; } if (cc != n) { - fprintf(stderr, "Unexpected end of file in longname\n"); - + errmsg( "ar: unexpected end of file in longname" ); goto free_and_out; } @@ -663,8 +636,7 @@ canonicalize(Archive * arch, const struct ar_hdr * hdr) if (n >= strlen(arch->nameTable)) { - fprintf(stderr, "Longname index too large\n"); - + errmsg( "ar: longname index too large" ); return FALSE; } @@ -674,15 +646,13 @@ canonicalize(Archive * arch, const struct ar_hdr * hdr) if (!p) { - fprintf(stderr, "Bad longname index\n"); - + errmsg( "ar: invalid longname index" ); return FALSE; } if (p[1] != '\n') { - fprintf(stderr, "Malformed longname table\n"); - + errmsg( "ar: malformed longname table" ); return FALSE; } @@ -724,7 +694,7 @@ canonicalize(Archive * arch, const struct ar_hdr * hdr) #define FIELD(AFIELD, MFIELD, base) \ if (!getNumber(hdr->AFIELD, base, sizeof(hdr->AFIELD), &ul)) \ { \ - fprintf(stderr, "Malformed archive member header\n"); \ + errmsg( "ar: malformed archive member header" ); \ goto free_and_out; \ } \ arch->MFIELD = ul; @@ -790,9 +760,7 @@ skipPadding(int fd, int pad) { if (lseek(fd, 1, SEEK_CUR) == -1) { - fprintf(stderr, "Can't skip pad byte: %s\n", - strerror(errno)); - + errmsg( "ar: cannot skip pad byte: %s", strerror(errno) ); return FALSE; } } @@ -842,8 +810,7 @@ readSpecialMember(Archive * arch) if (!getNumber(hdr.ar_size, 10, sizeof(hdr.ar_size), &len)) { - fprintf(stderr, "Invalid name-table size\n"); - + errmsg( "ar: invalid nameTable size" ); return FALSE; } @@ -851,8 +818,7 @@ readSpecialMember(Archive * arch) if (!arch->nameTable) { - fprintf(stderr, "Out of memory\n"); - + errmsg( "ar: nameTable: %s", strerror(errno) ); return FALSE; } @@ -860,17 +826,13 @@ readSpecialMember(Archive * arch) if (cc == -1) { - fprintf(stderr, "Error reading name-table: %s\n", - strerror(errno)); - + errmsg( "ar: error reading nameTable: %s", strerror(errno) ); return FALSE; } if (cc != (ssize_t) len) { - fprintf(stderr, - "Unexpected end of file in name-table\n"); - + errmsg( "ar: unexpected end of file in nameTable" ); return FALSE; } @@ -932,9 +894,7 @@ skipMember(const Archive * arch) { if (lseek(arch->fd, arch->size, SEEK_CUR) == -1) { - fprintf(stderr, "Can't skip past archive member: %s\n", - strerror(errno)); - + errmsg( "ar: cannot skip past archive member: %s", strerror(errno) ); return FALSE; } @@ -962,23 +922,19 @@ writeFile(const Archive * arch, int outfd) if (cc == -1) { - fprintf(stderr, "Error reading archive member: %s\n", - strerror(errno)); - + errmsg( "ar: error reading archive member: %s", strerror(errno) ); return FALSE; } if (cc == 0) { - fprintf(stderr, "Unexpected end of file\n"); - + errmsg( "ar: unexpected end of file" ); return FALSE; } if (fullWrite(outfd, buf, cc) < 0) { - fprintf(stderr, "Write error: %s\n", strerror(errno)); - + errmsg( "ar: write failure: %s", strerror(errno) ); return FALSE; } --- sash/cmd_chattr.c +++ sash/cmd_chattr.c @@ -12,8 +12,9 @@ #include #include -#include +#include +#include "message.h" #include "sash.h" @@ -22,7 +23,7 @@ * This can turn on or off the immutable and append-only ext2 flags. */ void -do_chattr(int argc, const char ** argv) +do_chattr(int argc, const char *const *argv) { const char * fileName; const char * options; @@ -71,9 +72,7 @@ do_chattr(int argc, const char ** argv) break; default: - fprintf(stderr, "Unknown flag '%c'\n", - options[-1]); - + errmsg( "chattr: unknown flag: %c", options[-1] ); return; } } @@ -84,15 +83,13 @@ do_chattr(int argc, const char ** argv) */ if ((onFlags == 0) && (offFlags == 0)) { - fprintf(stderr, "No attributes specified\n"); - + errmsg( "chattr: no attributes specified" ); return; } if ((onFlags & offFlags) != 0) { - fprintf(stderr, "Inconsistent attributes specified\n"); - + errmsg( "chattr: inconsistent attributes specified" ); return; } @@ -101,8 +98,7 @@ do_chattr(int argc, const char ** argv) */ if (argc <= 0) { - fprintf(stderr, "No files specified for setting attributes\n"); - + errmsg( "chattr: no files specified for setting attributes" ); return; } @@ -120,8 +116,7 @@ do_chattr(int argc, const char ** argv) if (fd < 0) { - perror(fileName); - + errmsg( "chattr: %s: %s", fileName, strerror(errno) ); continue; } @@ -130,10 +125,8 @@ do_chattr(int argc, const char ** argv) */ if (ioctl(fd, EXT2_IOC_GETFLAGS, &oldFlags) < 0) { - perror(fileName); - - (void) close(fd); - + errmsg( "chattr: %s: %s", fileName, strerror(errno) ); + close(fd); continue; } @@ -160,10 +153,8 @@ do_chattr(int argc, const char ** argv) */ if (ioctl(fd, EXT2_IOC_SETFLAGS, &newFlags) < 0) { - perror(fileName); - + errmsg( "chattr: %s: %s", fileName, strerror(errno) ); (void) close(fd); - continue; } @@ -180,7 +171,7 @@ do_chattr(int argc, const char ** argv) * This lists the immutable and append-only ext2 flags. */ void -do_lsattr(int argc, const char ** argv) +do_lsattr(int argc, const char *const *argv) { const char * fileName; int fd; @@ -205,8 +196,7 @@ do_lsattr(int argc, const char ** argv) if (fd < 0) { - perror(fileName); - + errmsg( "lsattr: %s: %s", fileName, strerror(errno) ); continue; } @@ -222,8 +212,7 @@ do_lsattr(int argc, const char ** argv) if (status < 0) { - perror(fileName); - + errmsg( "lsattr: %s: %s", fileName, strerror(errno) ); continue; } --- sash/cmd_dd.c +++ sash/cmd_dd.c @@ -6,6 +6,7 @@ * The "dd" built-in command. */ +#include "message.h" #include "sash.h" @@ -41,7 +42,7 @@ static long getNum(const char * cp); void -do_dd(int argc, const char ** argv) +do_dd(int argc, const char *const *argv) { const char * str; const PARAM * par; @@ -73,10 +74,9 @@ do_dd(int argc, const char ** argv) str = *++argv; cp = strchr(str, '='); - if (cp == NULL) + if ( !cp ) { - fprintf(stderr, "Bad dd argument\n"); - + errmsg( "dd: invalid argument" ); return; } @@ -93,8 +93,7 @@ do_dd(int argc, const char ** argv) case PAR_IF: if (inFile) { - fprintf(stderr, "Multiple input files illegal\n"); - + errmsg( "dd: multiple input files illegal" ); return; } @@ -104,8 +103,7 @@ do_dd(int argc, const char ** argv) case PAR_OF: if (outFile) { - fprintf(stderr, "Multiple output files illegal\n"); - + errmsg( "dd: multiple output files illegal" ); return; } @@ -117,8 +115,7 @@ do_dd(int argc, const char ** argv) if (blockSize <= 0) { - fprintf(stderr, "Bad block size value\n"); - + errmsg( "dd: bad block size value" ); return; } @@ -129,8 +126,7 @@ do_dd(int argc, const char ** argv) if (count < 0) { - fprintf(stderr, "Bad count value\n"); - + errmsg( "dd: bad count value" ); return; } @@ -141,8 +137,7 @@ do_dd(int argc, const char ** argv) if (seekVal < 0) { - fprintf(stderr, "Bad seek value\n"); - + errmsg( "dd: bad seek value" ); return; } @@ -153,31 +148,27 @@ do_dd(int argc, const char ** argv) if (skipVal < 0) { - fprintf(stderr, "Bad skip value\n"); - + errmsg( "dd: bad skip value" ); return; } break; default: - fprintf(stderr, "Unknown dd parameter\n"); - + errmsg( "dd: unknown parameter" ); return; } } - if (inFile == NULL) + if ( !inFile ) { - fprintf(stderr, "No input file specified\n"); - + errmsg( "dd: no input file specified" ); return; } - if (outFile == NULL) + if ( !outFile ) { - fprintf(stderr, "No output file specified\n"); - + errmsg( "dd: no output file specified" ); return; } @@ -185,12 +176,11 @@ do_dd(int argc, const char ** argv) if (blockSize > sizeof(localBuf)) { - buf = malloc(blockSize); + buf = alloca(blockSize); - if (buf == NULL) + if ( !buf ) { - fprintf(stderr, "Cannot allocate buffer\n"); - + errmsg( "dd: buffer allocation failure: %s", strerror(errno) ); return; } } @@ -202,11 +192,7 @@ do_dd(int argc, const char ** argv) if (inFd < 0) { - perror(inFile); - - if (buf != localBuf) - free(buf); - + errmsg( "dd: error opening %s: %s", inFile, strerror(errno) ); return; } @@ -214,12 +200,9 @@ do_dd(int argc, const char ** argv) if (outFd < 0) { - perror(outFile); + errmsg( "dd: error opening %s: %s", outFile, strerror(errno) ); close(inFd); - if (buf != localBuf) - free(buf); - return; } @@ -233,13 +216,13 @@ do_dd(int argc, const char ** argv) if (inCc < 0) { - perror(inFile); + errmsg( "dd: error reading %s while skipping: %s", inFile, strerror(errno) ); goto cleanup; } if (inCc == 0) { - fprintf(stderr, "End of file while skipping\n"); + errmsg( "dd: %s: unexpected end of file while skipping", inFile ); goto cleanup; } } @@ -250,8 +233,7 @@ do_dd(int argc, const char ** argv) { if (lseek(outFd, seekVal * blockSize, 0) < 0) { - perror(outFile); - + errmsg( "dd: error seeking %s: %s", outFile, strerror(errno) ); goto cleanup; } } @@ -263,7 +245,7 @@ do_dd(int argc, const char ** argv) if (intFlag) { - fprintf(stderr, "Interrupted\n"); + errmsg( "dd: interrupted" ); goto cleanup; } @@ -273,7 +255,7 @@ do_dd(int argc, const char ** argv) if (outCc < 0) { - perror(outFile); + errmsg( "dd: error writing %s: %s", outFile, strerror(errno) ); goto cleanup; } @@ -284,22 +266,23 @@ do_dd(int argc, const char ** argv) } if (inCc < 0) - perror(inFile); + errmsg( "dd: error reading %s: %s", inFile, strerror(errno) ); cleanup: - close(inFd); + if ( close(inFd) < 0 ) + errmsg( "dd: error closing %s: %s", inFile, strerror(errno) ); if (close(outFd) < 0) - perror(outFile); - - if (buf != localBuf) - free(buf); + errmsg( "dd: error closing %s: %s", outFile, strerror(errno) ); - printf("%ld+%d records in\n", intotal / blockSize, - (intotal % blockSize) != 0); + if ( intotal || outTotal ) + { + printf("%ld+%d records in\n", intotal / blockSize, + (intotal % blockSize) != 0); - printf("%ld+%d records out\n", outTotal / blockSize, - (outTotal % blockSize) != 0); + printf("%ld+%d records out\n", outTotal / blockSize, + (outTotal % blockSize) != 0); + } } --- sash/cmd_ed.c +++ sash/cmd_ed.c @@ -6,6 +6,7 @@ * The "ed" built-in command (much simplified) */ +#include "message.h" #include "sash.h" #define USERSIZE 1024 /* max line length typed in by user */ @@ -43,7 +44,7 @@ static LEN bufSize; static void doCommands(void); static void subCommand(const char * cmd, NUM num1, NUM num2); -static BOOL getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum); +static BOOL getNum(const char **retcp, BOOL * retHaveNum, NUM * retNum); static BOOL setCurNum(NUM num); static BOOL initEdit(void); static void termEdit(void); @@ -61,7 +62,7 @@ static LEN findString void -do_ed(int argc, const char ** argv) +do_ed(int argc, const char *const *argv) { if (!initEdit()) return; @@ -70,18 +71,16 @@ do_ed(int argc, const char ** argv) { fileName = strdup(argv[1]); - if (fileName == NULL) + if ( !fileName ) { - fprintf(stderr, "No memory\n"); + errmsg( "ed: %s", strerror(errno) ); termEdit(); - return; } if (!readLines(fileName, 1)) { termEdit(); - return; } @@ -119,7 +118,7 @@ doCommands(void) printf(": "); fflush(stdout); - if (fgets(buf, sizeof(buf), stdin) == NULL) + if ( !fgets(buf, sizeof(buf), stdin) ) return; len = strlen(buf); @@ -131,7 +130,7 @@ doCommands(void) if (*endbuf != '\n') { - fprintf(stderr, "Command line too long\n"); + errmsg( "ed: command line too long" ); do { @@ -208,7 +207,7 @@ doCommands(void) case 'f': if (*cp && !isBlank(*cp)) { - fprintf(stderr, "Bad file command\n"); + errmsg( "ed: bad file command" ); break; } @@ -227,9 +226,9 @@ doCommands(void) newname = strdup(cp); - if (newname == NULL) + if ( !newname ) { - fprintf(stderr, "No memory for file name\n"); + errmsg( "ed: file name allocation failure: %s", strerror(errno) ); break; } @@ -249,7 +248,7 @@ doCommands(void) if ((*cp < 'a') || (*cp > 'a') || cp[1]) { - fprintf(stderr, "Bad mark name\n"); + errmsg( "ed: bad mark name" ); break; } @@ -270,7 +269,7 @@ doCommands(void) if (have1 || *cp) { - fprintf(stderr, "Bad quit command\n"); + errmsg( "ed: bad quit command" ); break; } @@ -295,16 +294,16 @@ doCommands(void) case 'r': if (*cp && !isBlank(*cp)) { - fprintf(stderr, "Bad read command\n"); + errmsg( "ed: bad read command" ); break; } while (isBlank(*cp)) cp++; - if (*cp == '\0') + if ( !*cp ) { - fprintf(stderr, "No file name\n"); + errmsg( "ed: no file name specified" ); break; } @@ -314,7 +313,7 @@ doCommands(void) if (readLines(cp, num1 + 1)) break; - if (fileName == NULL) + if ( !fileName ) fileName = strdup(cp); break; @@ -326,7 +325,7 @@ doCommands(void) case 'w': if (*cp && !isBlank(*cp)) { - fprintf(stderr, "Bad write command\n"); + errmsg( "ed: bad write command" ); break; } @@ -341,9 +340,9 @@ doCommands(void) if (*cp == '\0') cp = fileName; - if (cp == NULL) + if ( !cp ) { - fprintf(stderr, "No file name specified\n"); + errmsg( "ed: no file name specified"); break; } @@ -368,7 +367,7 @@ doCommands(void) case '.': if (have1) { - fprintf(stderr, "No arguments allowed\n"); + errmsg( "ed: no arguments allowed" ); break; } @@ -398,7 +397,7 @@ doCommands(void) break; default: - fprintf(stderr, "Unimplemented command\n"); + errmsg( "ed: command not implemented" ); break; } } @@ -430,8 +429,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { - fprintf(stderr, "Bad line range for substitute\n"); - + errmsg( "ed: bad line range for substitution" ); return; } @@ -448,8 +446,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) if (isBlank(*cp) || (*cp == '\0')) { - fprintf(stderr, "Bad delimiter for substitute\n"); - + errmsg( "ed: bad delimiter for substitution" ); return; } @@ -458,10 +455,9 @@ subCommand(const char * cmd, NUM num1, NUM num2) cp = strchr(cp, delim); - if (cp == NULL) + if ( !cp ) { - fprintf(stderr, "Missing 2nd delimiter for substitute\n"); - + errmsg( "ed: missing 2nd delimiter for substitution" ); return; } @@ -486,8 +482,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) break; default: - fprintf(stderr, "Unknown option for substitute\n"); - + errmsg( "ed: unknown option for substitution" ); return; } @@ -495,7 +490,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) { if (searchString[0] == '\0') { - fprintf(stderr, "No previous search string\n"); + errmsg( "ed: no previous search string" ); return; } @@ -508,7 +503,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) lp = findLine(num1); - if (lp == NULL) + if ( !lp ) return; oldLen = strlen(oldStr); @@ -581,10 +576,9 @@ subCommand(const char * cmd, NUM num1, NUM num2) */ nlp = (LINE *) malloc(sizeof(LINE) + lp->len + deltaLen); - if (nlp == NULL) + if ( !nlp ) { - fprintf(stderr, "Cannot get memory for line\n"); - + errmsg( "ed: cannot allocate line: %s", strerror(errno) ); return; } @@ -625,7 +619,7 @@ subCommand(const char * cmd, NUM num1, NUM num2) } if (!didSub) - fprintf(stderr, "No substitutions found for \"%s\"\n", oldStr); + errmsg( "ed: no substitutions found for \"%s\"", oldStr ); } @@ -647,7 +641,7 @@ findString( const LINE * lp, const char * str, LEN len, LEN offset) { ncp = memchr(cp, *str, left); - if (ncp == NULL) + if ( !ncp ) return -1; left -= (ncp - cp); @@ -692,7 +686,7 @@ addLines(NUM num) if (buf[len - 1] != '\n') { - fprintf(stderr, "Line too long\n"); + errmsg( "ed: line too long" ); do { @@ -718,7 +712,7 @@ addLines(NUM num) * The character pointer which stopped the scan is also returned. */ static BOOL -getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum) +getNum(const char **retcp, BOOL * retHaveNum, NUM * retNum) { const char * cp; char * endStr; @@ -757,7 +751,7 @@ getNum(const char ** retcp, BOOL * retHaveNum, NUM * retNum) if ((*cp < 'a') || (*cp > 'z')) { - fprintf(stderr, "Bad mark name\n"); + errmsg( "ed: bad mark name" ); return FALSE; } @@ -844,10 +838,9 @@ initEdit(void) bufSize = INITBUF_SIZE; bufBase = malloc(bufSize); - if (bufBase == NULL) + if ( !bufBase ) { - fprintf(stderr, "No memory for buffer\n"); - + errmsg( "ed: buffer allocation failure: %s", strerror(errno) ); return FALSE; } @@ -917,8 +910,7 @@ readLines(const char * file, NUM num) if ((num < 1) || (num > lastNum + 1)) { - fprintf(stderr, "Bad line for read\n"); - + errmsg( "ed: bad line for read" ); return FALSE; } @@ -926,8 +918,7 @@ readLines(const char * file, NUM num) if (fd < 0) { - perror(file); - + errmsg( "ed: error opening %s: %s", file, strerror(errno) ); return FALSE; } @@ -982,11 +973,10 @@ readLines(const char * file, NUM num) len = (bufSize * 3) / 2; cp = realloc(bufBase, len); - if (cp == NULL) + if ( !cp ) { - fprintf(stderr, "No memory for buffer\n"); + errmsg( "ed: buffer allocation failure: %s", strerror(errno) ); close(fd); - return FALSE; } @@ -1004,9 +994,8 @@ readLines(const char * file, NUM num) if (cc < 0) { - perror(file); + errmsg( "ed: error reading %s: %s", file, strerror(errno) ); close(fd); - return FALSE; } @@ -1046,7 +1035,7 @@ writeLines(const char * file, NUM num1, NUM num2) if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { - fprintf(stderr, "Bad line range for write\n"); + errmsg( "ed: bad line range for write" ); return FALSE; } @@ -1057,8 +1046,7 @@ writeLines(const char * file, NUM num1, NUM num2) fd = creat(file, 0666); if (fd < 0) { - perror(file); - + errmsg( "ed: error creating %s: %s", file, strerror(errno) ); return FALSE; } @@ -1067,10 +1055,9 @@ writeLines(const char * file, NUM num1, NUM num2) lp = findLine(num1); - if (lp == NULL) + if ( !lp ) { close(fd); - return FALSE; } @@ -1078,9 +1065,8 @@ writeLines(const char * file, NUM num1, NUM num2) { if (write(fd, lp->data, lp->len) != lp->len) { - perror(file); + errmsg( "ed: error writing %s: %s", file, strerror(errno) ); close(fd); - return FALSE; } @@ -1091,8 +1077,7 @@ writeLines(const char * file, NUM num1, NUM num2) if (close(fd) < 0) { - perror(file); - + errmsg( "ed: error closing %s: %s", file, strerror(errno) ); return FALSE; } @@ -1118,14 +1103,13 @@ printLines(NUM num1, NUM num2, BOOL expandFlag) if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { - fprintf(stderr, "Bad line range for print\n"); - + errmsg( "ed: bad line range for print" ); return FALSE; } lp = findLine(num1); - if (lp == NULL) + if ( !lp ) return FALSE; while (!intFlag && (num1 <= num2)) @@ -1199,17 +1183,15 @@ insertLine(NUM num, const char * data, LEN len) if ((num < 1) || (num > lastNum + 1)) { - fprintf(stderr, "Inserting at bad line number\n"); - + errmsg( "ed: inserting at bad line number" ); return FALSE; } newLp = (LINE *) malloc(sizeof(LINE) + len - 1); - if (newLp == NULL) + if ( !newLp ) { - fprintf(stderr, "Failed to allocate memory for line\n"); - + errmsg( "ed: line allocation failure: %s", strerror(errno) ); return FALSE; } @@ -1222,7 +1204,7 @@ insertLine(NUM num, const char * data, LEN len) { lp = findLine(num); - if (lp == NULL) + if ( !lp ) { free((char *) newLp); @@ -1255,14 +1237,13 @@ deleteLines(NUM num1, NUM num2) if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { - fprintf(stderr, "Bad line numbers for delete\n"); - + errmsg( "ed: bad line numbers for delete" ); return FALSE; } lp = findLine(num1); - if (lp == NULL) + if ( !lp ) return FALSE; if ((curNum >= num1) && (curNum <= num2)) @@ -1316,7 +1297,7 @@ searchLines(const char * str, NUM num1, NUM num2) if ((num1 < 1) || (num2 > lastNum) || (num1 > num2)) { - fprintf(stderr, "Bad line numbers for search\n"); + errmsg( "ed: bad line numbers for search" ); return 0; } @@ -1325,7 +1306,7 @@ searchLines(const char * str, NUM num1, NUM num2) { if (searchString[0] == '\0') { - fprintf(stderr, "No previous search string\n"); + errmsg( "ed: no previous search string" ); return 0; } @@ -1340,7 +1321,7 @@ searchLines(const char * str, NUM num1, NUM num2) lp = findLine(num1); - if (lp == NULL) + if ( !lp ) return 0; while (num1 <= num2) @@ -1352,8 +1333,7 @@ searchLines(const char * str, NUM num1, NUM num2) lp = lp->next; } - fprintf(stderr, "Cannot find string \"%s\"\n", str); - + errmsg( "ed: cannot find string \"%s\"", str ); return 0; } @@ -1369,8 +1349,7 @@ findLine(NUM num) if ((num < 1) || (num > lastNum)) { - fprintf(stderr, "Line number %d does not exist\n", num); - + errmsg( "ed: line number %d does not exist", num ); return NULL; } @@ -1424,7 +1403,7 @@ setCurNum(NUM num) lp = findLine(num); - if (lp == NULL) + if ( !lp ) return FALSE; curNum = num; --- sash/cmd_file.c +++ sash/cmd_file.c @@ -6,11 +6,10 @@ * The "file" built-in command. */ -#include -#include #include #include +#include "message.h" #include "sash.h" @@ -18,7 +17,7 @@ static const char * checkFile(const char * name); void -do_file(int argc, const char ** argv) +do_file(int argc, const char *const *argv) { const char * name; const char * info; --- sash/cmd_find.c +++ sash/cmd_find.c @@ -9,18 +9,11 @@ #include #include #include -#include +#include "message.h" #include "sash.h" -#ifdef S_ISLNK -#define LSTAT lstat -#else -#define LSTAT stat -#endif - - #define MAX_NAME_SIZE (1024 * 10) @@ -47,7 +40,7 @@ static BOOL testFile(const char * fullName, const struct stat * statBuf); * This is limited to just printing their file names. */ void -do_find(int argc, const char ** argv) +do_find(int argc, const char *const *argv) { const char * cp; const char * path; @@ -63,8 +56,7 @@ do_find(int argc, const char ** argv) if ((argc <= 0) || (**argv == '-')) { - fprintf(stderr, "No path specified\n"); - + errmsg( "find: no path specified" ); return; } @@ -82,7 +74,7 @@ do_find(int argc, const char ** argv) { if ((argc <= 0) || (**argv == '-')) { - fprintf(stderr, "Missing type string\n"); + errmsg( "find: missing type string" ); return; } @@ -94,7 +86,7 @@ do_find(int argc, const char ** argv) { if ((argc <= 0) || (**argv == '-')) { - fprintf(stderr, "Missing file name\n"); + errmsg( "find: missing file name" ); return; } @@ -106,7 +98,7 @@ do_find(int argc, const char ** argv) { if ((argc <= 0) || (**argv == '-')) { - fprintf(stderr, "Missing file size\n"); + errmsg( "find: missing file size" ); return; } @@ -121,7 +113,7 @@ do_find(int argc, const char ** argv) if (*cp || (fileSize < 0)) { - fprintf(stderr, "Bad file size specified\n"); + errmsg( "find: bad file size specified" ); return; } @@ -129,9 +121,9 @@ do_find(int argc, const char ** argv) else { if (*cp != '-') - fprintf(stderr, "Missing dash in option\n"); + errmsg( "find: missing dash in option" ); else - fprintf(stderr, "Unknown option\n"); + errmsg( "find: unknown option" ); return; } @@ -143,16 +135,13 @@ do_find(int argc, const char ** argv) */ if (stat(path, &statBuf) < 0) { - fprintf(stderr, "Cannot stat \"%s\": %s\n", path, - strerror(errno)); - + errmsg( "find: cannot stat \"%s\": %s", path, strerror(errno) ); return; } if (!S_ISDIR(statBuf.st_mode)) { - fprintf(stderr, "Path \"%s\" is not a directory\n", path); - + errmsg( "find: path \"%s\" is not a directory", path ); return; } @@ -191,11 +180,9 @@ examineDirectory(const char * path) */ dir = opendir(path); - if (dir == NULL) + if ( !dir ) { - fprintf(stderr, "Cannot read directory \"%s\": %s\n", - path, strerror(errno)); - + errmsg( "find: cannot read directory \"%s\": %s", path, strerror(errno) ); return; } @@ -229,11 +216,9 @@ examineDirectory(const char * path) /* * Find out about this file. */ - if (LSTAT(fullName, &statBuf) < 0) + if (lstat(fullName, &statBuf) < 0) { - fprintf(stderr, "Cannot stat \"%s\": %s\n", - fullName, strerror(errno)); - + errmsg( "find: cannot stat \"%s\": %s", fullName, strerror(errno) ); continue; } --- sash/cmd_grep.c +++ sash/cmd_grep.c @@ -6,8 +6,7 @@ * The "grep" built-in command. */ -#include - +#include "message.h" #include "sash.h" @@ -16,7 +15,7 @@ static BOOL search void -do_grep(int argc, const char ** argv) +do_grep(int argc, const char *const *argv) { FILE * fp; const char * word; @@ -50,8 +49,7 @@ do_grep(int argc, const char ** argv) break; default: - fprintf(stderr, "Unknown option\n"); - + errmsg( "grep: unknown option: -%c", *cp ); return; } } @@ -67,10 +65,9 @@ do_grep(int argc, const char ** argv) fp = fopen(name, "r"); - if (fp == NULL) + if ( !fp ) { - perror(name); - + errmsg( "grep: error opening %s: %s", name, strerror(errno) ); continue; } @@ -81,7 +78,6 @@ do_grep(int argc, const char ** argv) if (intFlag) { fclose(fp); - return; } @@ -90,7 +86,7 @@ do_grep(int argc, const char ** argv) cp = &buf[strlen(buf) - 1]; if (*cp != '\n') - fprintf(stderr, "%s: Line too long\n", name); + errmsg( "grep: %s: line too long", name ); if (search(buf, word, ignoreCase)) { @@ -105,7 +101,7 @@ do_grep(int argc, const char ** argv) } if (ferror(fp)) - perror(name); + errmsg( "grep: error reading %s: %s", name, strerror(errno) ); fclose(fp); } --- sash/cmd_gzip.c +++ sash/cmd_gzip.c @@ -16,6 +16,7 @@ #include #include +#include "message.h" #include "sash.h" @@ -63,7 +64,7 @@ static const char * convertName void -do_gzip(int argc, const char ** argv) +do_gzip(int argc, const char *const *argv) { const char * outPath; const char * inFile; @@ -94,10 +95,10 @@ do_gzip(int argc, const char ** argv) { if (argv[i][0] == '-') { - if (strcmp(argv[i], "-o") == 0) - fprintf(stderr, "Illegal use of -o\n"); + if ( !strcmp(argv[i], "-o") ) + errmsg( "gzip: illegal use of -o" ); else - fprintf(stderr, "Illegal option\n"); + errmsg( "gzip: illegal option" ); return; } @@ -108,7 +109,7 @@ do_gzip(int argc, const char ** argv) * the input files in place using their full paths. The input * file names are then deleted. */ - if (outPath == NULL) + if ( !outPath ) { while (!intFlag && (argc-- > 0)) { @@ -128,8 +129,7 @@ do_gzip(int argc, const char ** argv) */ if (unlink(inFile) < 0) { - fprintf(stderr, "%s: %s\n", inFile, - "Compressed ok but unlink failed"); + errmsg( "gzip: %s: %s", inFile, "compressed ok but unlink failed" ); } } @@ -147,7 +147,7 @@ do_gzip(int argc, const char ** argv) if (argc == 1) (void) gzip(*argv, outPath); else - fprintf(stderr, "Exactly one input file is required\n"); + errmsg( "gzip: exactly one input file is required" ); return; } @@ -193,7 +193,7 @@ do_gzip(int argc, const char ** argv) void -do_gunzip(int argc, const char ** argv) +do_gunzip(int argc, const char *const *argv) { const char * outPath; const char * inFile; @@ -225,9 +225,9 @@ do_gunzip(int argc, const char ** argv) if (argv[i][0] == '-') { if (strcmp(argv[i], "-o") == 0) - fprintf(stderr, "Illegal use of -o\n"); + errmsg( "gunzip: illegal use of -o" ); else - fprintf(stderr, "Illegal option\n"); + errmsg( "gunzip: illegal option" ); return; } @@ -249,9 +249,7 @@ do_gunzip(int argc, const char ** argv) if (inFile == outFile) { - fprintf(stderr, "%s: %s\n", inFile, - "missing compression extension"); - + errmsg( "gunzip: %s: %s", inFile, "missing compression suffix" ); continue; } @@ -267,8 +265,7 @@ do_gunzip(int argc, const char ** argv) */ if (unlink(inFile) < 0) { - fprintf(stderr, "%s: %s\n", inFile, - "Uncompressed ok but unlink failed"); + errmsg( "gunzip: %s: %s", inFile, "uncompressed ok but unlink failed" ); } } @@ -298,7 +295,7 @@ do_gunzip(int argc, const char ** argv) if (argc == 1) (void) gunzip(*argv, outPath); else - fprintf(stderr, "Exactly one input file is required\n"); + errmsg( "gunzip: exactly one input file is required" ); return; } @@ -367,8 +364,7 @@ gzip(const char * inputFileName, const char * outputFileName) */ if (stat(inputFileName, &statBuf1) < 0) { - perror(inputFileName); - + errmsg( "gzip: %s: %s", inputFileName, strerror(errno) ); return FALSE; } @@ -381,10 +377,7 @@ gzip(const char * inputFileName, const char * outputFileName) if ((statBuf1.st_dev == statBuf2.st_dev) && (statBuf1.st_ino == statBuf2.st_ino)) { - fprintf(stderr, - "Cannot compress file \"%s\" on top of itself\n", - inputFileName); - + errmsg( "gzip: cannot compress file \"%s\" on top of itself", inputFileName ); return FALSE; } @@ -395,8 +388,7 @@ gzip(const char * inputFileName, const char * outputFileName) if (inFD < 0) { - perror(inputFileName); - + errmsg( "gzip: error opening %s: %s", inputFileName, strerror(errno) ); goto failed; } @@ -407,8 +399,7 @@ gzip(const char * inputFileName, const char * outputFileName) if (outGZ == NULL) { - fprintf(stderr, "%s: gzopen failed\n", outputFileName); - + errmsg( "gzip: %s: gzopen failure: %s", outputFileName, strerror(errno) ); goto failed; } @@ -420,9 +411,7 @@ gzip(const char * inputFileName, const char * outputFileName) { if (gzwrite(outGZ, buf, len) != len) { - fprintf(stderr, "%s: %s\n", inputFileName, - gzerror(outGZ, &err)); - + errmsg( "gzip: error writing %s: %s", outputFileName, gzerror(outGZ, &err) ); goto failed; } @@ -432,8 +421,7 @@ gzip(const char * inputFileName, const char * outputFileName) if (len < 0) { - perror(inputFileName); - + errmsg( "gzip: error reading %s: %s", inputFileName, strerror(errno) ); goto failed; } @@ -442,8 +430,7 @@ gzip(const char * inputFileName, const char * outputFileName) */ if (close(inFD)) { - perror(inputFileName); - + errmsg( "gzip: error closing %s: %s", inputFileName, strerror(errno) ); goto failed; } @@ -451,8 +438,7 @@ gzip(const char * inputFileName, const char * outputFileName) if (gzclose(outGZ) != Z_OK) { - fprintf(stderr, "%s: gzclose failed\n", outputFileName); - + errmsg( "gzip: %s: gzclose failure: %s", outputFileName, gzerror(outGZ, &err) ); goto failed; } @@ -502,8 +488,7 @@ gunzip(const char * inputFileName, const char * outputFileName) */ if (stat(inputFileName, &statBuf1) < 0) { - perror(inputFileName); - + errmsg( "gunzip: %s: %s", inputFileName, strerror(errno) ); return FALSE; } @@ -516,10 +501,7 @@ gunzip(const char * inputFileName, const char * outputFileName) if ((statBuf1.st_dev == statBuf2.st_dev) && (statBuf1.st_ino == statBuf2.st_ino)) { - fprintf(stderr, - "Cannot uncompress file \"%s\" on top of itself\n", - inputFileName); - + errmsg( "gunzip: cannot uncompress file \"%s\" on top of itself", inputFileName ); return FALSE; } @@ -528,10 +510,9 @@ gunzip(const char * inputFileName, const char * outputFileName) */ inGZ = gzopen(inputFileName, "rb"); - if (inGZ == NULL) + if ( !inGZ ) { - fprintf(stderr, "%s: gzopen failed\n", inputFileName); - + errmsg( "gunzip: %s: gzopen failure: %s", inputFileName, strerror(errno) ); return FALSE; } @@ -545,8 +526,7 @@ gunzip(const char * inputFileName, const char * outputFileName) if (outFD < 0) { - perror(outputFileName); - + errmsg( "gunzip: error opening %s: %s", outputFileName, strerror(errno) ); goto failed; } @@ -558,8 +538,7 @@ gunzip(const char * inputFileName, const char * outputFileName) { if (fullWrite(outFD, buf, len) < 0) { - perror(outputFileName); - + errmsg( "gunzip: error writing %s: %s", outputFileName, strerror(errno) ); goto failed; } @@ -569,9 +548,7 @@ gunzip(const char * inputFileName, const char * outputFileName) if (len < 0) { - fprintf(stderr, "%s: %s\n", inputFileName, - gzerror(inGZ, &err)); - + errmsg( "gunzip: error reading %s: %s", inputFileName, gzerror(inGZ, &err) ); goto failed; } @@ -580,8 +557,7 @@ gunzip(const char * inputFileName, const char * outputFileName) */ if (close(outFD)) { - perror(outputFileName); - + errmsg( "gunzip: error closing %s: %s", outputFileName, strerror(errno) ); goto failed; } @@ -589,8 +565,7 @@ gunzip(const char * inputFileName, const char * outputFileName) if (gzclose(inGZ) != Z_OK) { - fprintf(stderr, "%s: gzclose failed\n", inputFileName); - + errmsg( "gunzip: %s: gzclose failure: %s", inputFileName, gzerror(inGZ, &err) ); goto failed; } --- sash/cmd_ls.c +++ sash/cmd_ls.c @@ -6,23 +6,17 @@ * The "ls" built-in command. */ -#include "sash.h" - #include #include #include #include #include - -#define LISTSIZE 8192 +#include "message.h" +#include "sash.h" -#ifdef S_ISLNK -#define LSTAT lstat -#else -#define LSTAT stat -#endif +#define LISTSIZE 8192 /* @@ -60,7 +54,7 @@ static void clearListNames(void); void -do_ls(int argc, const char ** argv) +do_ls(int argc, const char *const *argv) { const char * cp; const char * name; @@ -73,7 +67,7 @@ do_ls(int argc, const char ** argv) char fullName[PATH_LEN]; struct stat statBuf; - static const char * def[] = {"."}; + static const char *const def[] = {"."}; /* * Reset for a new listing run. @@ -103,7 +97,7 @@ do_ls(int argc, const char ** argv) case 'C': flags |= LSF_COLUMN; break; default: - fprintf(stderr, "Unknown option -%c\n", cp[-1]); + errmsg( "ls: unknown option -%c", cp[-1] ); return; } @@ -177,10 +171,9 @@ do_ls(int argc, const char ** argv) name = *argv++; endSlash = (*name && (name[strlen(name) - 1] == '/')); - if (LSTAT(name, &statBuf) < 0) + if ( lstat(name, &statBuf) < 0 ) { - perror(name); - + errmsg( "ls: %s: %s", name, strerror(errno) ); continue; } @@ -197,8 +190,7 @@ do_ls(int argc, const char ** argv) if (dirp == NULL) { - perror(name); - + errmsg( "ls: %s: %s", name, strerror(errno) ); continue; } @@ -300,10 +292,9 @@ listAllFiles(int flags, int displayWidth) { name = list[i]; - if (LSTAT(name, &statBuf) < 0) + if ( lstat(name, &statBuf) < 0 ) { - perror(name); - + errmsg( "ls: %s: %s", name, strerror(errno) ); continue; } @@ -529,10 +520,9 @@ addListName(const char * fileName) newList = realloc(list, ((sizeof(char **)) * (listSize + LISTSIZE))); - if (newList == NULL) + if ( !newList ) { - fprintf(stderr, "No memory for file name buffer\n"); - + errmsg( "ls: file list allocation failure: %s", strerror(errno) ); return FALSE; } @@ -545,10 +535,9 @@ addListName(const char * fileName) */ list[listUsed] = strdup(fileName); - if (list[listUsed] == NULL) + if ( !list[listUsed] ) { - fprintf(stderr, "No memory for file name\n"); - + errmsg( "ls: file name allocation failure: %s", strerror(errno) ); return FALSE; } --- sash/cmd_tar.c +++ sash/cmd_tar.c @@ -7,12 +7,12 @@ * This allows creation, extraction, and listing of tar files. */ -#include "sash.h" - #include #include #include -#include + +#include "message.h" +#include "sash.h" /* @@ -87,13 +87,13 @@ static ino_t tarInode; /* * Local procedures to restore files from a tar file. */ -static void readTarFile(int fileCount, const char ** fileTable); +static void readTarFile(int fileCount, const char *const *fileTable); static void readData(const char * cp, int count); static void createPath(const char * name, int mode); static long getOctal(const char * cp, int len); static void readHeader(const TarHeader * hp, - int fileCount, const char ** fileTable); + int fileCount, const char *const *fileTable); /* @@ -108,19 +108,19 @@ static void saveDirectory(const char * fileName, const struct stat * statbuf); static BOOL wantFileName(const char * fileName, - int fileCount, const char ** fileTable); + int fileCount, const char *const *fileTable); static void writeHeader(const char * fileName, const struct stat * statbuf); -static void writeTarFile(int fileCount, const char ** fileTable); +static void writeTarFile(int fileCount, const char *const *fileTable); static void writeTarBlock(const char * buf, int len); static BOOL putOctal(char * cp, int len, long value); void -do_tar(int argc, const char ** argv) +do_tar(int argc, const char *const *argv) { const char * options; @@ -129,8 +129,7 @@ do_tar(int argc, const char ** argv) if (argc < 2) { - fprintf(stderr, "Too few arguments for tar\n"); - + errmsg( "tar: too few arguments for tar" ); return; } @@ -154,10 +153,9 @@ do_tar(int argc, const char ** argv) switch (*options) { case 'f': - if (tarName != NULL) + if ( !tarName ) { - fprintf(stderr, "Only one 'f' option allowed\n"); - + errmsg( "tar: only one 'f' option allowed" ); return; } @@ -183,8 +181,7 @@ do_tar(int argc, const char ** argv) break; default: - fprintf(stderr, "Unknown tar flag '%c'\n", *options); - + errmsg( "tar: unknown flag: %c", *options ); return; } } @@ -194,15 +191,13 @@ do_tar(int argc, const char ** argv) */ if (extractFlag + listFlag + createFlag != 1) { - fprintf(stderr, "Exactly one of 'c', 'x' or 't' must be specified\n"); - + errmsg( "tar: exactly one of 'c', 'x' or 't' must be specified" ); return; } - if (tarName == NULL) + if ( !tarName ) { - fprintf(stderr, "The 'f' flag must be specified\n"); - + errmsg( "tar: the 'f' flag must be specified" ); return; } @@ -222,7 +217,7 @@ do_tar(int argc, const char ** argv) * If the list is empty than all files are extracted or listed. */ static void -readTarFile(int fileCount, const char ** fileTable) +readTarFile(int fileCount, const char *const *fileTable) { const char * cp; int cc; @@ -248,8 +243,7 @@ readTarFile(int fileCount, const char ** fileTable) if (tarFd < 0) { - perror(tarName); - + errmsg( "tar: error opening %s: %s", tarName, strerror(errno) ); return; } @@ -271,17 +265,13 @@ readTarFile(int fileCount, const char ** fileTable) if (inCc < 0) { - perror(tarName); - + errmsg( "tar: error reading %s: %s", tarName, strerror(errno) ); goto done; } - if (inCc == 0) + if ( !inCc ) { - fprintf(stderr, - "Unexpected end of file from \"%s\"", - tarName); - + errmsg( "tar: %s: unexpected end of file", tarName ); goto done; } } @@ -327,7 +317,7 @@ readTarFile(int fileCount, const char ** fileTable) * Check for an interrupt. */ if (intFlag) - fprintf(stderr, "Interrupted - aborting\n"); + errmsg( "tar: interrupted" ); done: @@ -335,7 +325,7 @@ done: * Close the tar file if needed. */ if ((tarFd >= 0) && (close(tarFd) < 0)) - perror(tarName); + errmsg( "tar: error closing %s: %s", tarName, strerror(errno) ); /* * Close the output file if needed. @@ -353,7 +343,7 @@ done: * the end of the tar file. */ static void -readHeader(const TarHeader * hp, int fileCount, const char ** fileTable) +readHeader(const TarHeader * hp, int fileCount, const char *const *fileTable) { int mode; int uid; @@ -399,7 +389,7 @@ readHeader(const TarHeader * hp, int fileCount, const char ** fileTable) if ((mode < 0) || (uid < 0) || (gid < 0) || (size < 0)) { if (!badHeader) - fprintf(stderr, "Bad tar header, skipping\n"); + errmsg( "tar: bad header, skipping" ); badHeader = TRUE; @@ -436,10 +426,7 @@ readHeader(const TarHeader * hp, int fileCount, const char ** fileTable) name++; if (!warnedRoot) - { - fprintf(stderr, - "Absolute path detected, removing leading slashes\n"); - } + errmsg( "tar: absolute path detected, removing leading slashes" ); warnedRoot = TRUE; } @@ -499,19 +486,14 @@ readHeader(const TarHeader * hp, int fileCount, const char ** fileTable) if (hardLink) { if (link(hp->linkName, name) < 0) - perror(name); - + errmsg( "tar: error hardlinking '%s' -> '%s': %s", name, hp->linkName, strerror(errno) ); return; } if (softLink) { -#ifdef S_ISLNK if (symlink(hp->linkName, name) < 0) - perror(name); -#else - fprintf(stderr, "Cannot create symbolic links\n"); -#endif + errmsg( "tar: error symlinking '%s' -> '%s': %s", name, hp->linkName, strerror(errno) ); return; } @@ -541,9 +523,8 @@ readHeader(const TarHeader * hp, int fileCount, const char ** fileTable) if (outFd < 0) { - perror(name); + errmsg( "tar: error creating %s: %s", name, strerror(errno) ); skipFileFlag = TRUE; - return; } @@ -586,7 +567,7 @@ readData(const char * cp, int count) */ if (fullWrite(outFd, cp, count) < 0) { - perror(outName); + errmsg( "tar: error writing %s: %s", outName, strerror(errno) ); (void) close(outFd); outFd = -1; skipFileFlag = TRUE; @@ -601,7 +582,7 @@ readData(const char * cp, int count) if (dataCc <= 0) { if (close(outFd)) - perror(outName); + errmsg( "tar: error closing %s: %s", outName, strerror(errno) ); outFd = -1; } @@ -612,7 +593,7 @@ readData(const char * cp, int count) * Write a tar file containing the specified files. */ static void -writeTarFile(int fileCount, const char ** fileTable) +writeTarFile(int fileCount, const char *const *fileTable) { struct stat statbuf; @@ -623,8 +604,7 @@ writeTarFile(int fileCount, const char ** fileTable) */ if (fileCount <= 0) { - fprintf(stderr, "No files specified to be saved\n"); - + errmsg( "tar: no files specified to be saved" ); return; } @@ -635,8 +615,7 @@ writeTarFile(int fileCount, const char ** fileTable) if (tarFd < 0) { - perror(tarName); - + errmsg( "tar: error creating %s: %s", tarName, strerror(errno) ); return; } @@ -645,8 +624,7 @@ writeTarFile(int fileCount, const char ** fileTable) */ if (fstat(tarFd, &statbuf) < 0) { - perror(tarName); - + errmsg( "tar: %s: %s", tarName, strerror(errno) ); goto done; } @@ -663,7 +641,7 @@ writeTarFile(int fileCount, const char ** fileTable) } if (intFlag) - fprintf(stderr, "Interrupted - aborting archiving\n"); + errmsg( "tar: interrupted - archiving aborted"); /* * Now write an empty block of zeroes to end the archive. @@ -676,7 +654,7 @@ done: * Close the tar file and check for errors if it was opened. */ if ((tarFd >= 0) && (close(tarFd) < 0)) - perror(tarName); + errmsg( "tar: error closing %s: %s", tarName, strerror(errno) ); } @@ -702,8 +680,7 @@ saveFile(const char * fileName, BOOL seeLinks) */ if (strlen(fileName) >= TAR_NAME_SIZE) { - fprintf(stderr, "%s: File name is too long\n", fileName); - + errmsg( "tar: %s: file name is too long", fileName ); return; } @@ -719,8 +696,7 @@ saveFile(const char * fileName, BOOL seeLinks) if (status < 0) { - perror(fileName); - + errmsg( "tar: %s: %s", fileName, strerror(errno) ); return; } @@ -729,7 +705,7 @@ saveFile(const char * fileName, BOOL seeLinks) */ if ((statbuf.st_dev == tarDev) && (statbuf.st_ino == tarInode)) { - fprintf(stderr, "Skipping saving of archive file itself\n"); + errmsg( "tar: skipped saving of archive file itself" ); return; } @@ -756,7 +732,7 @@ saveFile(const char * fileName, BOOL seeLinks) /* * The file is a strange type of file, ignore it. */ - fprintf(stderr, "%s: not a directory or regular file\n", fileName); + errmsg( "tar: %s: not a directory or regular file", fileName ); } @@ -780,8 +756,7 @@ saveRegularFile(const char * fileName, const struct stat * statbuf) if (fileFd < 0) { - perror(fileName); - + errmsg( "tar: error opening %s: %s", fileName, strerror(errno) ); return; } @@ -823,7 +798,7 @@ saveRegularFile(const char * fileName, const struct stat * statbuf) if (cc < 0) { - perror(fileName); + errmsg( "tar: error reading %s: %s", fileName, strerror(errno) ); (void) close(fileFd); errorFlag = TRUE; @@ -837,10 +812,7 @@ saveRegularFile(const char * fileName, const struct stat * statbuf) */ if (cc < dataCount) { - fprintf(stderr, - "%s: Short read - zero filling", - fileName); - + errmsg( "tar: %s: unexpected end of file - zero filling", fileName ); sawEof = TRUE; } } @@ -863,7 +835,7 @@ saveRegularFile(const char * fileName, const struct stat * statbuf) * Close the file. */ if (close(fileFd) < 0) - fprintf(stderr, "%s: close: %s\n", fileName, strerror(errno)); + errmsg( "tar: error closing %s: %s", fileName, strerror(errno) ); } @@ -895,11 +867,9 @@ saveDirectory(const char * dirName, const struct stat * statbuf) */ dir = opendir(dirName); - if (dir == NULL) + if ( !dir ) { - fprintf(stderr, "Cannot read directory \"%s\": %s\n", - dirName, strerror(errno)); - + errmsg( "tar: cannot read directory \"%s\": %s\n", dirName, strerror(errno) ); return; } @@ -1029,10 +999,8 @@ writeTarBlock(const char * buf, int len) */ if ((completeLength > 0) && !fullWrite(tarFd, buf, completeLength)) { - perror(tarName); - + errmsg( "tar: error writing %s: %s", tarName, strerror(errno) ); errorFlag = TRUE; - return; } @@ -1054,8 +1022,7 @@ writeTarBlock(const char * buf, int len) */ if (!fullWrite(tarFd, fullBlock, TAR_BLOCK_SIZE)) { - perror(tarName); - + errmsg( "tar: error writing %s: %s", tarName, strerror(errno) ); errorFlag = TRUE; } } @@ -1191,7 +1158,7 @@ putOctal(char * cp, int len, long value) * Returns TRUE if the file is selected. */ static BOOL -wantFileName(const char * fileName, int fileCount, const char ** fileTable) +wantFileName(const char * fileName, int fileCount, const char *const *fileTable) { const char * pathName; int fileLength; --- sash/cmds.c +++ sash/cmds.c @@ -6,6 +6,7 @@ * Most simple built-in commands are here. */ +#include "message.h" #include "sash.h" #include @@ -15,12 +16,14 @@ #include #include #include -#include -#include +#ifndef dev_t +#define dev_t dev_t +#endif +#include void -do_echo(int argc, const char ** argv) +do_echo(int argc, const char *const *argv) { BOOL first; @@ -40,14 +43,13 @@ do_echo(int argc, const char ** argv) void -do_pwd(int argc, const char ** argv) +do_pwd(int argc, const char *const *argv) { char buf[PATH_LEN]; - if (getcwd(buf, PATH_LEN) == NULL) + if ( !getcwd(buf, PATH_LEN) ) { - fprintf(stderr, "Cannot get current directory\n"); - + errmsg( "pwd: cannot get current directory" ); return; } @@ -56,7 +58,7 @@ do_pwd(int argc, const char ** argv) void -do_cd(int argc, const char ** argv) +do_cd(int argc, const char *const *argv) { const char * path; @@ -66,41 +68,36 @@ do_cd(int argc, const char ** argv) { path = getenv("HOME"); - if (path == NULL) + if ( !path ) { - fprintf(stderr, "No HOME environment variable\n"); - + errmsg( "cd: HOME not set" ); return; } } if (chdir(path) < 0) - perror(path); + errmsg( "cd: chdir: %s: %s", path, strerror(errno) ); } void -do_mkdir(int argc, const char ** argv) +do_mkdir(int argc, const char *const *argv) { while (argc-- > 1) { if (mkdir(argv[1], 0777) < 0) - perror(argv[1]); + errmsg( "mkdir: %s: %s", argv[1], strerror(errno) ); - argv++; + ++argv; } } void -do_mknod(int argc, const char ** argv) +do_mknod(int argc, const char *const *argv) { - const char * cp; - int mode; - int major; - int minor; - - mode = 0666; + int mode = 0666, major = 0, minor = 0; + const char *cp = argv[3]; if (strcmp(argv[2], "b") == 0) mode |= S_IFBLK; @@ -108,25 +105,19 @@ do_mknod(int argc, const char ** argv) mode |= S_IFCHR; else { - fprintf(stderr, "Bad device type\n"); - + errmsg( "mknod: bad device type: %s", argv[2] ); return; } - major = 0; - cp = argv[3]; - while (isDecimal(*cp)) major = major * 10 + *cp++ - '0'; if (*cp || (major < 0) || (major > 255)) { - fprintf(stderr, "Bad major number\n"); - + errmsg( "mknod: bad major number: %d", major ); return; } - minor = 0; cp = argv[4]; while (isDecimal(*cp)) @@ -134,51 +125,50 @@ do_mknod(int argc, const char ** argv) if (*cp || (minor < 0) || (minor > 255)) { - fprintf(stderr, "Bad minor number\n"); - + errmsg( "mknod: bad minor number: %d", minor ); return; } if (mknod(argv[1], mode, major * 256 + minor) < 0) - perror(argv[1]); + errmsg( "mknod: %s: %s", argv[1], strerror(errno) ); } void -do_rmdir(int argc, const char ** argv) +do_rmdir(int argc, const char *const *argv) { while (argc-- > 1) { if (rmdir(argv[1]) < 0) - perror(argv[1]); + errmsg( "rmdir: %s: %s", argv[1], strerror(errno) ); - argv++; + ++argv; } } void -do_sync(int argc, const char ** argv) +do_sync(int argc, const char *const *argv) { sync(); } void -do_rm(int argc, const char ** argv) +do_rm(int argc, const char *const *argv) { while (argc-- > 1) { if (unlink(argv[1]) < 0) - perror(argv[1]); + errmsg( "rm: %s: %s", argv[1], strerror(errno) ); - argv++; + ++argv; } } void -do_chmod(int argc, const char ** argv) +do_chmod(int argc, const char *const *argv) { const char * cp; int mode; @@ -191,26 +181,25 @@ do_chmod(int argc, const char ** argv) if (*cp) { - fprintf(stderr, "Mode must be octal\n"); - + errmsg( "chmod: mode must be octal" ); return; } - argc--; - argv++; + --argc; + ++argv; while (argc-- > 1) { if (chmod(argv[1], mode) < 0) - perror(argv[1]); + errmsg( "chmod: %s: %s", argv[1], strerror(errno) ); - argv++; + ++argv; } } void -do_chown(int argc, const char ** argv) +do_chown(int argc, const char *const *argv) { const char * cp; int uid; @@ -228,41 +217,39 @@ do_chown(int argc, const char ** argv) if (*cp) { - fprintf(stderr, "Bad uid value\n"); - + errmsg( "chown: bad uid value: %s", argv[1] ); return; } } else { pwd = getpwnam(cp); - if (pwd == NULL) + if ( !pwd ) { - fprintf(stderr, "Unknown user name\n"); - + errmsg( "chown: unknown user name: %s", cp ); return; } uid = pwd->pw_uid; } - argc--; - argv++; + --argc; + ++argv; while (argc-- > 1) { - argv++; + ++argv; if ((stat(*argv, &statBuf) < 0) || (chown(*argv, uid, statBuf.st_gid) < 0)) { - perror(*argv); + errmsg( "chown: %s: %s", *argv, strerror(errno) ); } } } void -do_chgrp(int argc, const char ** argv) +do_chgrp(int argc, const char *const *argv) { const char * cp; int gid; @@ -280,8 +267,7 @@ do_chgrp(int argc, const char ** argv) if (*cp) { - fprintf(stderr, "Bad gid value\n"); - + errmsg( "chgrp: bad gid value: %s", argv[1] ); return; } } @@ -289,34 +275,33 @@ do_chgrp(int argc, const char ** argv) { grp = getgrnam(cp); - if (grp == NULL) + if ( !grp ) { - fprintf(stderr, "Unknown group name\n"); - + errmsg( "chgrp: unknown group name: %s", cp ); return; } gid = grp->gr_gid; } - argc--; - argv++; + --argc; + ++argv; while (argc-- > 1) { - argv++; + ++argv; if ((stat(*argv, &statBuf) < 0) || (chown(*argv, statBuf.st_uid, gid) < 0)) { - perror(*argv); + errmsg( "chgrp: %s: %s", *argv, strerror(errno) ); } } } void -do_touch(int argc, const char ** argv) +do_touch(int argc, const char *const *argv) { const char * name; int fd; @@ -334,32 +319,26 @@ do_touch(int argc, const char ** argv) if (fd >= 0) { close(fd); - continue; } if (utime(name, &now) < 0) - perror(name); + errmsg( "touch: %s: %s", name, strerror(errno) ); } } void -do_mv(int argc, const char ** argv) +do_mv(int argc, const char *const *argv) { - const char * srcName; - const char * destName; - const char * lastArg; - BOOL dirFlag; - - lastArg = argv[argc - 1]; - - dirFlag = isDirectory(lastArg); + const char *srcName; + const char *destName; + const char *lastArg = argv[argc - 1]; + BOOL dirFlag = isDirectory(lastArg); if ((argc > 3) && !dirFlag) { - fprintf(stderr, "%s: not a directory\n", lastArg); - + errmsg( "mv: %s: when moving multiple files, last argument must be a directory", lastArg ); return; } @@ -369,8 +348,7 @@ do_mv(int argc, const char ** argv) if (access(srcName, 0) < 0) { - perror(srcName); - + errmsg( "mv: %s: %s", srcName, strerror(errno) ); continue; } @@ -384,8 +362,7 @@ do_mv(int argc, const char ** argv) if (errno != EXDEV) { - perror(destName); - + errmsg( "mv: %s: %s", destName, strerror(errno) ); continue; } @@ -393,65 +370,45 @@ do_mv(int argc, const char ** argv) continue; if (unlink(srcName) < 0) - perror(srcName); + errmsg( "mv: error unlinking %s: %s", srcName, strerror(errno) ); } } void -do_ln(int argc, const char ** argv) +do_ln(int argc, const char *const *argv) { - const char * srcName; - const char * destName; - const char * lastArg; - BOOL dirFlag; + const char * srcName; + const char * destName; + const char * lastArg = argv[argc - 1]; + BOOL dirFlag = isDirectory(lastArg), sym = FALSE; if (argv[1][0] == '-') { if (strcmp(argv[1], "-s")) { - fprintf(stderr, "Unknown option\n"); - - return; - } - - if (argc != 4) - { - fprintf(stderr, "Wrong number of arguments for symbolic link\n"); - + errmsg( "ln: unknown option: %s", argv[1] ); return; } -#ifdef S_ISLNK - if (symlink(argv[2], argv[3]) < 0) - perror(argv[3]); -#else - fprintf(stderr, "Symbolic links are not allowed\n"); -#endif - return; + sym = TRUE; + --argc; + ++argv; } - /* - * Here for normal hard links. - */ - lastArg = argv[argc - 1]; - dirFlag = isDirectory(lastArg); - if ((argc > 3) && !dirFlag) { - fprintf(stderr, "%s: not a directory\n", lastArg); - + errmsg( "ln: %s: when making multiple links, last argument must be a directory", lastArg ); return; } - while (argc-- > 2) + while (--argc > 1) { srcName = *(++argv); - if (access(srcName, 0) < 0) + if ( !sym && access(srcName, 0) < 0) { - perror(srcName); - + errmsg( "ln: %s: %s", srcName, strerror(errno) ); continue; } @@ -460,18 +417,15 @@ do_ln(int argc, const char ** argv) if (dirFlag) destName = buildName(destName, srcName); - if (link(srcName, destName) < 0) - { - perror(destName); - - continue; - } + if ( (sym ? symlink(srcName, destName) : link(srcName, destName)) < 0 ) + errmsg( "%s: %s -> %s: %s", (sym ? "symlink" : "ln"), + srcName, destName, strerror(errno) ); } } void -do_cp(int argc, const char ** argv) +do_cp(int argc, const char *const *argv) { const char * srcName; const char * destName; @@ -484,8 +438,7 @@ do_cp(int argc, const char ** argv) if ((argc > 3) && !dirFlag) { - fprintf(stderr, "%s: not a directory\n", lastArg); - + errmsg( "cp: %s: when copying multiple files, last argument must be a directory", lastArg ); return; } @@ -503,20 +456,20 @@ do_cp(int argc, const char ** argv) void -do_mount(int argc, const char ** argv) +do_mount(int argc, const char *const *argv) { const char * str; const char * type; int flags; - argc--; - argv++; + --argc; + ++argv; type = "ext2"; flags = MS_MGC_VAL; while ((argc > 0) && (**argv == '-')) { - argc--; + --argc; str = *argv++; while (*++str) switch (*str) @@ -524,13 +477,12 @@ do_mount(int argc, const char ** argv) case 't': if ((argc <= 0) || (**argv == '-')) { - fprintf(stderr, "Missing file system type\n"); - + errmsg( "mount: missing file system type" ); return; } type = *argv++; - argc--; + --argc; break; case 'r': @@ -542,34 +494,33 @@ do_mount(int argc, const char ** argv) break; default: - fprintf(stderr, "Unknown option\n"); - + errmsg( "mount: unknown option: %s", str ); return; } } if (argc != 2) { - fprintf(stderr, "Wrong number of arguments for mount\n"); + errmsg( "mount: wrong number of arguments for mount" ); return; } if (mount(argv[0], argv[1], type, flags, 0) < 0) - perror("mount failed"); + errmsg( "mount: %s", strerror(errno) ); } void -do_umount(int argc, const char ** argv) +do_umount(int argc, const char *const *argv) { if (umount(argv[1]) < 0) - perror(argv[1]); + errmsg( "umount: %s: %s", argv[1], strerror(errno) ); } void -do_cmp(int argc, const char ** argv) +do_cmp(int argc, const char *const *argv) { int fd1; int fd2; @@ -585,30 +536,26 @@ do_cmp(int argc, const char ** argv) if (stat(argv[1], &statBuf1) < 0) { - perror(argv[1]); - + errmsg( "cmp: %s: %s", argv[1], strerror(errno) ); return; } if (stat(argv[2], &statBuf2) < 0) { - perror(argv[2]); - + errmsg( "cmp: %s: %s", argv[2], strerror(errno) ); return; } if ((statBuf1.st_dev == statBuf2.st_dev) && (statBuf1.st_ino == statBuf2.st_ino)) { - printf("Files are links to each other\n"); - + puts( "Files are links to each other" ); return; } if (statBuf1.st_size != statBuf2.st_size) { - printf("Files are different sizes\n"); - + puts( "Files are different sizes" ); return; } @@ -616,8 +563,7 @@ do_cmp(int argc, const char ** argv) if (fd1 < 0) { - perror(argv[1]); - + errmsg( "cmp: error opening %s: %s", argv[1], strerror(errno) ); return; } @@ -625,15 +571,14 @@ do_cmp(int argc, const char ** argv) if (fd2 < 0) { - perror(argv[2]); + errmsg( "cmp: error opening %s: %s", argv[2], strerror(errno) ); close(fd1); - return; } pos = 0; - while (TRUE) + for(;;) { if (intFlag) goto closefiles; @@ -642,7 +587,7 @@ do_cmp(int argc, const char ** argv) if (cc1 < 0) { - perror(argv[1]); + errmsg( "cmp: error reading %s: %s", argv[1], strerror(errno) ); goto closefiles; } @@ -650,25 +595,25 @@ do_cmp(int argc, const char ** argv) if (cc2 < 0) { - perror(argv[2]); + errmsg( "cmp: error reading %s: %s", argv[2], strerror(errno) ); goto closefiles; } - if ((cc1 == 0) && (cc2 == 0)) + if ( !cc1 && !cc2 ) { - printf("Files are identical\n"); + puts( "Files are identical" ); goto closefiles; } if (cc1 < cc2) { - printf("First file is shorter than second\n"); + puts( "First file is shorter than second" ); goto closefiles; } if (cc1 > cc2) { - printf("Second file is shorter than first\n"); + puts( "Second file is shorter than first" ); goto closefiles; } @@ -685,7 +630,7 @@ do_cmp(int argc, const char ** argv) while (*bp1++ == *bp2++) pos++; - printf("Files differ at byte position %ld\n", pos); + printf( "Files differ at byte position %ld\n", pos ); goto closefiles; } @@ -697,7 +642,7 @@ closefiles: void -do_more(int argc, const char ** argv) +do_more(int argc, const char *const *argv) { FILE * fp; const char * name; @@ -739,11 +684,9 @@ do_more(int argc, const char ** argv) name = *(++argv); fp = fopen(name, "r"); - - if (fp == NULL) + if ( !fp ) { - perror(name); - + errmsg( "more: error opening %s: %s", name, strerror(errno) ); return; } @@ -833,7 +776,7 @@ do_more(int argc, const char ** argv) void -do_sum(int argc, const char ** argv) +do_sum(int argc, const char *const *argv) { const char * name; int fd; @@ -843,8 +786,8 @@ do_sum(int argc, const char ** argv) unsigned long checksum; char buf[BUF_SIZE]; - argc--; - argv++; + --argc; + ++argv; while (argc-- > 0) { @@ -854,8 +797,7 @@ do_sum(int argc, const char ** argv) if (fd < 0) { - perror(name); - + errmsg( "sum: error opening %s: %s", name, strerror(errno) ); continue; } @@ -878,8 +820,7 @@ do_sum(int argc, const char ** argv) if (cc < 0) { - perror(name); - + errmsg( "sum: error reading %s: %s", name, strerror(errno) ); (void) close(fd); continue; @@ -893,58 +834,34 @@ do_sum(int argc, const char ** argv) void -do_exit(int argc, const char ** argv) +do_exit(int argc, const char *const *argv) { - if (getpid() == 1) + if ( getpid() == 1 ) { - fprintf(stderr, "You are the INIT process!\n"); - + errmsg( "exit: you are the INIT process!" ); return; } - exit(0); + exit( argc ? atoi( argv[1] ) : 0 ); } void -do_setenv(int argc, const char ** argv) +do_setenv(int argc, const char *const *argv) { - const char * name; - const char * value; - char * str; - - name = argv[1]; - value = argv[2]; - - /* - * The value given to putenv must remain around, so we must malloc it. - * Note: memory is not reclaimed if the same variable is redefined. - */ - str = malloc(strlen(name) + strlen(value) + 2); - - if (str == NULL) - { - fprintf(stderr, "Cannot allocate memory\n"); - - return; - } - - strcpy(str, name); - strcat(str, "="); - strcat(str, value); - - putenv(str); + if ( setenv( argv[1], argv[2], 1 ) < 0 ) + errmsg( "setenv: %s", strerror(errno) ); } void -do_printenv(int argc, const char ** argv) +do_printenv(int argc, const char *const *argv) { - const char ** env; + const char *const * env; extern char ** environ; int len; - env = (const char **) environ; + env = (const char *const *) environ; if (argc == 1) { @@ -971,7 +888,7 @@ do_printenv(int argc, const char ** argv) void -do_umask(int argc, const char ** argv) +do_umask(int argc, const char *const *argv) { const char * cp; int mask; @@ -993,63 +910,91 @@ do_umask(int argc, const char ** argv) if (*cp || (mask & ~0777)) { - fprintf(stderr, "Bad umask value\n"); - + errmsg( "umask: bad value: %o", mask ); return; } umask(mask); } +typedef struct +{ + int no; + const char *name; +} sig_desc_t; + +static sig_desc_t sig_desc[] = { + { SIGHUP, "HUP" }, + { SIGINT, "INT" }, + { SIGQUIT, "QUIT" }, + { SIGILL, "ILL" }, + { SIGTRAP, "TRAP" }, + { SIGABRT, "ABRT" }, + { SIGIOT, "IOT" }, + { SIGBUS, "BUS" }, + { SIGFPE, "FPE" }, + { SIGKILL, "KILL" }, + { SIGUSR1, "USR1" }, + { SIGSEGV, "SEGV" }, + { SIGUSR2, "USR2" }, + { SIGPIPE, "PIPE" }, + { SIGALRM, "ALRM" }, + { SIGTERM, "TERM" }, +#ifdef SIGSTKFLT + { SIGSTKFLT, "STKFLT" }, +#endif + { SIGSYS, "SYS" }, + { SIGCHLD, "CHLD" }, + { SIGCONT, "CONT" }, + { SIGSTOP, "STOP" }, + { SIGTSTP, "TSTP" }, + { SIGTTIN, "TTIN" }, + { SIGTTOU, "TTOU" }, + { SIGURG, "URG" }, + { SIGXCPU, "XCPU" }, + { SIGXFSZ, "XFSZ" }, + { SIGVTALRM, "VTALRM" }, + { SIGPROF, "PROF" }, + { SIGWINCH, "WINCH" }, + { SIGIO, "IO" }, + { SIGPOLL, "POLL" }, + { SIGPWR, "PWR" } +}; void -do_kill(int argc, const char ** argv) +do_kill(int argc, const char *const *argv) { const char * cp; - int sig; - int pid; + int sig = SIGTERM, pid; - sig = SIGTERM; - - if (argv[1][0] == '-') + if ( *argv[1] == '-' ) { + unsigned i = 0; + sig = 0; cp = &argv[1][1]; - - if (strcmp(cp, "HUP") == 0) - sig = SIGHUP; - else if (strcmp(cp, "INT") == 0) - sig = SIGINT; - else if (strcmp(cp, "QUIT") == 0) - sig = SIGQUIT; - else if (strcmp(cp, "KILL") == 0) - sig = SIGKILL; - else if (strcmp(cp, "STOP") == 0) - sig = SIGSTOP; - else if (strcmp(cp, "CONT") == 0) - sig = SIGCONT; - else if (strcmp(cp, "USR1") == 0) - sig = SIGUSR1; - else if (strcmp(cp, "USR2") == 0) - sig = SIGUSR2; - else if (strcmp(cp, "TERM") == 0) - sig = SIGTERM; - else + for ( ; i < sizeof(sig_desc) / sizeof(*sig_desc); ++i ) { - sig = 0; + if ( !strcmp( cp, sig_desc[i].name ) ) + { + sig = sig_desc[i].no; + break; + } + } + if ( !sig ) + { while (isDecimal(*cp)) sig = sig * 10 + *cp++ - '0'; - if (*cp) + if ( sig <= 0 || sig > 31 || *cp ) { - fprintf(stderr, "Unknown signal\n"); - + errmsg( "kill: unknown signal: %s", &argv[1][1] ); return; } } - argc--; - argv++; + --argc; + ++argv; } while (argc-- > 1) @@ -1062,19 +1004,18 @@ do_kill(int argc, const char ** argv) if (*cp) { - fprintf(stderr, "Non-numeric pid\n"); - + errmsg( "kill: non-numeric pid: %s", *argv ); return; } if (kill(pid, sig) < 0) - perror(*argv); + errmsg( "kill: %d: %s", pid, strerror(errno) ); } } void -do_where(int argc, const char ** argv) +do_where(int argc, const char *const *argv) { const char * program; const char * dirName; @@ -1086,10 +1027,9 @@ do_where(int argc, const char ** argv) found = FALSE; program = argv[1]; - if (strchr(program, '/') != NULL) + if ( strchr(program, '/') ) { - fprintf(stderr, "Program name cannot include a path\n"); - + errmsg( "where: program name cannot include a path" ); return; } @@ -1098,10 +1038,9 @@ do_where(int argc, const char ** argv) fullPath = getChunk(strlen(path) + strlen(program) + 2); path = chunkstrdup(path); - if ((path == NULL) || (fullPath == NULL)) + if ( !path || !fullPath ) { - fprintf(stderr, "Memory allocation failed\n"); - + errmsg( "where: memory allocation failure: %s", strerror(errno) ); return; } @@ -1155,4 +1094,64 @@ do_where(int argc, const char ** argv) printf("Program \"%s\" not found in PATH\n", program); } +void do_losetup(int argc, const char *const *argv) +{ + int loopfd, targfd; + struct loop_info loopInfo; + + if ( !strcmp( argv[1], "-d" ) ) + { + loopfd = open( argv[2], O_RDONLY ); + if ( loopfd < 0 ) + { + errmsg( "losetup: error opening %s: %s", argv[2], strerror(errno) ); + return; + } + + if ( ioctl(loopfd, LOOP_CLR_FD, 0) < 0 ) + { + errmsg( "losetup: error unassociating device: %s", strerror(errno) ); + close( loopfd ); + return; + } + + close( loopfd ); + return; + } + + loopfd = open( argv[1], O_RDONLY ); + if ( loopfd < 0 ) + { + errmsg( "losetup: error opening %s: %s", argv[1], strerror(errno) ); + return; + } + + targfd = open( argv[2], O_RDONLY ); + if ( targfd < 0 ) + { + errmsg( "losetup: error opening %s: %s", argv[2], strerror(errno) ); + close( loopfd ); + return; + } + + if ( ioctl(loopfd, LOOP_SET_FD, targfd) < 0 ) + { + errmsg( "losetup: error setting up loopback device: %s", strerror(errno) ); + close( loopfd ); + close( targfd ); + return; + } + + memset(&loopInfo, 0, sizeof(loopInfo)); + strcpy(loopInfo.lo_name, argv[2]); + + if ( ioctl(loopfd, LOOP_SET_STATUS, &loopInfo) < 0 ) + errmsg( "losetup: error setting up loopback device: %s", strerror(errno) ); + + close( loopfd ); + close( targfd ); + + return; +} + /* END CODE */ --- /dev/null +++ sash/getline.c @@ -0,0 +1,75 @@ +#include +#include "getline.h" +#include "sash.h" + +int rl_disable; + +static void showPrompt( void ) +{ + const char *cp = prompt ?: "$ "; + write( STDOUT_FILENO, cp, strlen(cp) ); +} + +static char *get_line_norl( FILE *fp ) +{ + static char buf[CMD_LEN]; + int is_tty = isatty(fileno(fp)); + char *p; + + if ( is_tty ) + showPrompt(); + + for(;;) + { + if ( fgets( buf, CMD_LEN - 1, fp ) ) + break; + + if ( ferror(fp) && (EINTR == errno) ) + { + clearerr( fp ); + continue; + } + + return 0; + } + + for ( p = buf + strlen(buf) - 1; p >= buf; --p ) + if ( !isspace( *p ) ) + break; + + p[1] = '\0'; + + return buf; +} + +#ifdef WITH_READLINE +#include +#include + +static char *get_line_rl( FILE *fp ) +{ + static char *input; + + if ( input ) + free( input ); + + intCrlf = FALSE; + input = readline( prompt ?: "$ " ); + intCrlf = TRUE; + + if ( input && *input ) + add_history( input ); + + return input; +} +#endif /* WITH_READLINE */ + +char *get_line( FILE *fp ) +{ +#ifdef WITH_READLINE + if ( !rl_disable && isatty(fileno(fp)) ) + return get_line_rl( fp ); + else +#endif /* WITH_READLINE */ + return get_line_norl( fp ); +} --- /dev/null +++ sash/getline.h @@ -0,0 +1,12 @@ +#ifndef __GETLINE_H__ +#define __GETLINE_H__ + +#include + +extern int intCrlf; +extern int rl_disable; +extern char *prompt; + +extern char *get_line( FILE *fp ); + +#endif /* __GETLINE_H__ */ --- /dev/null +++ sash/message.c @@ -0,0 +1,33 @@ +#include +#include +#include +#include "message.h" + +extern const char *__progname; + +static void print_message( const char *fmt, va_list args ) +{ + fprintf( stderr, "%s: ", __progname ); + vfprintf( stderr, fmt, args ); + fputs( "\r\n", stderr ); + fflush( stderr ); +} + +void errmsg( const char *fmt, ... ) +{ + va_list args; + + va_start( args, fmt ); + print_message( fmt, args ); + va_end( args ); +} + +void fatal( const char *fmt, ... ) +{ + va_list args; + + va_start( args, fmt ); + print_message( fmt, args ); + va_end( args ); + exit( 1 ); +} --- /dev/null +++ sash/message.h @@ -0,0 +1,7 @@ +#ifndef __MESSAGE_H__ +#define __MESSAGE_H__ + +void errmsg( const char *fmt, ... ) __attribute__ ((format (printf, 1, 2))); +void fatal( const char *fmt, ... ) __attribute__ ((noreturn)) __attribute__ ((format (printf, 1, 2))); + +#endif /* __MESSAGE_H__ */ --- sash/sash.1 +++ sash/sash.1 @@ -2,7 +2,7 @@ .SH NAME sash \- stand-alone shell with built-in commands .SH SYNOPSYS -.B sash [-c command] [-p prompt] [-q] [-a] +.B sash [-c command] [-p prompt] [-q] [-a] [script] .SH DESCRIPTION The .B sash @@ -24,9 +24,9 @@ These built-in commands are: .nf -ar, -chattr, -chgrp, -chmod, -chown, -cmp, -cp, -dd, -echo, -ed, -grep, -file, -find, -gunzip, - -gzip, -kill, -ln, -ls, -lsattr, -mkdir, -mknod, - -more, -mount, -mv, -printenv, -pwd, -rm, -rmdir, - -sum, -sync, -tar, -touch, -umount, -where + -gzip, -kill, -losetup, -ln, -ls, -lsattr, -mkdir, + -mknod, -more, -mount, -mv, -printenv, -pwd, -rm, + -rmdir, -sum, -sync, -tar, -touch, -umount, -where .fi .PP These commands are generally similar to the standard programs with similar @@ -303,6 +303,12 @@ is a numeric value, or one of the special values HUP, INT, QUIT, KILL, TERM, STOP, CONT, USR1 or USR2. If no signal is specified then SIGTERM is used. .TP +.B -losetup [-d] loopDev [file] +Associates loopback devices with files on the system. If -d is not given, +the loopback device \fBloopDev\fR is associated with \fBfile\fR. If -d is +given, \fBloopDev\fR is unassociated with the file it's currently configured +for. +.TP .B -ln [-s] srcName ... destName Links one or more files from the .I srcName @@ -455,20 +461,36 @@ then the reason is also printed. .SH OPTIONS There are several command line options to .BR sash . -The -c option executes the next argument as a command (including embedded +.TP +.B -c +Executes the next argument as a command (including embedded spaces to separate the arguments of the command), and then exits. -.PP -The -p option takes the next argument as the prompt string to be used +.TP +.B -p +Takes the next argument as the prompt string to be used when prompting for commands. -.PP -The -q option makes +.TP +.B -q +Makes .B sash quiet, which simply means that it doesn't print its introduction line when it starts. -.PP -The -a option creates aliases for the built-in commands so +.TP +.B -a +Creates aliases for the built-in commands so that they replace the corresponding standard commands. This is the same result as if the 'aliasall' command was used. +.TP +.B -e +Disables command editing and history support, if it was compiled into the +.B sash +executable. Otherwise, does nothing. +.PP +A file name may be provided as the last argument to sash, in which case +sash's standard input is read from that file. This allows #! scripts +to use sash as their script interpretor. Be aware that sash does not provide +most normal bourne-shell programming features, however. + .SH SYSTEM RECOVERY This section contains some useful information about using .B sash --- sash/sash.c +++ sash/sash.c @@ -10,8 +10,9 @@ #include #include #include -#include +#include "getline.h" +#include "message.h" #include "sash.h" @@ -31,7 +32,7 @@ static const char * const version = "3.4"; typedef struct { const char * name; - void (*func)(int argc, const char ** argv); + void (*func)(int argc, const char *const *argv); int minArgs; int maxArgs; const char * description; @@ -132,9 +133,9 @@ static const CommandEntry commandEntryTable[] = }, { - "exit", do_exit, 1, 1, + "exit", do_exit, 1, 2, "Exit from sash", - "" + "[exitcode]" }, { @@ -182,6 +183,12 @@ static const CommandEntry commandEntryTable[] = }, { + "-losetup", do_losetup, 3, 3, + "Associate a loopback device with a file", + "[-d] device\n -losetup device filename" + }, + + { "-ln", do_ln, 3, INFINITE_ARGS, "Link one fileName to another", "[-s] srcName ... destName" @@ -351,25 +358,21 @@ typedef struct static Alias * aliasTable; static int aliasCount; -static FILE * sourcefiles[MAX_SOURCE]; -static int sourceCount; - -static BOOL intCrlf = TRUE; -static char * prompt; +int intCrlf = TRUE; +char *prompt; /* * Local procedures. */ -static void catchInt(int); -static void catchQuit(int); -static void readFile(const char * name); +static void catchInterrupt(int); +static int readFile(const char * name); static void command(const char * cmd); static BOOL tryBuiltIn(const char * cmd); static void runCmd(const char * cmd); -static void childProcess(const char * cmd); -static void showPrompt(void); -static void usage(void); +static void childProcess(const char * cmd) __attribute__ ((noreturn)); +static void print_version( FILE *fp ); +static void usage(void) __attribute__ ((noreturn)); static Alias * findAlias(const char * name); @@ -378,143 +381,128 @@ static Alias * findAlias(const char * name); */ BOOL intFlag; - -int -main(int argc, const char ** argv) +int main( int argc, char *const argv[] ) { - const char * cp; - const char * singleCommand; - BOOL quietFlag; - BOOL aliasFlag; - char buf[PATH_LEN]; - - singleCommand = NULL; - quietFlag = FALSE; - aliasFlag = FALSE; - - /* - * Look for options. - */ - argv++; - argc--; + const char *singleCommand = NULL; + BOOL aliasFlag = FALSE, quietFlag = FALSE; + int ch; + char *cp; - while ((argc > 0) && (**argv == '-')) + while ( (ch = getopt( argc, argv, "aeqh?c:p:" )) >= 0 ) { - cp = *argv++ + 1; - argc--; - - while (*cp) switch (*cp++) + switch ( ch ) { - case 'c': - /* - * Execute specified command. - */ - if ((argc != 1) || singleCommand) - usage(); - - singleCommand = *argv++; - argc--; - + case 'a': + aliasFlag = TRUE; break; - - case 'p': - /* - * Set the prompt string. - */ - if ((argc <= 0) || (**argv == '-')) - usage(); - - if (prompt) - free(prompt); - - prompt = strdup(*argv++); - argc--; - + case 'e': + rl_disable = TRUE; break; - case 'q': quietFlag = TRUE; break; - - case 'a': - aliasFlag = TRUE; + case 'c': + if ( singleCommand ) + usage(); + singleCommand = strdup( optarg ); + if ( !singleCommand ) + fatal( "error during initialization: %s", strerror(errno) ); + break; + case 'p': + if ( prompt ) + free( prompt ); + + prompt = strdup( optarg ); + if ( !prompt ) + fatal( "error during initialization: %s", strerror(errno) ); break; - case 'h': case '?': usage(); - break; - default: - fprintf(stderr, "Unknown option -%c\n", cp[-1]); - - return 1; + fatal( "unrecognized option: -%c", ch ); } } /* - * No more arguments are allowed. + * No arguments are allowed for single command. */ - if (argc > 0) + if ( (singleCommand && optind < argc) || (optind + 1 < argc) ) usage(); /* * Default our path if it is not set. */ - if (getenv("PATH") == NULL) - putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/etc"); + if ( !getenv("PATH") ) + 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 ( aliasFlag ) + do_aliasall( 0, NULL ); /* * If we are to execute a single command, then do so and exit. */ - if (singleCommand) + if ( singleCommand ) { - command(singleCommand); - + command( singleCommand ); return 0; } + if ( optind < argc ) + { + int fd = open( argv[optind], O_RDONLY ); + if ( fd < 0 ) + fatal( "error opening %s: %s", argv[optind], strerror(errno) ); + + if ( dup2(fd, STDIN_FILENO) < 0 ) + fatal( "dup2: %s", strerror(errno) ); + + if ( fcntl( STDIN_FILENO, F_SETFD, FD_CLOEXEC ) < 0 ) + fatal( "fcntl: %s", strerror(errno) ); + + if ( close(fd) < 0 ) + fatal( "close: %s", strerror(errno) ); + } + /* * Print a hello message unless we are told to be silent. */ - if (!quietFlag && isatty(STDIN)) + if ( !quietFlag && isatty(STDIN_FILENO) ) { - printf("Stand-alone shell (version %s)\n", version); + print_version( stdout ); if (aliasFlag) printf("Built-in commands are aliased to standard commands\n"); } - signal(SIGINT, catchInt); - signal(SIGQUIT, catchQuit); + signal(SIGINT, catchInterrupt); + signal(SIGQUIT, catchInterrupt); /* * Execute the user's alias file if present. */ cp = getenv("HOME"); - if (cp) + if ( cp ) { - strcpy(buf, cp); - strcat(buf, "/"); - strcat(buf, ".aliasrc"); + const char aliasrc[] = "/.aliasrc"; + unsigned len = strlen( cp ); + char fname[len + sizeof(aliasrc)]; + + memcpy( fname, cp, len ); + memcpy( fname + len, aliasrc, sizeof(aliasrc) ); - if ((access(buf, 0) == 0) || (errno != ENOENT)) - readFile(buf); + if ( !access(fname, R_OK ) ) + readFile( fname ); } /* * Read commands from stdin. */ - readFile(NULL); - - return 0; + return readFile( 0 ); } @@ -522,80 +510,55 @@ main(int argc, const char ** argv) * 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]; - - if (sourceCount >= MAX_SOURCE) - { - fprintf(stderr, "Too many source files\n"); - - return; - } - - fp = stdin; + FILE *fp = stdin; - if (name) + if ( name ) { - fp = fopen(name, "r"); - - if (fp == NULL) + fp = fopen( name, "r" ); + if ( !fp ) { - perror(name); + errmsg( "%s: %s", name, strerror(errno) ); + return 1; + } - return; + if ( fcntl( fileno(fp), F_SETFD, FD_CLOEXEC ) < 0 ) + { + errmsg( "fcntl: %s: %s", name, strerror(errno) ); + return 1; } } - sourcefiles[sourceCount++] = fp; - - ttyFlag = isatty(fileno(fp)); - - while (TRUE) + for(;;) { - if (ttyFlag) - showPrompt(); + const char *input; - if (intFlag && !ttyFlag && (fp != stdin)) + if ( intFlag && !isatty(fileno(fp)) ) { - fclose(fp); - sourceCount--; + if (fp != stdin) + fclose(fp); - return; + return 128; } - - if (fgets(buf, CMD_LEN - 1, fp) == NULL) - { - if (ferror(fp) && (errno == EINTR)) - { - clearerr(fp); - continue; - } + input = get_line( fp ); - break; + if ( !input ) + { + if ( getpid() == 1 ) + continue; + else + break; } - cc = strlen(buf); - - if (buf[cc - 1] == '\n') - cc--; - - while ((cc > 0) && isBlank(buf[cc - 1])) - cc--; - - buf[cc] = '\0'; - - command(buf); + command( input ); } - if (ferror(fp)) + if ( ferror(fp) ) { - perror("Reading command line"); + errmsg( "error reading command input: %s", strerror(errno) ); if (fp == stdin) exit(1); @@ -606,7 +569,7 @@ readFile(const char * name) if (fp != stdin) fclose(fp); - sourceCount--; + return 0; } @@ -695,45 +658,43 @@ command(const char * cmd) static BOOL tryBuiltIn(const char * cmd) { - const char * endCmd; - const CommandEntry * entry; - int argc; - const char ** argv; - char cmdName[CMD_LEN]; + char *cmdName; + const char *endCmd = cmd; + const CommandEntry *entry; + int argc; + const char *const *argv; /* * 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++; + while ( *endCmd && !isBlank(*endCmd) ) + ++endCmd; + cmdName = alloca( endCmd - cmd + 1 ); 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++) + for ( entry = commandEntryTable; entry->name; ++entry ) { - if (strcmp(entry->name, cmdName) == 0) + if ( !strcmp(entry->name, cmdName) ) break; } /* * If the command is not a built-in, return indicating that. */ - if (entry->name == NULL) + if ( !entry->name ) return FALSE; /* * The command is a built-in. * Break the command up into arguments and expand wildcards. */ - if (!makeArgs(cmd, &argc, &argv)) + if ( !makeArgs(cmd, &argc, &argv) ) return TRUE; /* @@ -742,7 +703,7 @@ tryBuiltIn(const char * cmd) */ if ((argc < entry->minArgs) || (argc > entry->maxArgs)) { - fprintf(stderr, "usage: %s %s\n", entry->name, entry->usage); + errmsg( "usage: %s %s", entry->name, entry->usage); return TRUE; } @@ -818,7 +779,7 @@ runCmd(const char * cmd) if (pid < 0) { - perror("fork failed"); + errmsg( "fork failed: %s", strerror(errno) ); return; } @@ -841,18 +802,15 @@ runCmd(const char * cmd) intCrlf = TRUE; - if (pid < 0) + if ( pid < 0 ) { - fprintf(stderr, "Error from waitpid: %s", strerror(errno)); - + errmsg( "waitpid: %s", strerror(errno) ); return; } - if (WIFSIGNALED(status)) - { - fprintf(stderr, "pid %ld: killed by signal %d\n", - (long) pid, WTERMSIG(status)); - } + if ( WIFSIGNALED(status) ) + errmsg( "%s: %s%s\n", cmd, strsignal(WTERMSIG(status)), + WCOREDUMP(status) ? " (core dumped)" : "" ); } @@ -864,53 +822,37 @@ runCmd(const char * cmd) static void childProcess(const char * cmd) { - const char ** argv; + char *const *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); - } + if ( !makeArgs(cmd, &argc, (const char *const **)&argv) ) + exit( system( cmd ) ); /* * Try to execute the program directly. */ - execvp(argv[0], (char **) argv); + execvp( argv[0], 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); - } + if ( errno == ENOEXEC ) + exit( system( cmd ) ); /* * There was something else wrong, complain and exit. */ - perror(argv[0]); - exit(1); + fatal( "exec: %s: %s", argv[0], strerror(errno) ); } void -do_help(int argc, const char ** argv) +do_help(int argc, const char *const *argv) { const CommandEntry * entry; const char * str; @@ -955,7 +897,7 @@ do_help(int argc, const char ** argv) void -do_alias(int argc, const char ** argv) +do_alias(int argc, const char *const *argv) { const char * name; char * value; @@ -982,14 +924,14 @@ do_alias(int argc, const char ** argv) if (alias) printf("%s\n", alias->value); else - fprintf(stderr, "Alias \"%s\" is not defined\n", name); + errmsg( "alias \"%s\" is not defined", name ); return; } - if (strcmp(name, "alias") == 0) + if ( !strcmp(name, "alias") ) { - fprintf(stderr, "Cannot alias \"alias\"\n"); + errmsg( "cannot alias \"alias\""); return; } @@ -997,17 +939,14 @@ do_alias(int argc, const char ** argv) if (!makeString(argc - 2, argv + 2, buf, CMD_LEN)) return; - value = malloc(strlen(buf) + 1); + value = strdup( buf ); - if (value == NULL) + if ( !value ) { - fprintf(stderr, "No memory for alias value\n"); - + errmsg( "failed to alias \"%s\": %s", name, strerror( errno ) ); return; } - strcpy(value, buf); - alias = findAlias(name); if (alias) @@ -1018,7 +957,7 @@ do_alias(int argc, const char ** argv) return; } - if ((aliasCount % ALIAS_ALLOC) == 0) + if ( !(aliasCount % ALIAS_ALLOC) ) { count = aliasCount + ALIAS_ALLOC; @@ -1030,11 +969,10 @@ do_alias(int argc, const char ** argv) else alias = (Alias *) malloc(sizeof(Alias) * count); - if (alias == NULL) + if ( !alias ) { - free(value); - fprintf(stderr, "No memory for alias table\n"); - + free( value ); + errmsg( "failed to alias \"%s\": %s", name, strerror( errno ) ); return; } @@ -1043,19 +981,17 @@ do_alias(int argc, const char ** argv) alias = &aliasTable[aliasCount]; - alias->name = malloc(strlen(name) + 1); + alias->name = strdup( name ); - if (alias->name == NULL) + if ( !alias->name ) { - free(value); - fprintf(stderr, "No memory for alias name\n"); - + free( value ); + errmsg( "failed to alias \"%s\": %s", name, strerror( errno ) ); return; } - strcpy(alias->name, name); alias->value = value; - aliasCount++; + ++aliasCount; } @@ -1064,25 +1000,22 @@ do_alias(int argc, const char ** argv) * using the names without the dash. */ void -do_aliasall(int argc, const char **argv) +do_aliasall(int argc, const char *const *argv) { - const CommandEntry * entry; - const char * name; - const char * newArgv[4]; + const CommandEntry *entry; - for (entry = commandEntryTable; entry->name; entry++) + for ( entry = commandEntryTable; entry->name; ++entry ) { - name = entry->name; + const char *name = entry->name; if (*name != '-') continue; + else + { + const char *const newArgv[] = { "alias", name + 1, name, NULL }; - newArgv[0] = "alias"; - newArgv[1] = name + 1; - newArgv[2] = name; - newArgv[3] = NULL; - - do_alias(3, newArgv); + do_alias(3, newArgv); + } } } @@ -1110,60 +1043,40 @@ findAlias(const char * name) void -do_source(int argc, const char ** argv) +do_source(int argc, const char *const *argv) { readFile(argv[1]); } void -do_exec(int argc, const char ** argv) +do_exec(int argc, const char *const *argv) { - const char * name; - - name = argv[1]; - - if (access(name, 4)) - { - perror(name); - - return; - } - - while (--sourceCount >= 0) - { - if (sourcefiles[sourceCount] != stdin) - fclose(sourcefiles[sourceCount]); - } - - argv[argc] = NULL; - - execvp(name, (char **) argv + 1); - exit(1); + char *const *av = (char *const *)argv; + const char *const name = av[1]; + execvp( name, av + 1); + errmsg( "exec: %s: %s", name, strerror(errno) ); } void -do_prompt(int argc, const char ** argv) +do_prompt(int argc, const char *const *argv) { char * cp; - char buf[CMD_LEN]; + char buf[1+CMD_LEN]; - if (!makeString(argc - 1, argv + 1, buf, CMD_LEN)) + if (!makeString(argc - 1, argv + 1, buf, sizeof(buf))) return; - cp = malloc(strlen(buf) + 2); + strcat( buf, " " ); + cp = strdup( buf ); - if (cp == NULL) + if ( !cp ) { - fprintf(stderr, "No memory for prompt\n"); - + errmsg( "failed to set prompt: %s", strerror(errno) ); return; } - strcpy(cp, buf); - strcat(cp, " "); - if (prompt) free(prompt); @@ -1172,7 +1085,7 @@ do_prompt(int argc, const char ** argv) void -do_unalias(int argc, const char ** argv) +do_unalias(int argc, const char *const *argv) { Alias * alias; @@ -1192,56 +1105,28 @@ do_unalias(int argc, const char ** argv) } -/* - * Display the prompt string. - */ -static void -showPrompt(void) +static void catchInterrupt( int no ) { - 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); + if ( intCrlf ) + write( STDOUT_FILENO, "\r\n", 2 ); } -static void -catchQuit(int val) +static void print_version( FILE *fp ) { - signal(SIGQUIT, catchQuit); - - intFlag = TRUE; - - if (intCrlf) - write(STDOUT, "\n", 1); + fprintf( fp, "Stand-alone shell (version %s)\n", version ); } - /* * Print the usage information and quit. */ -static void -usage(void) +static void usage( void ) { - fprintf(stderr, "Stand-alone shell (version %s)\n", version); - fprintf(stderr, "\n"); - fprintf(stderr, "Usage: sash [-a] [-q] [-c command] [-p prompt]\n"); + extern const char *__progname; + print_version( stderr ); + fprintf( stderr, "Usage: %s [-a] [-q] [-e] [-c command] [-p prompt] [script]\n", __progname ); exit(1); } --- sash/sash.h +++ sash/sash.h @@ -19,7 +19,7 @@ #include #include #include - +#include #define PATH_LEN 1024 #define CMD_LEN 10240 @@ -52,56 +52,57 @@ typedef int BOOL; /* * 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 void do_alias(int argc, const char *const *argv); +extern void do_aliasall(int argc, const char *const *argv); +extern void do_cd(int argc, const char *const *argv); +extern void do_exec(int argc, const char *const *argv); +extern void do_exit(int argc, const char *const *argv); +extern void do_prompt(int argc, const char *const *argv); +extern void do_source(int argc, const char *const *argv); +extern void do_umask(int argc, const char *const *argv); +extern void do_unalias(int argc, const char *const *argv); +extern void do_help(int argc, const char *const *argv); +extern void do_ln(int argc, const char *const *argv); +extern void do_cp(int argc, const char *const *argv); +extern void do_mv(int argc, const char *const *argv); +extern void do_rm(int argc, const char *const *argv); +extern void do_chmod(int argc, const char *const *argv); +extern void do_mkdir(int argc, const char *const *argv); +extern void do_rmdir(int argc, const char *const *argv); +extern void do_mknod(int argc, const char *const *argv); +extern void do_chown(int argc, const char *const *argv); +extern void do_chgrp(int argc, const char *const *argv); +extern void do_sum(int argc, const char *const *argv); +extern void do_sync(int argc, const char *const *argv); +extern void do_printenv(int argc, const char *const *argv); +extern void do_more(int argc, const char *const *argv); +extern void do_cmp(int argc, const char *const *argv); +extern void do_touch(int argc, const char *const *argv); +extern void do_ls(int argc, const char *const *argv); +extern void do_dd(int argc, const char *const *argv); +extern void do_tar(int argc, const char *const *argv); +extern void do_ar(int argc, const char *const *argv); +extern void do_mount(int argc, const char *const *argv); +extern void do_umount(int argc, const char *const *argv); +extern void do_setenv(int argc, const char *const *argv); +extern void do_pwd(int argc, const char *const *argv); +extern void do_echo(int argc, const char *const *argv); +extern void do_kill(int argc, const char *const *argv); +extern void do_grep(int argc, const char *const *argv); +extern void do_file(int argc, const char *const *argv); +extern void do_find(int argc, const char *const *argv); +extern void do_ed(int argc, const char *const *argv); +extern void do_where(int argc, const char *const *argv); +extern void do_losetup(int argc, const char *const *argv); #ifdef HAVE_GZIP -extern void do_gzip(int argc, const char ** argv); -extern void do_gunzip(int argc, const char ** argv); +extern void do_gzip(int argc, const char *const *argv); +extern void do_gunzip(int argc, const char *const *argv); #endif #ifdef HAVE_EXT2 -extern void do_lsattr(int argc, const char ** argv); -extern void do_chattr(int argc, const char ** argv); +extern void do_lsattr(int argc, const char *const *argv); +extern void do_chattr(int argc, const char *const *argv); #endif @@ -124,13 +125,13 @@ extern const char * buildName (const char * dirName, const char * fileName); extern BOOL makeArgs - (const char * cmd, int * argcPtr, const char *** argvPtr); + (const char * cmd, int * argcPtr, const char *const ** argvPtr); extern BOOL copyFile (const char * srcName, const char * destName, BOOL setModes); extern BOOL makeString - (int argc, const char ** argv, char * buf, int bufLen); + (int argc, const char *const *argv, char * buf, int bufLen); extern int expandWildCards (const char * fileNamePattern, const char *** retFileTable); --- sash/utils.c +++ sash/utils.c @@ -520,7 +520,7 @@ expandWildCards(const char * fileNamePattern, const char *** retFileTable) /* * Return the file list and count. */ - *retFileTable = (const char **) fileTable; + *retFileTable = (const char **)fileTable; return fileCount; } @@ -532,11 +532,11 @@ expandWildCards(const char * fileNamePattern, const char *** retFileTable) int nameSort(const void * p1, const void * p2) { - const char ** s1; - const char ** s2; + const char *const * s1; + const char *const * s2; - s1 = (const char **) p1; - s2 = (const char **) p2; + s1 = (const char *const *) p1; + s2 = (const char *const *) p2; return strcmp(*s1, *s2); } @@ -646,14 +646,14 @@ match(const char * text, const char * pattern) * already output. */ BOOL -makeArgs(const char * cmd, int * retArgc, const char *** retArgv) +makeArgs(const char * cmd, int * retArgc, const char *const ** retArgv) { const char * argument; char * cp; char * cpOut; char * newStrings; - const char ** fileTable; - const char ** newArgTable; + const char **fileTable; + const char **newArgTable; int newArgTableSize; int fileCount; int len; @@ -900,7 +900,7 @@ makeArgs(const char * cmd, int * retArgc, const char *** retArgv) * Copy the new arguments to the end of the old ones. */ memcpy((void *) &argTable[argCount], (const void *) fileTable, - (sizeof(const char **) * fileCount)); + (sizeof(const char *const *) * fileCount)); /* * Add to the argument count. @@ -914,7 +914,7 @@ makeArgs(const char * cmd, int * retArgc, const char *** retArgv) argTable[argCount] = NULL; *retArgc = argCount; - *retArgv = argTable; + *retArgv = (const char *const *)argTable; return TRUE; } @@ -929,7 +929,7 @@ makeArgs(const char * cmd, int * retArgc, const char *** retArgv) BOOL makeString( int argc, - const char ** argv, + const char *const * argv, char * buf, int bufLen )