diff --git a/TODO b/TODO index 43ec289..0966c54 100644 --- a/TODO +++ b/TODO @@ -1,90 +1,108 @@ -Write a Makefile. +Write a Makefile. [done] Add octal escape support to echo. -Rework yes(1) to buffer input. This achieves greater throughput per system call. +Rework yes(1) to buffer output. This achieves greater throughput per system call. -Write the following utilities: - ar - at/atd - basename - batch(?) - bc - cal - cat (done) - chgrp - chmod - chown - cksum - cmp - comm - compress(?) - cp - crond/crontab - csplit - cut - dd - df - diff - dirname - du - ed/x - expand(?) - expr - file - find - fold - fuser - grep - head - iconv - id - join - kill - link(?) - ln - locale - localedef - logname - lp(?) - ls - mesg - mkdir - mkfifo - mknod - mktemp - more - mv - newgrp(?) - nice - nl - paste - pathchk(?) - pax - printf - ps - pwd - renice - rm - rmdir - sed - sh - sleep - sort - split - strings - tabs - tail - talk(?) - tee - test - touch - tput - tr - tsort - uname - uncompress(?) - unexpand - uniq - wc [in progress] - who - write(?) - xargs +----------------------------------------------------- +PROGS +_____________________________________________________ +Simple commands (only a handful of parameters at most, with simple premises) +-sleep [done] +-true [done] +-yes [done] +-basename/dirname +-echo [in-progress, SUS] +-wc [in-progress] +-tee +-cat [done] +-pwd +-cksum +-cal + +Filesystem modifiers +-rm +-mv +-cp +-mkdir +-rmdir +-mktemp +-chgrp +-chown +-chmod +-mkfifo +-mknod +-touch +-ln +-link(?) +-ls +-find +-file + +Filters +-sed +-nl +-tr +-expand/unexpand +-fold +-head/tail +-sort +-grep +-uniq +-cut +-paste +-csplit +-iconv + +Sorting, searching and testing +-test +-cmp +-comm +-diff +-tsort +-du +-df +-join +-split + +System interfaces +-uname +-tput +-who +-ps +-kill +-renice +-nice +-newgrp +-pathchk +-fuser +-id +-tabs +-lp +-locale +-localedef +-at/atd +-batch +-crond +-crontab +-logname + +Binary utilities +-ar +-tar +-pax +-od +-dd +-compress +-expand +-strings + +Interactive utilities +-ed +-bc +-sh + +Miscellaneous +-xargs +-mesg [maybe] +-write [maybe] +-printf +-expr diff --git a/src/Makefile b/src/Makefile index 3f5f94d..b37ae74 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,16 +6,18 @@ LDFLAGS = -static LDLIBS = PREFIX = usr/local DESTDIR = -BIN = echo yes true false cat +BIN = cat\ + false\ + sleep\ + true\ + yes\ + echo\ + wc\ + all: ${BIN} -echo: echo.c -wc: wc.c -yes: yes.c -true: true.c -false: +false: true ln -s true false -cat: cat.c install: all install -Dm0755 ${BIN} ${DESTDIR}/${PREFIX}/bin diff --git a/src/sleep.c b/src/sleep.c new file mode 100644 index 0000000..039a4b8 --- /dev/null +++ b/src/sleep.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include + + +#include "support.h" + + +int main(int argc, char **argv) + { + int i; + i = 0; + + + if(argc != 2) + { + throw(NEEDARG_FAIL, mastrcat(argv[0], " int")); + } + + i = (int) (strtol(argv[1], (char **) NULL, 10)); + if(errno == ERANGE) + { + throw(TIME_FAIL, mastrcat(argv[0], " ERANGE error.")); + } + if(i < 0) + { + throw(MISC_FAIL, mastrcat(argv[0], ": need positive number.")); + } + + + sleep(i); + + + exit(0); + } diff --git a/src/support.h b/src/support.h index b655b5e..c259a62 100644 --- a/src/support.h +++ b/src/support.h @@ -11,7 +11,9 @@ enum { MALLOC_FAIL, NEEDARG_FAIL, FOPEN_FAIL, - WRITE_FAIL + WRITE_FAIL, + TIME_FAIL, + MISC_FAIL }; @@ -54,6 +56,10 @@ void throw(long unsigned int condition, void *info) exit(FOPEN_FAIL); case WRITE_FAIL: printf("failed to write: %s\n", (char *) info); exit(WRITE_FAIL); + case TIME_FAIL: printf("time error: %s\n", (char *) info); + exit(TIME_FAIL); + case MISC_FAIL: printf("%s\n", (char *) info); + exit(MISC_FAIL); default: printf("You shouldn't be seeing this.\nSomething is very wrong.\n"); exit(-256); } diff --git a/src/wc.c b/src/wc.c new file mode 100644 index 0000000..267b5aa --- /dev/null +++ b/src/wc.c @@ -0,0 +1,126 @@ +/* wc.c -- program to count and display the number of lines, words and one of bytes or characters in the named files */ + + +#include +#include +#include +#include + +#include "support.h" + + +enum + { + C, + M, + L, + W, + OUTWORD, + INWORD, + /* character or byte */ + COB = 0, + WORDS = 1, + LINES = 2, + }; + + +int main(int argc, char **argv) + { + char state; + int c, i; + + char par[4] = {1}; + /* M and C conflict; M counts actual characters (theoretically), so we should go with that as the default */ + par[C] = 0; + int count[3] = {0}; + int total[3] = {0}; + FILE *fd; + + state = OUTWORD; + c = i = 0; + + fd = 0; + + + /* process our parameters */ + for(; (c = getopt(argc, argv, "cmlw")) != -1; c = 0) + { + switch(c) + { + case 'c': par[C] = 1; + par[M] = 0; + break; + case 'm': par[M] = 1; + par[C] = 0; + break; + case 'l': par[L] = 1; + break; + case 'w': par[W] = 1; + break; + /* Fall-through to default from ':' */ + case ':': + case '?': + default: throw(NEEDARG_FAIL, mastrcat(argv[0], "[-c|-m] [-lw] [file ...]")); + break; + } + } + + + + /* for every file we're given... */ + for(fd = 0, i = optind; i < argc; fclose(fd), i++) + { + /* ...open our file... */ + if( !(fd = fopen(argv[i], "r"))) + { + printf("%d %d\n", i, optind); + exit(1); + } + + /* ...then read until EOF... */ + for(c = 0; (c = fgetc(fd)) != EOF;) + { + /* ...and count the goods as we go. */ + if(!(isblank(c) || c == '\n')) + { + if(state == OUTWORD) + { + count[WORDS]++; + } + + state = INWORD; + } + else + { + if(c == '\n') + { + count[LINES]++; + } + + state = OUTWORD; + } + + count[COB]++; + } + + /* ...then print our total and reset. */ + printf("%d %d %d %s\n", count[LINES], count[WORDS], count[COB], argv[i]); + + total[COB] += count[COB]; + total[WORDS] += count[WORDS]; + total[LINES] += count[LINES]; + + count[COB] = 0; + count[WORDS] = 0; + count[LINES] = 0; + } + + + if((argc-optind) > 1) + { + printf("%d %d %d total\n", total[LINES], total[WORDS], total[COB]); + } + + + exit(0); + }