uuprog

changeset 0:4f628556fa3e tip

uuprog initial commit
author John Tsiombikas <nuclear@member.fsf.org>
date Thu, 25 Aug 2011 08:53:01 +0300
parents
children
files .hgignore Makefile cat.c configure cp.c echo.c false.c ls.c mkdir.c pwd.c rm.c rmdir.c sleep.c sort.c tee.c true.c uname.c
diffstat 17 files changed, 948 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/.hgignore	Thu Aug 25 08:53:01 2011 +0300
     1.3 @@ -0,0 +1,3 @@
     1.4 +\.d$
     1.5 +\.o$
     1.6 +\.swp$
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/Makefile	Thu Aug 25 08:53:01 2011 +0300
     2.3 @@ -0,0 +1,28 @@
     2.4 +CC = gcc
     2.5 +CFLAGS = -pedantic -Wall -g
     2.6 +
     2.7 +.PHONY: all
     2.8 +all: cat cp echo false ls mkdir pwd rm rmdir sleep sort tee true uname
     2.9 +
    2.10 +cat: cat.o
    2.11 +cp: cp.o
    2.12 +echo: echo.o
    2.13 +false: false.o
    2.14 +ls: ls.o
    2.15 +mkdir: mkdir.o
    2.16 +pwd: pwd.o
    2.17 +rm: rm.o
    2.18 +rmdir: rmdir.o
    2.19 +sleep: sleep.o
    2.20 +sort: sort.o
    2.21 +tee: tee.o
    2.22 +true: true.o
    2.23 +uname: uname.o
    2.24 +
    2.25 +.PHONY: clean
    2.26 +clean:
    2.27 +	rm -f cat cp echo false ls mkdir pwd rm rmdir sleep sort tee true uname *.o
    2.28 +
    2.29 +.PHONY: distclean
    2.30 +distclean: clean
    2.31 +	rm -f Makefile
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/cat.c	Thu Aug 25 08:53:01 2011 +0300
     3.3 @@ -0,0 +1,23 @@
     3.4 +/*! cc -o cat cat.c */
     3.5 +#include <stdio.h>
     3.6 +#include <string.h>
     3.7 +#include <errno.h>
     3.8 +
     3.9 +int main(int argc, char **argv)
    3.10 +{
    3.11 +	char buf[4096];
    3.12 +	size_t rbytes;
    3.13 +	FILE *fp;
    3.14 +
    3.15 +	while(*++argv) {
    3.16 +		if(!(fp = fopen(*argv, "rb"))) {
    3.17 +			fprintf(stderr, "cat: %s: %s\n", *argv, strerror(errno));
    3.18 +		} else {
    3.19 +			while((rbytes = fread(buf, 1, sizeof buf, fp)) > 0) {
    3.20 +				fwrite(buf, 1, rbytes, stdout);
    3.21 +			}
    3.22 +			fclose(fp);
    3.23 +		}
    3.24 +	}
    3.25 +	return 0;
    3.26 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/configure	Thu Aug 25 08:53:01 2011 +0300
     4.3 @@ -0,0 +1,27 @@
     4.4 +#!/bin/sh
     4.5 +
     4.6 +echo 'CC = gcc' >Makefile
     4.7 +echo 'CFLAGS = -pedantic -Wall -g' >>Makefile
     4.8 +echo >>Makefile
     4.9 +
    4.10 +allfiles=`echo *.c | sed 's/\.c//g'`
    4.11 +
    4.12 +echo '.PHONY: all' >>Makefile
    4.13 +echo "all: $allfiles" >>Makefile
    4.14 +echo >>Makefile
    4.15 +
    4.16 +for i in *.c; do
    4.17 +	bname=`basename $i .c`
    4.18 +
    4.19 +	echo "$bname: $bname.o" >>Makefile
    4.20 +done
    4.21 +
    4.22 +echo >>Makefile
    4.23 +echo '.PHONY: clean' >>Makefile
    4.24 +echo 'clean:' >>Makefile
    4.25 +echo "	rm -f $allfiles *.o" >>Makefile
    4.26 +
    4.27 +echo >>Makefile
    4.28 +echo '.PHONY: distclean' >>Makefile
    4.29 +echo 'distclean: clean' >>Makefile
    4.30 +echo '	rm -f Makefile' >>Makefile
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/cp.c	Thu Aug 25 08:53:01 2011 +0300
     5.3 @@ -0,0 +1,60 @@
     5.4 +/*! cc -o cp cp.c */
     5.5 +#include <stdio.h>
     5.6 +#include <string.h>
     5.7 +#include <errno.h>
     5.8 +#include <unistd.h>
     5.9 +#include <sys/types.h>
    5.10 +#include <sys/stat.h>
    5.11 +
    5.12 +int copy_file(const char *sname, const char *dname);
    5.13 +
    5.14 +char buf[4096];
    5.15 +
    5.16 +int main(int argc, char **argv)
    5.17 +{
    5.18 +	int i, src_count = argc - 2;
    5.19 +
    5.20 +	if(src_count > 1) {
    5.21 +		struct stat st;
    5.22 +		char *to_dir = argv[argc - 1];
    5.23 +
    5.24 +		if(stat(to_dir, &st) == -1) {
    5.25 +			fprintf(stderr, "failed to stat %s: %s\n", to_dir, strerror(errno));
    5.26 +			return 1;
    5.27 +		}
    5.28 +
    5.29 +		for(i=0; i<src_count; i++) {
    5.30 +			sprintf(buf, "%s/%s", to_dir, argv[i+1]);
    5.31 +			if(copy_file(argv[i+1], buf) == -1) {
    5.32 +				return 1;
    5.33 +			}
    5.34 +		}
    5.35 +		return 0;
    5.36 +	}
    5.37 +	
    5.38 +	return copy_file(argv[1], argv[2]) == -1 ? 1 : 0;
    5.39 +}
    5.40 +
    5.41 +int copy_file(const char *sname, const char *dname)
    5.42 +{
    5.43 +	FILE *src, *dst;
    5.44 +	size_t brd;
    5.45 +
    5.46 +	if(!(src = fopen(sname, "rb"))) {
    5.47 +		fprintf(stderr, "failed to open source file %s: %s\n", sname, strerror(errno));
    5.48 +		return -1;
    5.49 +	}
    5.50 +	if(!(dst = fopen(dname, "wb"))) {
    5.51 +		fclose(src);
    5.52 +		fprintf(stderr, "failed to open destination file %s: %s\n", dname, strerror(errno));
    5.53 +		return -1;
    5.54 +	}
    5.55 +
    5.56 +	while((brd = fread(buf, 1, sizeof buf, src)) > 0) {
    5.57 +		fwrite(buf, 1, brd, dst);
    5.58 +	}
    5.59 +
    5.60 +	fclose(dst);
    5.61 +	fclose(src);
    5.62 +	return 0;
    5.63 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/echo.c	Thu Aug 25 08:53:01 2011 +0300
     6.3 @@ -0,0 +1,14 @@
     6.4 +/*! cc -o echo echo.c */
     6.5 +#include <stdio.h>
     6.6 +
     6.7 +int main(int argc, char **argv)
     6.8 +{
     6.9 +	while(*++argv) {
    6.10 +		fputs(*argv, stdout);
    6.11 +		if(*(argv + 1)) {
    6.12 +			putchar(' ');
    6.13 +		}
    6.14 +	}
    6.15 +	putchar('\n');
    6.16 +	return 0;
    6.17 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/false.c	Thu Aug 25 08:53:01 2011 +0300
     7.3 @@ -0,0 +1,5 @@
     7.4 +/*! cc -o false false.c */
     7.5 +int main(void)
     7.6 +{
     7.7 +	return 1;
     7.8 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/ls.c	Thu Aug 25 08:53:01 2011 +0300
     8.3 @@ -0,0 +1,313 @@
     8.4 +/*! gcc -pedantic -Wall -g -o ls ls.c */
     8.5 +#include <stdio.h>
     8.6 +#include <stdlib.h>
     8.7 +#include <string.h>
     8.8 +#include <errno.h>
     8.9 +#include <time.h>
    8.10 +#include <unistd.h>
    8.11 +#include <fcntl.h>
    8.12 +#include <dirent.h>
    8.13 +#include <pwd.h>
    8.14 +#include <grp.h>
    8.15 +#include <sys/types.h>
    8.16 +#include <sys/stat.h>
    8.17 +
    8.18 +enum {SORT_NONE, SORT_NAME};
    8.19 +
    8.20 +enum {
    8.21 +	OPT_LONG	= 1,
    8.22 +	OPT_ALL		= 2,
    8.23 +	OPT_DIR		= 4,
    8.24 +	OPT_CLASS	= 8,
    8.25 +	OPT_HUMAN	= 16,
    8.26 +	OPT_INODES	= 32
    8.27 +};
    8.28 +
    8.29 +int proc_opt(char opt);
    8.30 +int ls_dir(char *dir);
    8.31 +
    8.32 +unsigned int flags = 0;
    8.33 +int sort_by = SORT_NAME;
    8.34 +int term_col = 80;	/* TODO: detect columns */
    8.35 +
    8.36 +int main(int argc, char **argv)
    8.37 +{
    8.38 +	int i, did_one = 0;
    8.39 +
    8.40 +	for(i=1; i<argc; i++) {
    8.41 +		if(argv[i][0] == '-') {
    8.42 +			char *ptr = argv[i] + 1;
    8.43 +			while(ptr && *ptr) {
    8.44 +				if(proc_opt(*ptr++) == -1) {
    8.45 +					fprintf(stderr, "%s: invalid option -- %c\n", argv[0], *(ptr - 1));
    8.46 +					return 1;
    8.47 +				}
    8.48 +			}
    8.49 +		} else {
    8.50 +			printf("%s:\n", argv[i]);
    8.51 +			if(ls_dir(argv[i]) == -1) {
    8.52 +				fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno));
    8.53 +			}
    8.54 +			did_one = 1;
    8.55 +		}
    8.56 +	}
    8.57 +
    8.58 +	if(!did_one) {
    8.59 +		ls_dir(".");
    8.60 +	}
    8.61 +
    8.62 +	return 0;
    8.63 +}
    8.64 +
    8.65 +int proc_opt(char opt)
    8.66 +{
    8.67 +	switch(opt) {
    8.68 +	case 'a':
    8.69 +		flags |= OPT_ALL;
    8.70 +		break;
    8.71 +
    8.72 +	case 'l':
    8.73 +		flags |= OPT_LONG;
    8.74 +		break;
    8.75 +
    8.76 +	case 'F':
    8.77 +		flags |= OPT_CLASS;
    8.78 +		break;
    8.79 +
    8.80 +	case 'h':
    8.81 +		flags |= OPT_HUMAN;
    8.82 +		break;
    8.83 +
    8.84 +	case 'i':
    8.85 +		flags |= OPT_INODES;
    8.86 +		break;
    8.87 +
    8.88 +	default:
    8.89 +		return -1;
    8.90 +	}
    8.91 +	return 0;
    8.92 +}
    8.93 +
    8.94 +struct entry {
    8.95 +	char *name;
    8.96 +	struct stat st;
    8.97 +	struct entry *next;
    8.98 +};
    8.99 +
   8.100 +int print_entry(struct entry *ent)
   8.101 +{
   8.102 +	int len = strlen(ent->name);
   8.103 +
   8.104 +	if(flags & OPT_LONG) {
   8.105 +		int i;
   8.106 +		struct passwd *pwd;
   8.107 +		struct group *grp;
   8.108 +		char tmbuf[128];
   8.109 +
   8.110 +		switch(ent->st.st_mode & S_IFMT) {
   8.111 +		case S_IFSOCK:
   8.112 +			putchar('s');
   8.113 +			break;
   8.114 +		case S_IFLNK:
   8.115 +			putchar('l');
   8.116 +			break;
   8.117 +		case S_IFBLK:
   8.118 +			putchar('b');
   8.119 +			break;
   8.120 +		case S_IFDIR:
   8.121 +			putchar('d');
   8.122 +			break;
   8.123 +		case S_IFCHR:
   8.124 +			putchar('c');
   8.125 +			break;
   8.126 +		case S_IFIFO:
   8.127 +			putchar('f');
   8.128 +			break;
   8.129 +		default:
   8.130 +			putchar('-');
   8.131 +		}
   8.132 +
   8.133 +		for(i=0; i<3; i++) {
   8.134 +			int s = (2 - i) * 3;
   8.135 +			unsigned int val = (ent->st.st_mode >> s) & 7;
   8.136 +
   8.137 +			putchar(val & 4 ? 'r' : '-');
   8.138 +			putchar(val & 2 ? 'w' : '-');
   8.139 +			putchar(val & 1 ? 'x' : '-');
   8.140 +		}
   8.141 +		printf(" %3d ", (int)ent->st.st_nlink);
   8.142 +
   8.143 +		if(!(pwd = getpwuid(ent->st.st_uid))) {
   8.144 +			printf("%d ", ent->st.st_uid);
   8.145 +		} else {
   8.146 +			printf("%s ", pwd->pw_name);
   8.147 +		}
   8.148 +		if(!(grp = getgrgid(ent->st.st_gid))) {
   8.149 +			printf("%d ", ent->st.st_gid);
   8.150 +		} else {
   8.151 +			printf("%s ", grp->gr_name);
   8.152 +		}
   8.153 +
   8.154 +		sprintf(tmbuf, "%s", ctime(&ent->st.st_mtime));
   8.155 +		tmbuf[strlen(tmbuf) - 1] = 0;
   8.156 +
   8.157 +		printf("%6ld %s ", (long)ent->st.st_size, tmbuf);
   8.158 +	}
   8.159 +
   8.160 +	fputs(ent->name, stdout);
   8.161 +
   8.162 +	if(flags & OPT_CLASS) {
   8.163 +		if(S_ISDIR(ent->st.st_mode)) {
   8.164 +			putchar('/');
   8.165 +			len++;
   8.166 +		} else if(ent->st.st_mode & S_IXUSR) {
   8.167 +			putchar('*');
   8.168 +			len++;
   8.169 +		}
   8.170 +	}
   8.171 +
   8.172 +	return len;
   8.173 +}
   8.174 +
   8.175 +void print_list(struct entry *arr, int count)
   8.176 +{
   8.177 +	int i, j, ncol, longest = 0;
   8.178 +
   8.179 +	for(i=0; i<count; i++) {
   8.180 +		int len = strlen(arr[i].name) + 2;
   8.181 +		if(len > longest) {
   8.182 +			longest = len;
   8.183 +		}
   8.184 +	}
   8.185 +
   8.186 +	if(isatty(1) && !(flags & OPT_LONG)) {
   8.187 +		ncol = term_col / longest;
   8.188 +		if(!ncol) ncol = 1;
   8.189 +	} else {
   8.190 +		ncol = 1;
   8.191 +	}
   8.192 +
   8.193 +	for(i=0; i<count; i++) {
   8.194 +		int len;
   8.195 +
   8.196 +		len = print_entry(&arr[i]);
   8.197 +
   8.198 +		if(i < count - 1 && (i % ncol) == ncol - 1) {
   8.199 +			putchar('\n');
   8.200 +		} else {
   8.201 +			for(j=0; j<longest - len; j++) {
   8.202 +				putchar(' ');
   8.203 +			}
   8.204 +		}
   8.205 +	}
   8.206 +	putchar('\n');
   8.207 +}
   8.208 +
   8.209 +int cmp_func(const void *e1, const void *e2)
   8.210 +{
   8.211 +	const struct entry *ent1, *ent2;
   8.212 +	const char *n1, *n2;
   8.213 +
   8.214 +	ent1 = e1;
   8.215 +	ent2 = e2;
   8.216 +
   8.217 +	switch(sort_by) {
   8.218 +	case SORT_NAME:
   8.219 +	default:
   8.220 +		n1 = ent1->name;
   8.221 +		n2 = ent2->name;
   8.222 +	}
   8.223 +	return strcmp(n1, n2);
   8.224 +}
   8.225 +
   8.226 +int ls_dir(char *dname)
   8.227 +{
   8.228 +	int i, cwd_fd = -1, saved_err, ent_count = 0;
   8.229 +	DIR *dir = 0;
   8.230 +	struct dirent *ent = 0;
   8.231 +	struct entry *earr = 0, *elist = 0, *enode = 0;
   8.232 +
   8.233 +
   8.234 +	if(strcmp(dname, ".") != 0) {
   8.235 +		if((cwd_fd = open(".", O_RDONLY)) == -1) {
   8.236 +			goto err;
   8.237 +		}
   8.238 +		chdir(dname);
   8.239 +	}
   8.240 +
   8.241 +	if(!(dir = opendir("."))) {
   8.242 +		goto err;
   8.243 +	}
   8.244 +
   8.245 +	if(!(elist = malloc(sizeof *elist))) {
   8.246 +		goto err;
   8.247 +	}
   8.248 +	elist->name = 0;
   8.249 +	elist->next = 0;
   8.250 +
   8.251 +	while((ent = readdir(dir))) {
   8.252 +		struct stat st;
   8.253 +
   8.254 +		if(ent->d_name[0] == '.' && !(flags & OPT_ALL)) {
   8.255 +			continue;
   8.256 +		}
   8.257 +
   8.258 +		if(lstat(ent->d_name, &st) == -1) {
   8.259 +			goto err;
   8.260 +		}
   8.261 +
   8.262 +		if(!(enode = malloc(sizeof *enode))) {
   8.263 +			goto err;
   8.264 +		}
   8.265 +		if(!(enode->name = malloc(strlen(ent->d_name) + 1))) {
   8.266 +			goto err;
   8.267 +		}
   8.268 +		strcpy(enode->name, ent->d_name);
   8.269 +		memcpy(&enode->st, &st, sizeof st);
   8.270 +
   8.271 +		enode->next = elist->next;
   8.272 +		elist->next = enode;
   8.273 +		ent_count++;
   8.274 +	}
   8.275 +	closedir(dir);
   8.276 +	dir = 0;
   8.277 +
   8.278 +	/* change the list into an array, don't feel like writing list mergesorts */
   8.279 +	if(!(earr = malloc(ent_count * sizeof *earr))) {
   8.280 +		goto err;
   8.281 +	}
   8.282 +
   8.283 +	i = 0;
   8.284 +	enode = elist->next;
   8.285 +	while(enode) {
   8.286 +		earr[i].name = enode->name;
   8.287 +		earr[i++].st = enode->st;
   8.288 +		enode = enode->next;
   8.289 +	}
   8.290 +	if(sort_by != SORT_NONE) {
   8.291 +		qsort(earr, ent_count, sizeof *earr, cmp_func);
   8.292 +	}
   8.293 +
   8.294 +	print_list(earr, ent_count);
   8.295 +
   8.296 +	if(cwd_fd != -1) {
   8.297 +		fchdir(cwd_fd);
   8.298 +	}
   8.299 +	return 0;
   8.300 +
   8.301 +err:
   8.302 +	saved_err = errno;
   8.303 +	free(earr);
   8.304 +	/*free_entry_list(elist);*/
   8.305 +	free(enode->name);
   8.306 +	free(enode);
   8.307 +	if(dir) {
   8.308 +		closedir(dir);
   8.309 +	}
   8.310 +	if(cwd_fd != -1) {
   8.311 +		fchdir(cwd_fd);
   8.312 +		close(cwd_fd);
   8.313 +	}
   8.314 +	errno = saved_err;
   8.315 +	return -1;
   8.316 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/mkdir.c	Thu Aug 25 08:53:01 2011 +0300
     9.3 @@ -0,0 +1,18 @@
     9.4 +/*! cc -o mkdir mkdir.c */
     9.5 +#include <stdio.h>
     9.6 +#include <unistd.h>
     9.7 +#include <sys/stat.h>
     9.8 +
     9.9 +int main(int argc, char **argv)
    9.10 +{
    9.11 +	if(argc < 2) {
    9.12 +		fprintf(stderr, "must supply the directory name as argument\n");
    9.13 +		return 1;
    9.14 +	}
    9.15 +
    9.16 +	if(mkdir(argv[1], 0755) == -1) {
    9.17 +		perror("mkdir failed");
    9.18 +		return 1;
    9.19 +	}
    9.20 +	return 0;
    9.21 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/pwd.c	Thu Aug 25 08:53:01 2011 +0300
    10.3 @@ -0,0 +1,39 @@
    10.4 +/*! gcc -std=c89 -pedantic -Wall -o pwd pwd.c */
    10.5 +#include <stdio.h>
    10.6 +#include <stdlib.h>
    10.7 +#include <string.h>
    10.8 +#include <errno.h>
    10.9 +#include <unistd.h>
   10.10 +
   10.11 +int main(void)
   10.12 +{
   10.13 +	char *tmp, *wdbuf;
   10.14 +	size_t bufsz = 64;
   10.15 +
   10.16 +	if(!(wdbuf = malloc(bufsz))) {
   10.17 +		perror("malloc failed");
   10.18 +		return 1;
   10.19 +	}
   10.20 +
   10.21 +	while(!(tmp = getcwd(wdbuf, bufsz)) && errno == ERANGE) {
   10.22 +		size_t newsz = bufsz ? bufsz * 2 : 2;
   10.23 +
   10.24 +		if(!(tmp = realloc(wdbuf, newsz))) {
   10.25 +			fprintf(stderr, "failed to allocate: %u bytes: %s\n", (unsigned int)newsz, strerror(errno));
   10.26 +			free(wdbuf);
   10.27 +			return 1;
   10.28 +		}
   10.29 +		wdbuf = tmp;
   10.30 +		bufsz = newsz;
   10.31 +	}
   10.32 +
   10.33 +	if(!tmp) {
   10.34 +		perror("getcwd failed");
   10.35 +		free(wdbuf);
   10.36 +		return 1;
   10.37 +	}
   10.38 +
   10.39 +	puts(wdbuf);
   10.40 +	free(wdbuf);
   10.41 +	return 0;
   10.42 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/rm.c	Thu Aug 25 08:53:01 2011 +0300
    11.3 @@ -0,0 +1,154 @@
    11.4 +/*! cc -o rm rm.c */
    11.5 +#include <stdio.h>
    11.6 +#include <stdlib.h>
    11.7 +#include <string.h>
    11.8 +#include <signal.h>
    11.9 +#include <stdarg.h>
   11.10 +#include <errno.h>
   11.11 +#include <unistd.h>
   11.12 +#include <dirent.h>
   11.13 +#include <sys/stat.h>
   11.14 +
   11.15 +int rm(const char *path);
   11.16 +int rec_rm(const char *path);
   11.17 +char askuser(const char *fmt, ...);
   11.18 +void sigfunc(int sig);
   11.19 +
   11.20 +int ask, stop_proc, force, rec, verbose;
   11.21 +
   11.22 +int main(int argc, char **argv)
   11.23 +{
   11.24 +	int i;
   11.25 +
   11.26 +	signal(SIGINT, sigfunc);
   11.27 +
   11.28 +	for(i=1; i<argc; i++) {
   11.29 +		if(!stop_proc && argv[i][0] == '-' && argv[i][2] == 0) {
   11.30 +			switch(argv[i][1]) {
   11.31 +			case 'f':
   11.32 +				force = 1;
   11.33 +				break;
   11.34 +
   11.35 +			case '-':
   11.36 +				stop_proc = 1;
   11.37 +				break;
   11.38 +
   11.39 +			case 'i':
   11.40 +				ask = 1;
   11.41 +				break;
   11.42 +
   11.43 +			case 'r':
   11.44 +			case 'R':
   11.45 +				rec = 1;
   11.46 +				break;
   11.47 +
   11.48 +			case 'v':
   11.49 +				verbose = 1;
   11.50 +				break;
   11.51 +
   11.52 +			default:
   11.53 +				fprintf(stderr, "invalid option: %s\n", argv[i]);
   11.54 +				return 1;
   11.55 +			}
   11.56 +		} else {
   11.57 +
   11.58 +			if(rm(argv[i]) == -1) {
   11.59 +				return 1;
   11.60 +			}
   11.61 +		}
   11.62 +	}
   11.63 +
   11.64 +	return 0;
   11.65 +}
   11.66 +
   11.67 +char askuser(const char *fmt, ...)
   11.68 +{
   11.69 +	int c, resp;
   11.70 +	va_list ap;
   11.71 +
   11.72 +	va_start(ap, fmt);
   11.73 +	vprintf(fmt, ap);
   11.74 +	va_end(ap);
   11.75 +
   11.76 +	resp = getchar();
   11.77 +	do {
   11.78 +		c = getchar();
   11.79 +	} while(c != '\n' && c != -1);
   11.80 +
   11.81 +	return resp;
   11.82 +}
   11.83 +
   11.84 +int rm(const char *path)
   11.85 +{
   11.86 +	if(ask) {
   11.87 +		char c = askuser("remove file `%s'? ", path);
   11.88 +
   11.89 +		if(c != 'y' && c != 'Y') {
   11.90 +			return 0;
   11.91 +		}
   11.92 +	}
   11.93 +
   11.94 +	if(unlink(path) == -1) {
   11.95 +		if((errno != EISDIR || rec_rm(path) == -1) && !force) {
   11.96 +			fprintf(stderr, "cannot remove \"%s\": %s\n", path, strerror(errno));
   11.97 +			return -1;
   11.98 +		}
   11.99 +	} else {
  11.100 +		if(verbose) {
  11.101 +			printf("removed `%s'\n", path);
  11.102 +		}
  11.103 +	}
  11.104 +	return 0;
  11.105 +}
  11.106 +
  11.107 +int rec_rm(const char *path)
  11.108 +{
  11.109 +	DIR *dir;
  11.110 +	struct dirent *dent;
  11.111 +
  11.112 +	if(ask) {
  11.113 +		char c = askuser("descend into directory `%s'? ", path);
  11.114 +
  11.115 +		if(c != 'y' && c != 'Y') {
  11.116 +			return 0;
  11.117 +		}
  11.118 +	}
  11.119 +
  11.120 +	if(!(dir = opendir(path))) {
  11.121 +		return force ? 0 : -1;
  11.122 +	}
  11.123 +
  11.124 +	while((dent = readdir(dir))) {
  11.125 +		struct stat st;
  11.126 +
  11.127 +		if(stat(dent->d_name, &st) == -1) {
  11.128 +			if(force) continue;
  11.129 +			closedir(dir);
  11.130 +			return -1;
  11.131 +		}
  11.132 +
  11.133 +		if(S_ISDIR(st.st_mode)) {
  11.134 +			if(rec_rm(dent->d_name) == -1) {
  11.135 +				closedir(dir);
  11.136 +				return -1;
  11.137 +			}
  11.138 +		} else {
  11.139 +			if(rm(dent->d_name) == -1) {
  11.140 +				closedir(dir);
  11.141 +				return -1;
  11.142 +			}
  11.143 +		}
  11.144 +	}
  11.145 +
  11.146 +	if(verbose) {
  11.147 +		printf("removed directory: `%s'\n", path);
  11.148 +	}
  11.149 +
  11.150 +	closedir(dir);
  11.151 +	return 0;
  11.152 +}
  11.153 +
  11.154 +void sigfunc(int sig)
  11.155 +{
  11.156 +	exit(1);
  11.157 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/rmdir.c	Thu Aug 25 08:53:01 2011 +0300
    12.3 @@ -0,0 +1,15 @@
    12.4 +/*! cc -o rmdir rmdir.c */
    12.5 +#include <stdio.h>
    12.6 +#include <unistd.h>
    12.7 +
    12.8 +int main(int argc, char **argv)
    12.9 +{
   12.10 +	int i;
   12.11 +	for(i=1; i<argc; i++) {
   12.12 +		if(rmdir(argv[i]) == -1) {
   12.13 +			perror("failed to remove directory");
   12.14 +			return 1;
   12.15 +		}
   12.16 +	}
   12.17 +	return 0;
   12.18 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/sleep.c	Thu Aug 25 08:53:01 2011 +0300
    13.3 @@ -0,0 +1,20 @@
    13.4 +/*! cc -o sleep sleep.c */
    13.5 +#include <stdio.h>
    13.6 +#include <stdlib.h>
    13.7 +#include <ctype.h>
    13.8 +#include <unistd.h>
    13.9 +
   13.10 +int main(int argc, char **argv)
   13.11 +{
   13.12 +	if(argc < 2) {
   13.13 +		puts("seconds argument missing...");
   13.14 +		return 1;
   13.15 +	}
   13.16 +	if(!isdigit(argv[1][0])) {
   13.17 +		fprintf(stderr, "invalid argument: %s\n", argv[1]);
   13.18 +		return 1;
   13.19 +	}
   13.20 +	
   13.21 +	sleep(atoi(argv[1]));
   13.22 +	return 0;
   13.23 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/sort.c	Thu Aug 25 08:53:01 2011 +0300
    14.3 @@ -0,0 +1,95 @@
    14.4 +/*! cc -o sort sort.c */
    14.5 +#include <stdio.h>
    14.6 +#include <stdlib.h>
    14.7 +#include <string.h>
    14.8 +
    14.9 +struct lnode {
   14.10 +	char *line;
   14.11 +	struct lnode *next;
   14.12 +};
   14.13 +
   14.14 +struct lnode *get_line(void);
   14.15 +int cmp(const void *a, const void *b);
   14.16 +
   14.17 +int main(void)
   14.18 +{
   14.19 +	struct lnode *tmp, *list = 0;
   14.20 +	char **arr;
   14.21 +	size_t i, line_count = 0;
   14.22 +	
   14.23 +	while((tmp = get_line())) {
   14.24 +		if(list) {
   14.25 +			tmp->next = list;
   14.26 +			list = tmp;
   14.27 +		} else {
   14.28 +			list = tmp;
   14.29 +		}
   14.30 +		line_count++;
   14.31 +	}
   14.32 +
   14.33 +	if(!(arr = malloc(line_count * sizeof *arr))) {
   14.34 +		perror("malloc failed");
   14.35 +		return 1;
   14.36 +	}
   14.37 +
   14.38 +	for(i=0; i<line_count; i++) {
   14.39 +		arr[i] = list->line;
   14.40 +
   14.41 +		tmp = list;
   14.42 +		list = list->next;
   14.43 +		free(tmp);
   14.44 +	}
   14.45 +
   14.46 +	qsort(arr, line_count, sizeof *arr, cmp);
   14.47 +
   14.48 +	for(i=0; i<line_count; i++) {
   14.49 +		puts(arr[i]);
   14.50 +		free(arr[i]);
   14.51 +	}
   14.52 +	free(arr);
   14.53 +	return 0;
   14.54 +}
   14.55 +
   14.56 +struct lnode *get_line(void)
   14.57 +{
   14.58 +	struct lnode *node;
   14.59 +	char *buf;
   14.60 +	size_t bufsz = 128;
   14.61 +	size_t used_buf = 0;
   14.62 +	int c;
   14.63 +
   14.64 +	if(!(buf = malloc(bufsz))) {
   14.65 +		perror("malloc failed");
   14.66 +		exit(1);
   14.67 +	}
   14.68 +
   14.69 +	while((c = getchar()) >= 0 && c != '\n') {
   14.70 +		if(used_buf >= bufsz - 1) {
   14.71 +			size_t newsz = bufsz * 2;
   14.72 +			if(!(buf = realloc(buf, newsz))) {
   14.73 +				perror("malloc failed");
   14.74 +				exit(1);
   14.75 +			}
   14.76 +			bufsz = newsz;
   14.77 +		}
   14.78 +		buf[used_buf++] = c;
   14.79 +	}
   14.80 +	buf[used_buf] = 0;
   14.81 +
   14.82 +	if(!used_buf) {
   14.83 +		return 0;
   14.84 +	}
   14.85 +
   14.86 +	if(!(node = malloc(sizeof *node))) {
   14.87 +		perror("malloc failed");
   14.88 +		exit(1);
   14.89 +	}
   14.90 +	node->line = buf;
   14.91 +	node->next = 0;
   14.92 +	return node;
   14.93 +}
   14.94 +
   14.95 +int cmp(const void *a, const void *b)
   14.96 +{
   14.97 +	return strcmp(*(char**)a, *(char**)b);
   14.98 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/tee.c	Thu Aug 25 08:53:01 2011 +0300
    15.3 @@ -0,0 +1,47 @@
    15.4 +/*! cc -o tee tee.c */
    15.5 +#include <stdio.h>
    15.6 +#include <stdlib.h>
    15.7 +#include <string.h>
    15.8 +#include <errno.h>
    15.9 +
   15.10 +void output(FILE **farr, int count, char *data, size_t bytes);
   15.11 +
   15.12 +int main(int argc, char **argv)
   15.13 +{
   15.14 +	char buf[512];
   15.15 +	size_t rdbytes;
   15.16 +	FILE **files;
   15.17 +	int i, fnum = 0;
   15.18 +
   15.19 +	if(!(files = malloc((argc - 1) * sizeof *files))) {
   15.20 +		perror("malloc failed");
   15.21 +		return EXIT_FAILURE;
   15.22 +	}
   15.23 +
   15.24 +	for(i=1; i<argc; i++) {
   15.25 +		if(!(files[fnum] = fopen(argv[i], "wb"))) {
   15.26 +			fprintf(stderr, "failed to write to %s: %s\n", argv[i], strerror(errno));
   15.27 +		} else {
   15.28 +			fnum++;
   15.29 +		}
   15.30 +	}
   15.31 +
   15.32 +	while((rdbytes = fread(buf, 1, sizeof buf, stdin))) {
   15.33 +		output(files, fnum, buf, rdbytes);
   15.34 +	}
   15.35 +
   15.36 +	for(i=0; i<fnum; i++) {
   15.37 +		fclose(files[i]);
   15.38 +	}
   15.39 +	return 0;
   15.40 +}
   15.41 +
   15.42 +void output(FILE **farr, int count, char *data, size_t bytes)
   15.43 +{
   15.44 +	int i;
   15.45 +
   15.46 +	fwrite(data, 1, bytes, stdout);
   15.47 +	for(i=0; i<count; i++) {
   15.48 +		fwrite(data, 1, bytes, farr[i]);
   15.49 +	}
   15.50 +}
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/true.c	Thu Aug 25 08:53:01 2011 +0300
    16.3 @@ -0,0 +1,5 @@
    16.4 +/*! gcc -o true true.c */
    16.5 +int main(void)
    16.6 +{
    16.7 +	return 0;
    16.8 +}
    17.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    17.2 +++ b/uname.c	Thu Aug 25 08:53:01 2011 +0300
    17.3 @@ -0,0 +1,82 @@
    17.4 +#include <stdio.h>
    17.5 +#include <sys/utsname.h>
    17.6 +
    17.7 +enum {
    17.8 +	SYS = 1,
    17.9 +	NODE = 2,
   17.10 +	REL = 4,
   17.11 +	VER = 8,
   17.12 +	MACHINE = 16,
   17.13 +	OS = 32
   17.14 +};
   17.15 +
   17.16 +int main(int argc, char **argv)
   17.17 +{
   17.18 +	int i;
   17.19 +	unsigned int sel = 0;
   17.20 +	struct utsname un;
   17.21 +
   17.22 +	for(i=1; i<argc; i++) {
   17.23 +		if(argv[i][0] == '-' && argv[i][2] == 0) {
   17.24 +			switch(argv[i][1]) {
   17.25 +			case 'a':
   17.26 +				sel |= SYS | NODE | REL | VER | MACHINE | OS;
   17.27 +				break;
   17.28 +
   17.29 +			case 's':
   17.30 +				sel |= SYS;
   17.31 +				break;
   17.32 +
   17.33 +			case 'n':
   17.34 +				sel |= NODE;
   17.35 +				break;
   17.36 +
   17.37 +			case 'r':
   17.38 +				sel |= REL;
   17.39 +				break;
   17.40 +
   17.41 +			case 'v':
   17.42 +				sel |= VER;
   17.43 +				break;
   17.44 +
   17.45 +			case 'm':
   17.46 +				sel |= MACHINE;
   17.47 +				break;
   17.48 +
   17.49 +			case 'o':
   17.50 +				sel |= OS;
   17.51 +				break;
   17.52 +
   17.53 +			default:
   17.54 +				fprintf(stderr, "unrecognized option: %s\n", argv[i]);
   17.55 +				return 1;
   17.56 +			}
   17.57 +		} else {
   17.58 +			fprintf(stderr, "unexpected argument: %s\n", argv[i]);
   17.59 +			return 1;
   17.60 +		}
   17.61 +	}
   17.62 +
   17.63 +	if(!sel) {
   17.64 +		sel = SYS;
   17.65 +	}
   17.66 +	uname(&un);
   17.67 +
   17.68 +	if(sel & SYS) {
   17.69 +		printf("%s ", un.sysname);
   17.70 +	}
   17.71 +	if(sel & NODE) {
   17.72 +		printf("%s ", un.nodename);
   17.73 +	}
   17.74 +	if(sel & REL) {
   17.75 +		printf("%s ", un.release);
   17.76 +	}
   17.77 +	if(sel & VER) {
   17.78 +		printf("%s ", un.version);
   17.79 +	}
   17.80 +	if(sel & MACHINE) {
   17.81 +		printf("%s ", un.machine);
   17.82 +	}
   17.83 +	putchar('\n');
   17.84 +	return 0;
   17.85 +}