summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorRobert de Bath <rdebath@poboxes.com>1997-02-25 20:42:19 +0100
committerLubomir Rintel <lkundrak@v3.sk>2013-10-23 23:38:07 +0200
commit4c36e9a0c125ccfff37aa440dab2cf58c4152fff (patch)
treea5d9c84ba2661029ddb2223dacd50529a361c3d5 /tests
parentf8de35da65c5d93bb733073cf40da154bc1c0748 (diff)
parent9696d7b0e1f3a1b0f5fd4a0428eb75afe8ad4ed6 (diff)
downloaddev86-4c36e9a0c125ccfff37aa440dab2cf58c4152fff.tar.gz
Import Dev86src-0.0.11.tar.gzv0.0.11
Diffstat (limited to 'tests')
-rw-r--r--tests/Makefile33
-rw-r--r--tests/README24
-rw-r--r--tests/compr.c383
-rw-r--r--tests/env.c81
-rw-r--r--tests/ft.c1209
-rw-r--r--tests/grab.c81
-rw-r--r--tests/hd.c185
-rw-r--r--tests/line2.c15
-rw-r--r--tests/lines.c36
-rw-r--r--tests/ouch.c27
-rw-r--r--tests/rand.c16
-rw-r--r--tests/size.c83
-rw-r--r--tests/sync.c1
-rw-r--r--tests/ucomp.c108
-rw-r--r--tests/wc.c133
15 files changed, 2400 insertions, 15 deletions
diff --git a/tests/Makefile b/tests/Makefile
index 52eb94a..ceb884e 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -2,22 +2,25 @@
# This file is part of the Linux-8086 C library and is distributed
# under the GNU Library General Public License.
-CC=bcc
-CFLAGS=-O -ansi
-LDFLAGS=
+BCC=bcc
+CC=$(BCC)
+CFLAGS=-O -s
-ifeq (Real_make,$(wildcard Real_make))
-include Real_make
-endif
+SRC=env.c ft.c hd.c size.c sync.c compr.c ucomp.c ouch.c lines.c \
+ wc.c line2.c rand.c grab.c
+OBJ=
+EXE=env ft hd size sync compr ucomp ouch lines wc line2 rand grab
-ifneq ($(TOPDIR),)
-starter:
- make -C ../libc/tests fetch_them
- make all
-endif
+LINK_FILES=cat chgrp chmod chown cp install ln mkdir mkfifo mknod mv rm
-not_from_here:
- @echo Do make tests from the top directory
+all: $(EXE)
+
+install links:
+ for i in $(LINK_FILES) ; do ln -s ft $$i ; done
+
+no_links:
+ rm -f $(LINK_FILES)
+
+clean realclean:
+ rm -f $(OBJ) $(EXE) $(LINK_FILES)
-clean:
- rm -f Real_make $(SRC) $(OBJ) $(EXE) $(LINK_FILES)
diff --git a/tests/README b/tests/README
new file mode 100644
index 0000000..1f9bcfd
--- /dev/null
+++ b/tests/README
@@ -0,0 +1,24 @@
+Copyright (C) 1996 Robert de Bath <robert@mayday.compulink.co.uk>
+This file is part of the Linux-8086 C library and is distributed
+under the GNU Library General Public License.
+
+These are user level tools, they're being used to test libc routines.
+
+env.c Prints the environment and arguments (Plus some junk)
+compr.c Mini compression program (rather slow but squeezes better than compress)
+ucomp.c Mini uncompression program (Very fast)
+ft.c Multiple simple file tools.
+hd.c Hex dump.
+line2.c Print lines from /etc/passwd (stdio)
+lines.c Print lines from /etc/passwd
+ouch.c Signal test
+size.c Size of Linux-i86 executables and object files.
+sync.c :-)
+wc.c Word,line and character counts.
+grab.c Grabs _all_ available memory (3GB+ on Linux-i386) then frees
+rand.c Generates random numbers and pipes them to 'hd'
+
+BTW: i386 OMAGIC files can be converted to deformed ELFs with this:
+ $ objcopy -O elf32-i386 sync
+
+-Robert
diff --git a/tests/compr.c b/tests/compr.c
new file mode 100644
index 0000000..8e53443
--- /dev/null
+++ b/tests/compr.c
@@ -0,0 +1,383 @@
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MAXNO 32767
+#define MAXLEN 127
+#define XXQSCAN /* Speed up scanning at the cost of not being optimal */
+
+unsigned char *fptr;
+unsigned short *vptr;
+FILE * fd;
+
+#define ITBSIZE 4096
+#define itbfunc() (ptr[mainscan]^(ptr[mainscan+1]<<4)^(ptr[mainscan+2]<<2))
+/*
+#define ITBSIZE 4001
+#define itbfunc() ((ptr[mainscan]+ptr[mainscan+1]*79+ptr[mainscan+2]*307)%4001)
+*/
+int * itb;
+
+int size;
+int maxno= 8000;
+long cnt=0;
+
+long icount = 0;
+long ocount = 0;
+
+unsigned char key;
+
+int fl;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+ if( argc < 2 ) { fprintf(stderr, "Usage; ... \n"); exit(1); }
+
+ if( argc == 3 )
+ {
+ maxno = atoi(argv[2]);
+ if( maxno < 256 ) maxno = 256;
+ if( maxno > MAXNO) maxno = MAXNO;
+ }
+
+ if( strcmp(argv[1], "-") == 0 )
+ fd = stdin;
+ else
+ fd = fopen(argv[1], "r" );
+ if( fd == 0 ) { perror("Open failed\n"); exit(1); }
+
+ fptr = (unsigned char * ) malloc((unsigned)maxno*2);
+ itb = (int * ) malloc(ITBSIZE*sizeof(int));
+ if( itb )
+ vptr = (unsigned short * ) malloc((unsigned)maxno * sizeof(short)*2 );
+ else
+ vptr = 0;
+
+ if( fptr == 0 )
+ {
+ perror("Cannot allocate RAM");
+ exit(1);
+ }
+ if( vptr == 0 && itb ) free(itb);
+
+ fl = 0;
+ {
+ if( (size = fread(fptr, 1, (int)maxno, fd )) < 0 ) { fprintf(stderr, "\nRead failed\n"); exit(1); }
+
+ if( size )
+ {
+ icount += size;
+ if( fl == 0 )
+ {
+ key = scan_min();
+ putchar(key); ocount++;
+ fl = 1;
+ }
+ else
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ if( vptr) compress();
+ else slo_compress();
+ }
+ }
+
+ fprintf(stderr, "\n");
+ exit(0);
+}
+
+scan_min()
+{
+ long count[256];
+ long i;
+ int j, n;
+
+ for( j=0; j<256; j++ ) count[j] = 0;
+
+ for( i=0; i<size; i++) count[ fptr[i] & 0xFF ]++;
+
+ for( i= (((unsigned long) -1) >> 1), j=0; j<256; j++ )
+ if( count[j] < i )
+ {
+ i = count[j] ;
+ n = j;
+ }
+
+ fprintf(stderr, "Most unused in 0x%lx to 0x%lx is 0x%02x at %ld\n", cnt, cnt+size, n, i );
+ cnt+= size;
+
+ return n;
+}
+
+compress()
+{
+ register long mainscan;
+ register long secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register int len;
+ register int matchlen;
+ long notepos;
+ long emark;
+#ifdef QSCAN
+ int count;
+#endif
+
+ for( mainscan=0; mainscan <ITBSIZE; itb[mainscan++] = -1 );
+
+ mainscan=0;
+ emark = size - 130 ;
+loopback:
+
+ for( ; mainscan < emark; )
+ {
+ matchlen = 3;
+ notepos = -1;
+#ifdef QSCAN
+ count = 0;
+#endif
+ for( secondscan=itb[itbfunc()];
+ secondscan >= 0 && mainscan - secondscan < maxno;
+ secondscan -= vptr[secondscan] )
+ {
+#ifdef DEBUG
+if( vptr[secondscan] == 0 )
+{
+ fprintf(stderr, "\nOh !!!!! mainsc %ld, sec-scan %ld\n", mainscan, secondscan);
+ vptr[secondscan] = secondscan+1;
+}
+#endif
+
+ for( len = 0; len < MAXLEN ; len++ )
+ if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break;
+ if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) )
+ {
+ notepos = secondscan;
+ matchlen = len;
+ if( len == MAXLEN ) break;
+ }
+#ifdef QSCAN
+ if( matchlen > 20 && len > 3 && ++count > 5 )
+ break;
+#endif
+ }
+
+ if( notepos == -1 )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(ptr[mainscan]);
+ }
+ matchlen = 1;
+ }
+ else
+ {
+ long x = mainscan - notepos;
+ ocount+=3;
+ putchar(key);
+ if( x > 255 ) putchar(matchlen | 0x80);
+ else putchar(matchlen);
+ putchar((int)x);
+ if( x > 255 ) { putchar((int)x>>8); ocount++; }
+ }
+
+ while( matchlen-- )
+ {
+ len = itbfunc();
+ vptr[mainscan] = mainscan - itb[len];
+#if 1
+ if( vptr[mainscan] == 0 )
+ {
+ fprintf(stderr, "\nHumm.. ms=%ld, hash=%d, itb[hash]=%ld\n", mainscan, len, itb[len]);
+ vptr[mainscan] = mainscan+1;
+ }
+#endif
+ itb[len] = mainscan;
+ mainscan++;
+ }
+ }
+
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+
+ if( emark < size-4 )
+ {
+ int cnt;
+ long l ;
+ if(mainscan > maxno )
+ {
+ for(cnt=0; cnt<ITBSIZE; cnt++)
+ {
+ if( itb[cnt] < maxno) itb[cnt] = -1;
+ else itb[cnt] -= maxno;
+ }
+ for(l=0; l<maxno; l++)
+ {
+ ptr[l] = ptr[l+maxno];
+ vptr[l] = vptr[l+maxno];
+ }
+ mainscan -= maxno;
+ size -= maxno;
+ }
+ if( size <= maxno )
+ {
+ if(( cnt = fread(ptr+size, 1, (int)maxno, fd)) < 0 )
+ { fprintf(stderr, "\nRead failed\n"); exit(1); }
+ size += cnt;
+ icount += cnt;
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ }
+ emark = size - 130;
+ if( mainscan >= emark )
+ emark = size -4;
+
+ goto loopback;
+ }
+
+ for( ; mainscan < size; )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(fptr[mainscan]);
+ }
+ mainscan++;
+ }
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+ /* end */
+}
+
+slo_compress()
+{
+ register long mainscan;
+ register long secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register int len;
+ register int matchlen;
+ long notepos;
+ long emark;
+#ifdef QSCAN
+ int count;
+#endif
+
+ mainscan=0;
+ emark = size - 130 ;
+loopback:
+
+ for( ; mainscan < emark; )
+ {
+ matchlen = 3;
+ notepos = -1;
+#ifdef QSCAN
+ count = 0;
+#endif
+ for( secondscan=mainscan-1;
+ secondscan >= 0 && mainscan - secondscan < maxno;
+ secondscan-- )
+ {
+ for( len = 0; len < MAXLEN ; len++ )
+ if( mainscan+len >= size || ptr[mainscan+len] != ptr[secondscan+len] ) break;
+ if( len > matchlen && (len != 4 || mainscan - secondscan < 256 ) )
+ {
+ notepos = secondscan;
+ matchlen = len;
+ if( len == MAXLEN ) break;
+ }
+#ifdef QSCAN
+ if( matchlen > 20 && len > 3 && ++count > 5 )
+ break;
+#endif
+ }
+
+ if( notepos == -1 )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(ptr[mainscan]);
+ }
+ matchlen = 1;
+ }
+ else
+ {
+ long x = mainscan - notepos;
+ ocount+=3;
+ putchar(key);
+ if( x > 255 ) putchar(matchlen | 0x80);
+ else putchar(matchlen);
+ putchar((int)x);
+ if( x > 255 ) { putchar((int)x>>8); ocount++; }
+ }
+
+ mainscan += matchlen;
+ }
+
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+
+ if( emark < size-4 )
+ {
+ int cnt;
+ long l ;
+ if(mainscan > maxno )
+ {
+ for(l=0; l<maxno; l++)
+ {
+ ptr[l] = ptr[l+maxno];
+ }
+ mainscan -= maxno;
+ size -= maxno;
+ }
+ if( size <= maxno )
+ {
+ if(( cnt = fread(ptr+size, 1, (int)maxno, fd)) < 0 )
+ { fprintf(stderr, "\nRead failed\n"); exit(1); }
+ size += cnt;
+ icount += cnt;
+ fprintf(stderr, "\rBlock %d \r", fl++ );
+ }
+ emark = size - 130;
+ if( mainscan >= emark )
+ emark = size -4;
+
+ goto loopback;
+ }
+
+ for( ; mainscan < size; )
+ {
+ if( ptr[mainscan] == key )
+ {
+ ocount+=2;
+ putchar(key);
+ putchar(0);
+ }
+ else
+ {
+ ocount++;
+ putchar(fptr[mainscan]);
+ }
+ mainscan++;
+ }
+ fprintf(stderr, "\rBlock %d ..In:%ld Out:%ld \r", fl-1, icount, ocount );
+ /* end */
+}
+
diff --git a/tests/env.c b/tests/env.c
new file mode 100644
index 0000000..c904969
--- /dev/null
+++ b/tests/env.c
@@ -0,0 +1,81 @@
+
+char hex[] = "0123456789ABCDEF";
+
+char buf[20];
+main(argc, argv, envp)
+int argc;
+char ** argv;
+char ** envp;
+{
+ int i,j; char *p; char * str;
+ int * arg = &argc;
+
+ for(j=0; j<8; j++)
+ {
+ phex(arg);
+ putstr(":");
+ for(i=0; i<8; i++)
+ {
+ putstr(" ");
+ phex(*arg++);
+ }
+ putstr("\n");
+ }
+
+#if 0
+ str = alloca(sizeof(hex)+2);
+ putstr("Alloca = ");
+ phex(&str);
+ putstr(",");
+ phex(str);
+ putstr("\n");
+#endif
+
+ p = (char*) &argc;
+
+ putstr("ARGC="); phex(argc); putstr("\n");
+ for(i=0; i<argc; i++)
+ {
+ phex(argv[i]);
+ putstr(":");
+ putstr(argv[i]);
+ putstr("\n");
+ }
+ putstr("ENV=>\n");
+ for(; *envp; envp++)
+ {
+ phex(envp);
+ putstr(":");
+ phex(*envp);
+ putstr(":");
+ putstr(*envp);
+ putstr("\n");
+ }
+}
+
+phex(val)
+{
+ int i;
+ printf("%04x", val);
+}
+
+putstr(str)
+{
+ printf("%s", str);
+}
+
+#if 0
+int global_var_that_needs_init = 0x201;
+
+#asm
+ loc 1 ! Make sure the pointer is in the correct segment
+auto_func: ! Label for bcc -M to work.
+ .word _init_vars ! Pointer to the autorun function
+ .text ! So the function after is also in the correct seg.
+#endasm
+
+static void init_vars()
+{
+ global_var_that_needs_init = getuid();
+}
+#endif
diff --git a/tests/ft.c b/tests/ft.c
new file mode 100644
index 0000000..1bdc737
--- /dev/null
+++ b/tests/ft.c
@@ -0,0 +1,1209 @@
+/* Copyright (C) 1995,1996 Robert de Bath <rdebath@cix.compulink.co.uk>
+ * This program is distributed under the GNU General Public License.
+ */
+
+/*
+ * File Tool, This program is a collection of basic file tools
+ * it includes cat, cp, ln, mkdir, mknod, chmod, chown, mv, rm
+ *
+ * Links may be used to call it under any of these names.
+ */
+#include <stdio.h>
+#ifdef __STDC__
+#include <unistd.h>
+#include <stdlib.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <dirent.h>
+#include <sys/param.h>
+#include <utime.h>
+#include <pwd.h>
+#include <grp.h>
+
+#ifdef S_IFSOCK
+#include <sys/socket.h>
+#endif
+#ifndef S_IFLNK
+#define lstat stat
+#endif
+
+/* Ansi prototypes */
+#ifdef __STTDC__
+#define PR(x) x
+#else
+#define PR(x) ()
+#endif
+
+void main PR((int argc, char ** argv));
+int select_command PR((char * argv));
+void do_prep PR((void));
+void do_post PR((void));
+void execute PR((char * dname, char * fname));
+int exec_for_subdir PR((char * dname));
+void exec_for_item PR((int when, char * fname));
+void parse_perms PR((char * prefix, char * ustring));
+int edit_mode PR((int mode, char * mode_str));
+int cmd_ft PR((char * fname));
+int cmd_mkfifo PR((char * fname));
+int cmd_mksock PR((char * fname));
+int cmd_rm PR((char * fname));
+void build_dest PR((char * dest, char * name, char * newpath));
+int strisdigit PR((char * str));
+int cmd_mv PR((char * fname));
+int cmd_ln PR((char * fname));
+int cmd_cp PR((char * fname));
+int copy_modes PR((char * file));
+int copy_file PR((char * source, char * dest));
+void Usage PR((void));
+int cmd_mkdir PR((char * dirname));
+int cmd_mknod PR((void));
+int warning PR((int enumber, char * estr, char * eobj));
+int error PR((int enumber, char * estr, char * eobj));
+
+#define DO_BDIR 0x0010 /* Do Dir before contents */
+#define DO_ADIR 0x0020 /* Do Dir after contents */
+#define DO_MCOPY 0x0040 /* Preserve modes flag forced */
+#define OK_DIR 0x0080 /* Directorys OK even if no flg_recurse */
+#define IGN_LNK 0x0100 /* Not interested in symlinks */
+#define NO_SOURCE 0x0200 /* Named files created */
+#define OK_NO_SOURCE 0x0400 /* Don't need the source */
+
+#define CMD_FT (0+OK_DIR+DO_BDIR)
+#define CMD_CAT (1+IGN_LNK)
+#define CMD_CHGRP (2+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CHMOD (3+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CHOWN (4+OK_DIR+IGN_LNK+DO_ADIR)
+#define CMD_CP (5+IGN_LNK)
+#define CMD_EXTAR (6+DO_MCOPY+DO_BDIR)
+#define CMD_INSTALL (7+DO_MCOPY)
+#define CMD_LN (8+IGN_LNK+DO_BDIR)
+#define CMD_MKDIR (9+NO_SOURCE)
+#define CMD_MKFIFO (10+NO_SOURCE)
+#define CMD_MKSOCK (11+NO_SOURCE)
+#define CMD_MKNOD (12+NO_SOURCE)
+#define CMD_MV (13+DO_MCOPY+OK_DIR+DO_BDIR)
+#define CMD_RM (14+DO_ADIR)
+
+struct {
+ char * name;
+ int cmd;
+ int argpat;
+ char * opts;
+} command_list[] =
+{
+ { "ft", CMD_FT, 0, "-Rv" },
+ { "cat", CMD_CAT, 0, "uR" },
+ { "chgrp", CMD_CHGRP, 1, "vfR" },
+ { "chmod", CMD_CHMOD, 1, "vfR" },
+ { "chown", CMD_CHOWN, 1, "vfR" },
+ { "cp", CMD_CP, -1, "vifRrpsda" },
+ { "extar", CMD_EXTAR, 1, "" },
+ { "install", CMD_INSTALL, -1, "cdso:g:m:" },
+ { "ln", CMD_LN, -1, "vifs" },
+ { "mkdir", CMD_MKDIR, 0, "m:" },
+ { "mkfifo", CMD_MKFIFO, 0, "m:" },
+#ifdef S_IFSOCK
+ { "mksock", CMD_MKSOCK, 0, "m:" },
+#endif
+ { "mknod", CMD_MKNOD, 4, "m:" },
+ { "mv", CMD_MV, -1, "vif" },
+ { "rm", CMD_RM, 0, "vifr" },
+ { 0 }
+};
+
+int cmd_arg = 0;
+int cmd_tok = CMD_FT;
+char * cmd_opt = "-";
+char * cmd_string = 0; /* the first (or last) arg where special */
+char * prog_name = "";
+
+char ** flist = 0;
+int fcount = 0;
+int add_base=0;
+char * or_name = 0;
+int or_offset = 0;
+
+int flg_recurse = 0;
+int flg_verbose = 1;
+int flg_preserve= 0;
+int flg_mkpdir = 0;
+int flg_noderef = 0;
+int flg_symlink = 0;
+int flg_exestrip= 0;
+
+int flg_r, flg_force;
+char *str_o, *str_g, *str_m;
+
+/* Things to set on the new file */
+int set_user = -1;
+int set_group = -1;
+int set_mode = -1;
+time_t set_time = -1;
+char mode_str[32] = "";
+int u_mask = 0; /* 07777 altered by umask() */
+
+struct stat cur_file_stat;
+struct stat dest_item;
+struct stat access_stat;
+
+int done_something = 0;
+
+void
+main(argc, argv)
+int argc; char ** argv;
+{
+ int ar;
+ (void) select_command(argv[0]);
+
+ for(ar=1;
+ argv[ar] && argv[ar][0] == '-' && argv[ar][1];
+ ar++)
+ {
+ char * p = argv[ar]+1;
+ /* For symbolic changes of the form -rwx */
+ if( cmd_tok == CMD_CHMOD && strchr("rwx", *p) != 0 ) break;
+ while(*p)
+ {
+ char * ap=0, *av=0;
+ char ch;
+ /* Is it a valid opt for this cmd */
+ if(*p == ':' || (ap=strchr(cmd_opt, *p)) == 0) Usage();
+
+ /* Got an argument ? */
+ if(ap[1] == ':')
+ {
+ if(!argv[ar+1]) Usage();
+ av = argv[++ar];
+ }
+
+ if( (ch = *p) == '-' )
+ {
+ if( (ch=select_command(p)) < 0 ) Usage();
+ }
+ switch(ch)
+ {
+ case '\0': break;
+ case 'r':
+ case 'R': flg_recurse++; break;
+ case 'v': flg_verbose++; break;
+ case 'p': if(cmd_tok == CMD_MKDIR) flg_mkpdir++;
+ else flg_preserve++;
+ break;
+ case 'd': if(cmd_tok == CMD_INSTALL)
+ { flg_mkpdir++; cmd_arg=0; } /* Special mkdir */
+ else flg_noderef++; /* cmd_copy */
+ break;
+
+ case 'f': flg_force++; flg_verbose=0; break;
+ case 'o': str_o = av; break;
+ case 'g': str_g = av; break;
+ case 'm': str_m = av; break;
+
+ case 's': flg_symlink++;
+ if( cmd_tok == CMD_LN) cmd_tok |= OK_DIR+OK_NO_SOURCE;
+ break;
+ case 'a': flg_recurse++; flg_preserve++; flg_noderef++;
+ break;
+ }
+ if(*p == '-') break;
+ p++;
+ }
+ }
+
+ switch(cmd_arg)
+ {
+ case 1:
+ if( ar >= argc ) Usage();
+ cmd_string = argv[ar++];
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ case 0:
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ case -1:
+ if( ar >= argc ) Usage();
+ cmd_string = argv[argc-1];
+ fcount = argc-ar-1;
+ flist = argv+ar;
+ break;
+ default:
+ if( ar != argc-cmd_arg ) Usage();
+ fcount = argc-ar;
+ flist = argv+ar;
+ break;
+ }
+
+ do_prep();
+
+ for(ar=0; ar<fcount; ar++)
+ {
+ done_something=1;
+ or_name = flist[ar]; or_offset = strlen(or_name)+1;
+ execute(flist[ar], (char*)0);
+ }
+
+ do_post();
+
+ if( !done_something )
+ {
+ if( cmd_tok == CMD_CAT )
+ execute("-", (char*)0);
+ else
+ Usage();
+ }
+ exit(0);
+}
+
+int select_command(argv)
+char * argv;
+{
+ int ar;
+ char *p, *s;
+ prog_name = argv;
+ for(ar=0; command_list[ar].name; ar++)
+ {
+ p = strrchr(argv, '-'); if(p) p++; else p=argv;
+ s = strrchr(p, '/'); if(s) s++; else s=p;
+ if( strcmp(s, command_list[ar].name) == 0 )
+ {
+ cmd_arg = command_list[ar].argpat;
+ cmd_tok = command_list[ar].cmd;
+ cmd_opt = command_list[ar].opts;
+ return 0;
+ }
+ }
+ return -1;
+}
+
+void do_prep()
+{
+ char * prefix = "::";
+
+ u_mask = umask(077);
+ umask(u_mask);
+ u_mask = (07777&(~u_mask));
+
+ if(cmd_tok&DO_MCOPY) flg_preserve++;
+ if(str_m) parse_perms(prefix, str_m);
+
+ switch(cmd_tok)
+ {
+ /* mknod is very different */
+ case CMD_MKNOD: cmd_mknod(); exit(0); break;
+
+ case CMD_CP:
+ if(strcmp(cmd_string, "-") == 0)
+ {
+ cmd_tok = CMD_CAT;
+ cmd_arg = 0;
+ break;
+ }
+ if(flg_symlink)
+ {
+ cmd_tok = CMD_LN+OK_DIR+OK_NO_SOURCE;
+ flg_preserve = 0;
+ }
+ break;
+
+ case CMD_CHOWN: prefix++;
+ case CMD_CHGRP: prefix++;
+ case CMD_CHMOD:
+ parse_perms(prefix, cmd_string);
+ set_time = 0;
+ break;
+ case CMD_INSTALL:
+ flg_exestrip = flg_symlink;
+ flg_symlink = 0;
+ if(str_o) parse_perms(prefix+2, str_o);
+ if(str_g) parse_perms(prefix+1, str_g);
+ if(flg_mkpdir) cmd_tok = CMD_MKDIR;
+ else
+ {
+ cmd_tok = CMD_CP;
+ flg_preserve = 1;
+ }
+ break;
+ }
+
+#ifndef S_IFLNK
+ if(flg_symlink)
+ {
+ error(0, "No support for symlinks available:", cmd_string);
+ exit(1);
+ }
+#endif
+
+ /* Are we transfering many to one ? Then it must be a directory */
+ if(cmd_arg == -1)
+ {
+ if( stat(cmd_string, &dest_item) == -1)
+ {
+ if( fcount > 1 )
+ {
+ if( cmd_mkdir(cmd_string) < 0 )
+ exit(1);
+ stat(cmd_string, &dest_item);
+ add_base = 1;
+ }
+ }
+ else
+ {
+ if( !S_ISDIR(dest_item.st_mode) )
+ {
+ if( fcount > 1 )
+ {
+ error(0, "Destination must be a directory:", cmd_string);
+ exit(1);
+ }
+ }
+ else add_base = 1;
+ }
+ }
+}
+
+void do_post()
+{
+ /* Oh! It seems there's nothing to do, ah well. */
+}
+
+void execute(dname, fname)
+char * dname; char * fname;
+{
+ char * buf;
+ if( strcmp(dname, "-") == 0 )
+ {
+ exec_for_item(0, dname);
+ return;
+ }
+ if( fname )
+ {
+ buf = alloca(strlen(dname) + strlen(fname) + 4);
+ if( buf == 0 )
+ {
+ error(errno, "Can't allocate memory for path beyond ", dname);
+ return ;
+ }
+ strcpy(buf, dname);
+ if(strcmp(dname, "/")) strcat(buf, "/");
+ strcat(buf, fname);
+ }
+ else buf = dname;
+
+ if( lstat(buf, &cur_file_stat) == -1 )
+ {
+ if( cmd_tok&(NO_SOURCE|OK_NO_SOURCE) )
+ exec_for_item(0, buf);
+ else
+ warning(errno, "", buf);
+ return;
+ }
+ if( !flg_force && ( cmd_tok&NO_SOURCE ))
+ {
+ error(EEXIST, "", buf);
+ return;
+ }
+
+ if( S_ISDIR(cur_file_stat.st_mode))
+ {
+ if( (cmd_tok&OK_DIR) || flg_recurse )
+ (void) exec_for_subdir(buf);
+ else
+ error(EISDIR, "", buf);
+ return;
+ }
+
+#ifdef S_IFLNK
+ if( S_ISLNK(cur_file_stat.st_mode))
+ {
+ /* Links are special */
+ if( cmd_tok&IGN_LNK )
+ {
+ if( stat(buf, &cur_file_stat) == -1 )
+ {
+ warning(errno, "", buf);
+ return;
+ }
+ }
+ }
+#endif
+ exec_for_item(0, buf);
+}
+
+int exec_for_subdir(dname)
+char * dname;
+{
+ DIR * dfd;
+ struct dirent * ent;
+ int old_mode = -1;
+
+ if( cmd_tok&DO_BDIR ) exec_for_item(-1, dname);
+
+ if( flg_recurse )
+ {
+ dfd = opendir(dname);
+ if( dfd == 0 && errno == EACCES && flg_force )
+ {
+ old_mode = (cur_file_stat.st_mode & 07777);
+ if( chmod(dname, (0700|old_mode)) )
+ return error(errno, "", dname);
+
+ dfd = opendir(dname);
+ }
+ if( dfd == 0 ) return error(errno, "", dname);
+
+ while((ent=readdir(dfd)))
+ {
+ if( strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0 )
+ continue;
+
+ alloca(0); /* Free up if using fake version */
+ execute(dname, ent->d_name);
+ }
+ closedir(dfd);
+ if( old_mode != -1 )
+ chmod(dname, old_mode);
+ }
+
+ if( cmd_tok&DO_ADIR )
+ {
+ lstat(dname, &cur_file_stat);
+ exec_for_item(1, dname);
+ }
+ return 0;
+}
+
+void exec_for_item(when, fname)
+int when; char * fname;
+{
+ int rv = -1;
+ switch(cmd_tok)
+ {
+ case CMD_FT: rv = cmd_ft(fname); break;
+
+ case CMD_CAT: rv = copy_file(fname, "-"); break;
+
+ case CMD_CHGRP: /* And fall */
+ case CMD_CHMOD: /* And fall */
+ case CMD_CHOWN: rv = copy_modes(fname); break;
+
+ case CMD_CP: rv = cmd_cp(fname); break;
+ case CMD_MV: rv = cmd_mv(fname); break;
+ case CMD_RM: rv = cmd_rm(fname); break;
+
+ case CMD_EXTAR: error(EINVAL, "", "No code."); exit(1);
+
+ case CMD_LN+OK_DIR+OK_NO_SOURCE:
+ case CMD_LN: rv = cmd_ln(fname); break;
+
+ case CMD_INSTALL: error(EINVAL, "", ""); exit(1);
+
+ case CMD_MKDIR: rv = cmd_mkdir(fname); break;
+ case CMD_MKFIFO: rv = cmd_mkfifo(fname); break;
+#ifdef S_IFSOCK
+ case CMD_MKSOCK: rv = cmd_mksock(fname); break;
+#endif
+ case CMD_MKNOD: break;
+ }
+}
+
+void parse_perms(prefix, ustring)
+char * prefix; char * ustring;
+{
+ char * userstr;
+ char * groupstr;
+ char * modestr;
+ char * cp;
+ struct passwd * pwd = 0;
+ struct group * grp;
+
+ userstr = alloca(strlen(prefix) + strlen(ustring) + 2);
+ strcpy(userstr, prefix);
+ strcat(userstr, ustring);
+
+ /* Select User */
+ cp = strchr(userstr, ':');
+ if(!cp) cp = strchr(userstr, '.');
+ if(cp) *cp = '\0';
+
+ /* If there's a user */
+ if( *userstr != 0 )
+ {
+ pwd = getpwnam(userstr);
+ if(pwd == NULL)
+ {
+ if(!strisdigit(userstr) )
+ {
+ error(EINVAL, "Unknown user ", userstr);
+ exit(1);
+ }
+ set_user = atoi(userstr);
+ }
+ else set_user = pwd->pw_uid;
+ endpwent();
+ }
+ if(cp)
+ {
+ groupstr = cp+1;
+ cp = strchr(groupstr, ':');
+ if(!cp) cp = strchr(groupstr, '.');
+ if(cp) *cp = '\0';
+ if( *groupstr != '\0' )
+ {
+ grp = getgrnam(groupstr);
+ if(grp == NULL)
+ {
+ if(!strisdigit(groupstr) )
+ {
+ error(EINVAL, "Unknown group ", groupstr);
+ exit(1);
+ }
+ set_group = atoi(groupstr);
+ }
+ else set_group = grp->gr_gid;
+ endgrent();
+ }
+ else if( pwd )
+ set_group = pwd->pw_gid;
+ }
+ if(cp)
+ {
+ modestr = cp+1;
+ if(strisdigit(modestr))
+ set_mode = strtol(modestr, NULL, 8);
+ else
+ {
+ strncpy(mode_str, modestr, sizeof(mode_str)-1);
+ /* This is the time that the mode change will fail on syn error */
+ (void) edit_mode(u_mask, mode_str);
+ }
+ }
+
+ if( set_user < 0 && set_group < 0 && set_mode < 0 && *mode_str == 0)
+ {
+ error(EINVAL, "", "Permission string has no changes");
+ exit(1);
+ }
+}
+
+int edit_mode(mode, mode_str)
+int mode; char * mode_str;
+{
+ char * str=mode_str;
+static mtab[] = {0, 0111, 0222, 0333, 0444, 0555, 0666, 0777 };
+
+ int done_change = 0;
+ int isdir = S_ISDIR(mode);
+ int change_op = 0;
+ int change_mask = u_mask;
+ int v=0, s=0, nm=0;
+
+ for(; *mode_str; mode_str++)
+ {
+ switch(*mode_str)
+ {
+ case ',': change_op = 0;
+ change_mask=u_mask; continue;
+ case '=': change_op = 1; if(0) {
+ case '+': change_op = 2; } if(0) {
+ case '-': change_op = 3; }
+ v=0; nm=0;
+ if(strchr(",=+-", mode_str[1]) == 0 ) continue;
+ break;
+ case 'a': if(change_op) goto ch_error;
+ nm |= 07777; if(0) {
+ case 'u': nm |= 04700; s= 6; } if(0) {
+ case 'g': nm |= 02070; s= 3; } if(0) {
+ case 'o': nm |= 01007; s= 0; }
+ if(change_op==0) { change_mask=nm; continue; }
+ v |= mtab[(mode>>s)&7];
+ break;
+ case 'r': v |= 0444; break;
+ case 'w': v |= 0222; break;
+ case 'x': v |= 0111; break;
+ case 's': v |=06000; break;
+ case 't': v |=01000; break;
+ case 'X': v |= mtab[isdir]; break;
+ default: goto ch_error;
+ }
+ switch(change_op)
+ {
+ case 0: goto ch_error;
+ case 1: mode= ((mode&(~change_mask)) | (v&change_mask));
+ break;
+ case 2: mode= ( mode | (v&change_mask));
+ break;
+ case 3: mode= ( mode & ~(v&change_mask));
+ break;
+ }
+ done_change=1;
+ }
+ if(!done_change)
+ {
+ch_error:
+ error(EINVAL, "Invalid mode string ", str);
+ exit(1);
+ }
+ return mode;
+}
+
+int
+cmd_ft(fname)
+char * fname;
+{
+static char oldpath[2048] = "~";
+static int last_uid=-1, last_gid=-1, last_mode=-1;
+ struct passwd * pptr;
+ struct group * gptr;
+
+ if( flg_verbose>1 )
+ {
+ char *p = 0;
+ if( fname[1] ) p = strrchr(fname, '/');
+ if( p )
+ {
+ *p = '\0';
+ if( strcmp(fname, oldpath) != 0 )
+ {
+ strcpy(oldpath, fname);
+ printf("%s/\n", oldpath);
+ }
+ *p = '/';
+ }
+ else if( *oldpath )
+ *oldpath = '\0';
+ if(p) printf("%s", p+1);
+ else printf("%s", fname);
+
+#ifdef S_IFLNK
+ if( S_ISLNK(cur_file_stat.st_mode))
+ {
+ char linkbuf[1024];
+ int v;
+ *linkbuf='\0';
+ v = readlink(fname, linkbuf, sizeof(linkbuf));
+ if(v>0) linkbuf[v] = '\0';
+ printf("\t+%s", linkbuf);
+ }
+ else
+#endif
+ if( cur_file_stat.st_mode != last_mode
+ || cur_file_stat.st_uid != last_uid
+ || cur_file_stat.st_gid != last_gid)
+ {
+ printf("\t");
+ if( cur_file_stat.st_uid != last_uid )
+ {
+ pptr = getpwuid(cur_file_stat.st_uid);
+ if( pptr )
+ printf("%s", pptr->pw_name);
+ else
+ printf("%d", cur_file_stat.st_uid);
+ }
+ printf(":");
+ if( cur_file_stat.st_gid != last_gid )
+ {
+ gptr = getgrgid(cur_file_stat.st_gid);
+ if( gptr )
+ printf("%s", gptr->gr_name);
+ else
+ printf("%d", cur_file_stat.st_gid);
+ }
+ if( (cur_file_stat.st_mode&07777) != (last_mode&07777) )
+ printf(":%03o", cur_file_stat.st_mode & 07777);
+
+ switch(cur_file_stat.st_mode & S_IFMT)
+ {
+ case S_IFDIR: printf("\td"); break;
+ case S_IFIFO: printf("\tp"); break;
+#ifdef S_IFSOCK
+ case S_IFSOCK: printf("\ts"); break;
+#endif
+ case S_IFBLK: printf("\tb,%d,%d", cur_file_stat.st_rdev>>8,
+ cur_file_stat.st_rdev&0xFF);
+ break;
+ case S_IFCHR: printf("\tc,%d,%d", cur_file_stat.st_rdev>>8,
+ cur_file_stat.st_rdev&0xFF);
+ break;
+ }
+ last_mode = ((cur_file_stat.st_mode&07777)|S_IFREG);
+ if( (cur_file_stat.st_mode&07000) ) last_mode = -1;
+ last_uid = cur_file_stat.st_uid;
+ last_gid = cur_file_stat.st_gid;
+ }
+ printf("\n");
+ }
+ else printf("%s\n", fname);
+
+ return 0;
+}
+
+int
+cmd_mkfifo(fname)
+char * fname;
+{
+ int rv;
+ int mode=0666;
+ if( set_mode >= 0 ) mode=set_mode;
+ rv = mknod(fname, S_IFIFO|mode, 0);
+ if(rv<0)
+ warning(errno, "Cannot create fifo ", fname);
+ return rv;
+}
+
+#ifdef S_IFSOCK
+int
+cmd_mksock(fname)
+char * fname;
+{
+ int rv, fd, len;
+ struct sockaddr *adr;
+
+ len = strlen(fname)+1 + sizeof(*adr) - sizeof(adr->sa_data);
+ if( len < sizeof(*adr) ) len = sizeof(*adr);
+
+ adr = alloca(len+2);
+ adr->sa_family = AF_UNIX;
+ strcpy(adr->sa_data, fname);
+
+ rv = fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if( fd>=0 ) rv = bind(fd, adr, len);
+ if( fd>=0 ) close(fd);
+ if(set_mode >= 0 && chmod(fname, set_mode&07777) < 0 )
+ warning(errno, "Chmod ", fname);
+
+ if(rv<0)
+ warning(errno, "Cannot create socket ", fname);
+ return rv;
+}
+#endif
+
+int
+cmd_rm(fname)
+char * fname;
+{
+ struct stat dirstat;
+ int rv;
+ char * buf, * p;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ if( !flg_recurse ) return error(EISDIR, "", fname);
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ {
+ if( rmdir(fname) >= 0 ) return 0;
+ }
+ else
+ {
+ if( unlink(fname) >= 0 ) return 0;
+ }
+
+ if( !flg_force )
+ return error(errno, "", fname);
+
+ /* Try VERY hard */
+ buf = alloca(strlen(fname)+4);
+ strcpy(buf, fname);
+ p = strrchr(buf, '/');
+ if( p ) strcpy(p+1, "."); else strcpy(buf, ".");
+
+ if( stat(buf, &dirstat) < 0 ) return -1;
+ if( chmod(buf, dirstat.st_mode|0700) < 0 ) return -1;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ rv = rmdir(fname);
+ else
+ rv = unlink(fname);
+
+ chmod(buf, dirstat.st_mode);
+
+ return rv;
+}
+
+void
+build_dest(dest, name, newpath)
+char * dest; char * name; char * newpath;
+{
+ char * p;
+ strcpy(dest, newpath);
+ if( add_base )
+ {
+ strcat(dest, "/");
+ p = strrchr(or_name, '/');
+ if(p==0) strcat(dest, or_name);
+ else strcat(dest, p+1);
+ }
+ if(strlen(name) <= or_offset) return;
+ strcat(dest, name+or_offset);
+}
+
+int
+strisdigit(str)
+char * str;
+{
+ if( str==0 || *str == 0 ) return 0;
+
+ for(;*str; str++)
+ if(*str>'9'|| *str<'0') return 0;
+ return 1;
+}
+
+int
+cmd_mv(fname)
+char * fname;
+{
+ char * destfile;
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( !flg_force && lstat(destfile, &access_stat) == 0 )
+ return error(EEXIST, "", destfile);
+
+ if( rename(fname, destfile) == 0 ) return 0;
+
+ if( errno != EXDEV )
+ return error(errno, "", fname);
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ return error(EISDIR, "Can't rename across devices ", fname);
+
+ if( copy_file(fname, destfile) != 0 ) return -1;
+ copy_modes(destfile);
+ return unlink(fname);
+}
+
+int
+cmd_ln(fname)
+char * fname;
+{
+ char * destfile;
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( lstat(destfile, &access_stat) != -1 )
+ {
+ if( !flg_force ) return error(EEXIST, "", destfile);
+ cmd_rm(destfile);
+ }
+
+#ifdef S_IFLNK
+ if( flg_symlink )
+ {
+ if( symlink(fname, destfile) == 0 ) return 0;
+ }
+ else
+ {
+#endif
+ if( link(fname, destfile) == 0 ) return 0;
+#ifdef S_IFLNK
+ }
+#endif
+
+ return error(errno, "", destfile);
+}
+
+int
+cmd_cp(fname)
+char * fname;
+{
+ struct stat dest_stat;
+ char * destfile;
+ int no_dest = 0;
+
+ destfile = alloca(strlen(fname)+strlen(cmd_string)+4);
+
+ build_dest(destfile, fname, cmd_string);
+
+ if( stat(destfile, &dest_stat) >= 0 )
+ {
+ if( dest_stat.st_ino == cur_file_stat.st_ino
+ && dest_stat.st_dev == cur_file_stat.st_dev )
+ {
+ warning(EPERM, "Can't copy file to itself ", fname);
+ return -1;
+ }
+ }
+ else no_dest = 1;
+
+ if( S_ISDIR(cur_file_stat.st_mode) )
+ {
+ if( !no_dest )
+ {
+ if( S_ISDIR(dest_stat.st_mode) ) return 0;
+ if( unlink(destfile) < 0 )
+ return error(errno, "Can't delete ", destfile);
+ }
+ return cmd_mkdir(destfile);
+ }
+ else if( S_ISDIR(dest_stat.st_mode) )
+ return error(EPERM, "Can't copy non-directory to directory ", destfile);
+ else if( S_ISREG(cur_file_stat.st_mode) )
+ {
+ /* Copy_ok - do we want to force a real file */;
+ if( flg_force && !no_dest && !S_ISREG(dest_stat.st_mode) )
+ cmd_rm(destfile);
+ }
+ else if( flg_recurse ) /* Don't copy other things while recursing */
+ {
+ return error(EPERM, "Can't copy ", fname);
+ }
+
+ if( copy_file(fname, destfile) != 0 ) return -1;
+ if( flg_preserve ) copy_modes(destfile);
+ return 0;
+}
+
+int
+copy_modes(file)
+char * file;
+{
+ int user, group, mode;
+ /* chown turns off set[ug]id bits for non-root,
+ so do the chmod last. */
+
+ /* Try to copy the old file's modtime and access time. */
+ if(set_time)
+ {
+ struct utimbuf tv;
+
+ tv.actime = cur_file_stat.st_atime;
+ tv.modtime = cur_file_stat.st_mtime;
+ if( set_time != -1 )
+ tv.modtime = set_time;
+ if (utime (file, &tv) && !flg_force)
+ return error (errno, "", file);
+ }
+
+ /* Try to preserve ownership. For non-root it might fail, but that's ok.
+ But root probably wants to know, e.g. if NFS disallows it. */
+ user = cur_file_stat.st_uid; if(set_user>=0) user = set_user;
+ group = cur_file_stat.st_gid; if(set_group>=0) group = set_group;
+
+ if (chown (file, user, group)
+ && (errno != EPERM || geteuid() == 0 || (flg_preserve==0 && flg_force==0)))
+ error (errno, "Can't change perms for ", file);
+
+ mode = cur_file_stat.st_mode;
+ if(set_mode>=0) mode=set_mode;
+ else if(*mode_str)
+ mode = edit_mode(mode, mode_str);
+
+ if (chmod (file, mode & 07777))
+ return error (errno, "", file);
+
+ return 0;
+}
+
+/* This copies from something to a file or stdout */
+/* If the source has zero blocks (possibly holes) the destination
+ * is built with holes (assuming it's a normal file) */
+
+int
+copy_file(source, dest)
+char * source; char * dest;
+{
+ char * buf;
+ int sfd, dfd;
+ struct stat st;
+ int blksz = BUFSIZ;
+ int cc;
+ char * ptr;
+ int hole_flag = 0;
+ int retv = 0;
+ int no_seek;
+ int mmode = 0666;
+
+ if(flg_verbose>1) printf("%s -> %s\n", source, dest);
+ if( strcmp(source, "-") == 0 )
+ sfd = 0;
+ else
+ {
+ sfd = open(source, O_RDONLY);
+ if(sfd<0) return error(errno, "", source);
+ mmode = (cur_file_stat.st_mode&0777);
+ }
+
+ if( strcmp(dest, "-") == 0 )
+ dfd = 1;
+ else
+ {
+ dfd = open(dest, O_WRONLY|O_TRUNC|O_CREAT, mmode);
+ if(dfd<0)
+ {
+ close(sfd);
+ return error(errno, "Cannot create ", source);
+ }
+ }
+
+ if( fstat(dfd, &st) )
+ {
+ retv = error(errno, "", dest);
+ no_seek = 1;
+ }
+ else
+ {
+#ifndef __BCC__
+ blksz = st.st_blksize;
+#endif
+ no_seek = !S_ISREG(st.st_mode);
+ }
+ buf = alloca(blksz + sizeof(int));
+ if( buf == 0 ) return error(0, "Out of memory", "");
+
+ for(;;)
+ {
+ cc = read(sfd, buf, blksz);
+ if(cc<0)
+ {
+ retv = error(errno, "", source);
+ goto exit_now;
+ }
+ if(cc==0) break;
+ buf[cc] = 1;
+ for(ptr=buf; *ptr==0 ; ptr++) ;
+ if((hole_flag = (ptr == buf+cc)))
+ { /* Make a hole */
+ if( lseek(dfd, (off_t) cc, SEEK_CUR) < 0 )
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+ else
+ {
+ if( cc != write(dfd, buf, cc))
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+ }
+ if( hole_flag )
+ {
+ if( lseek(dfd, (off_t) -1, SEEK_CUR) < 0
+ || write(dfd, "", 1) != 1 )
+ {
+ retv = error(errno, "", dest);
+ goto exit_now;
+ }
+ }
+
+exit_now:
+ if(sfd>2) close(sfd);
+ if(dfd>2) close(dfd);
+ return retv;
+}
+
+void
+Usage()
+{
+ int i;
+
+ printf("FileTool Usage: %s%s", prog_name[0]=='-'?"ft -":"", prog_name);
+ if( cmd_tok == CMD_FT )
+ {
+ printf(" --[com_name] [-options] [files]\n");
+ printf("\nAvailable commands are:\n");
+ }
+
+ for(i=1; command_list[i].name; i++)
+ {
+ if( cmd_tok == CMD_FT )
+ printf(" %s --%s", prog_name, command_list[i].name);
+ else if( cmd_tok != command_list[i].cmd )
+ continue;
+
+ if( *command_list[i].opts )
+ printf(" [-%s]", command_list[i].opts);
+ switch(command_list[i].argpat)
+ {
+ case 1: printf(" <info> [files]"); break;
+ case -1: printf(" [files] [dest]"); break;
+ case 0: printf(" [files]"); break;
+ default: printf(" path [bcu] major minor"); break;
+ }
+ printf("\n");
+ }
+
+ exit(99);
+}
+
+int
+cmd_mkdir(dirname)
+char * dirname;
+{
+ int retv;
+ int mode = 0777;
+ if( set_mode >= 0 ) mode = set_mode;
+
+ retv = mkdir(dirname, mode);
+ if(retv<0)
+ {
+ if(flg_mkpdir && errno == ENOENT)
+ {
+ /* Create parents */
+ }
+ }
+ if( retv>=0 && cmd_tok == CMD_MKDIR )
+ {
+ if( set_user > 0 || set_group > 0 )
+ {
+ if( chown(dirname, set_user, set_group) < 0)
+ warning(errno, "Cannot change directory owner ", dirname);
+ else if( chmod (dirname, mode & 07777) )
+ warning(errno, "", dirname);
+ }
+ }
+
+ if(retv<0) error(errno, "Cannot create directory ", dirname);
+ return retv;
+}
+
+int
+cmd_mknod()
+{
+ int device;
+ int rv = -1;
+ int mode=0666;
+ if( set_mode >= 0 ) mode=set_mode;
+
+ device = (atoi(flist[2])<<8) + atoi(flist[3]);
+
+ if(flist[1][0] == 'b')
+ rv = mknod(flist[0], S_IFBLK|mode, device);
+ else if(flist[1][0] == 'c' || flist[1][0] == 'u')
+ rv = mknod(flist[0], S_IFCHR|mode, device);
+ else Usage();
+
+ if(rv<0)
+ {
+ error(errno, "", flist[0]);
+ exit(1);
+ }
+ return rv;
+}
+
+int
+warning(enumber, estr, eobj)
+int enumber; char * estr; char * eobj;
+{
+ if(flg_verbose)
+ return error(enumber, estr, eobj);
+ return 0;
+}
+
+int
+error(enumber, estr, eobj)
+int enumber; char * estr; char * eobj;
+{
+ fprintf(stderr, "%s%s: ", prog_name[0]=='-'?"ft":"", prog_name);
+ fprintf(stderr, "%s%s: %s\n", estr, eobj, strerror(enumber));
+ return -1;
+}
diff --git a/tests/grab.c b/tests/grab.c
new file mode 100644
index 0000000..b65fa28
--- /dev/null
+++ b/tests/grab.c
@@ -0,0 +1,81 @@
+
+#include <stdio.h>
+#include <malloc.h>
+
+struct s
+{
+ struct s * n;
+ char v[1];
+};
+
+#define M ((unsigned)-1>>1)
+#define V (M^(M>>1))
+
+main (argc,argv)
+int argc;
+char ** argv;
+{
+ struct s * ptr1 = 0;
+ struct s * ptr2;
+ struct s * ptr3;
+ int i,sz;
+ unsigned long total = 0;
+
+ for(i=0, sz=256 ; i<32; i++, sz = ((sz << 1) | (sz & V)) & M)
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ printf("%2d(%8u)..%08lx..%ld\n",i,sz,(long)ptr2,(long)ptr2);
+ if(ptr2==0) break;
+ total+=sz;
+ if(ptr1==0)
+ {
+ ptr1 = ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ else
+ {
+ ptr3->n = ptr2;
+ ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ }
+ for(sz>>=1; sz>3; )
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ if(ptr2==0) { sz >>=1; continue; }
+ printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2);
+ total+=sz;
+ if(ptr1==0)
+ {
+ ptr1 = ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ else
+ {
+ ptr3->n = ptr2;
+ ptr3 = ptr2;
+ ptr3->n = 0;
+ }
+ }
+ printf("Free all - total was %ldK bytes\n", total/1024);
+ while( ptr1 )
+ {
+ ptr3 = ptr1->n;
+ free(ptr1);
+ ptr1 = ptr3;
+ }
+ ptr2 = (struct s *) malloc(200);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,200,(long)ptr2,(long)ptr2);
+ ptr2 = (struct s *) malloc(30000);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,30000,(long)ptr2,(long)ptr2);
+ ptr2 = (struct s *) malloc(20000);
+ printf("%2d(%8u)..%08lx..%ld\n",i++,20000,(long)ptr2,(long)ptr2);
+ sz = (256<<sizeof(int));
+ do
+ {
+ ptr2 = (struct s *) malloc(sz-sizeof(int));
+ printf("%2d(%8u)..%08lx..%ld\n",i++,sz,(long)ptr2,(long)ptr2);
+ }
+ while(ptr2 && i < 100);
+ exit(0);
+}
diff --git a/tests/hd.c b/tests/hd.c
new file mode 100644
index 0000000..341185f
--- /dev/null
+++ b/tests/hd.c
@@ -0,0 +1,185 @@
+
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+
+int lastnum[16] = {-1};
+long lastaddr = -1;
+long offset = 0;
+
+FILE *fd;
+
+main(argc, argv)
+int argc;
+char **argv;
+{
+ int done = 0;
+ int ar;
+ int aflag = 1;
+
+ for (ar = 1; ar < argc; ar++)
+ if (aflag && argv[ar][0] == '-')
+ switch (argv[ar][1])
+ {
+ case 'r':
+ return reverse_hd(argc, argv);
+ case 'o':
+ offset = strtol(argv[ar] + 2, (void *) 0, 0);
+ break;
+ case '-':
+ aflag = 0;
+ break;
+ default:
+ Usage();
+ }
+ else
+ {
+ fd = fopen(argv[ar], "rb");
+ if (fd == 0)
+ fprintf(stderr, "Cannot open file '%s'\n", argv[ar]);
+ else
+ {
+ do_fd();
+ fclose(fd);
+ }
+ done = 1;
+ }
+
+ if (!done)
+#ifdef MSDOS
+ Usage();
+#else
+ {
+ fd = stdin;
+ do_fd();
+ }
+#endif
+}
+
+Usage()
+{
+ fprintf(stderr, "Usage: hd [-r]|[[-oOffset] file]\n");
+ exit(1);
+}
+
+do_fd()
+{
+ int j, ch;
+ char buf[20];
+ int num[16];
+
+ if (offset)
+ fseek(fd, offset, 0);
+
+ for (ch = 0; ch != EOF; offset += 16)
+ {
+ memset(buf, '\0', 16);
+ for (j = 0; j < 16; j++)
+ num[j] = -1;
+ for (j = 0; j < 16; j++)
+ {
+ ch = fgetc(fd);
+ if (ch == EOF)
+ break;
+
+ num[j] = ch;
+ if (isascii(ch) && isprint(ch))
+ buf[j] = ch;
+ else
+ buf[j] = '.';
+ }
+ printline(offset, num, buf, ch == EOF);
+ }
+}
+
+printline(address, num, chr, eofflag)
+long address;
+int *num;
+char *chr;
+int eofflag;
+{
+ int j;
+
+ if (lastaddr >= 0)
+ {
+ for (j = 0; j < 16; j++)
+ if (num[j] != lastnum[j])
+ break;
+ if (j == 16 && !eofflag)
+ {
+ if (lastaddr + 16 == address)
+ {
+ printf("*\n");
+ fflush(stdout);
+ }
+ return;
+ }
+ }
+
+ lastaddr = address;
+ printf("%06lx:", address);
+ for (j = 0; j < 16; j++)
+ {
+ if (j == 8)
+ putchar(' ');
+ if (num[j] >= 0)
+ printf(" %02x", num[j]);
+ else
+ printf(" ");
+ lastnum[j] = num[j];
+ num[j] = -1;
+ }
+
+ printf(" %.16s\n", chr);
+}
+
+
+/*
+ * This function takes output from hd and converts it back into a binary
+ * file
+ */
+
+/* -- 0 1 2 3 4 5 6 7 8 9 a b c d e f */
+static char *datafmt = "%x: %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x\n";
+reverse_hd()
+{
+ char str[160];
+ char * ptr;
+ int c[16], d[16], x, i, nxtaddr, addr;
+
+ for (i = 0; i < 16; i++)
+ c[i] = 0;
+ nxtaddr = 0;
+
+ for (nxtaddr = 0;;)
+ {
+ if (gets(str) == NULL)
+ break;
+
+ str[57] = 0;
+ ptr = str;
+
+ if( !isxdigit(*ptr) ) continue;
+ addr = strtol(ptr, &ptr, 16);
+ if( *ptr == ':' ) ptr++;
+
+ if (nxtaddr == 0)
+ nxtaddr = addr;
+ while (nxtaddr < addr)
+ {
+ nxtaddr += 16;
+ for (i = 0; i < 16; i++)
+ putchar(c[i]);
+ }
+ for (i = 0; i < 16 && *ptr; i++)
+ {
+ char * ptr2;
+ c[i] = strtol(ptr, &ptr2, 16);
+ if( ptr == ptr2 ) break;
+ putchar(c[i]);
+ ptr = ptr2;
+ }
+ nxtaddr += 16;
+ }
+ return 0;
+}
diff --git a/tests/line2.c b/tests/line2.c
new file mode 100644
index 0000000..6cc11ff
--- /dev/null
+++ b/tests/line2.c
@@ -0,0 +1,15 @@
+
+#include <stdio.h>
+
+char buf[256];
+
+main()
+{
+ FILE * fd;
+ fd = fopen("/etc/passwd", "r");
+
+ while(fgets(buf, sizeof(buf), fd) != NULL)
+ {
+ printf(">>%s", buf);
+ }
+}
diff --git a/tests/lines.c b/tests/lines.c
new file mode 100644
index 0000000..6f3afb0
--- /dev/null
+++ b/tests/lines.c
@@ -0,0 +1,36 @@
+
+#include <string.h>
+#include <fcntl.h>
+
+char *
+readline(fd)
+{
+static char linebuf[256];
+ int cc;
+ char * p;
+
+ cc = read(fd, linebuf, sizeof(linebuf)-1);
+ if( cc <= 0 ) return 0;
+ p = strchr(linebuf, '\n');
+ if( p == 0 ) p = linebuf+sizeof(linebuf)-1;
+ else
+ {
+ p++; lseek(fd, (long)(p-linebuf)-cc, 1);
+ }
+ *p = 0;
+ return linebuf;
+}
+
+main()
+{
+ int fd = open("/etc/passwd", O_RDONLY);
+ char * p;
+
+ if(fd<0) exit(1);
+
+ while( p=readline(fd) )
+ {
+ write(1, ">>", 2);
+ write(1, p, strlen(p));
+ }
+}
diff --git a/tests/ouch.c b/tests/ouch.c
new file mode 100644
index 0000000..c2925c6
--- /dev/null
+++ b/tests/ouch.c
@@ -0,0 +1,27 @@
+
+#include <signal.h>
+#include <stdio.h>
+#include <errno.h>
+
+void trap()
+{
+ write(1, "Ouch!!\n", 7);
+}
+
+main()
+{
+ char buf[2];
+ int cc;
+
+ signal(SIGINT, trap);
+ while( (cc=read(0, buf, 1)) > 0 || (cc == -1 && errno == EINTR) )
+ {
+ if( cc < 0 )
+ fprintf(stderr, "INTR\n");
+ else
+ fprintf(stderr, "%x\n", buf[0]);
+ }
+
+
+ write(1, "\nExit!\n", 7);
+}
diff --git a/tests/rand.c b/tests/rand.c
new file mode 100644
index 0000000..c4fc6d2
--- /dev/null
+++ b/tests/rand.c
@@ -0,0 +1,16 @@
+#include <stdio.h>
+
+FILE * popen();
+
+main()
+{
+ FILE * fd = popen("./hd", "w");
+ int ch;
+
+ srand(time((void*)0));
+
+ for(ch=0; ch<256; ch++)
+ putc(rand(), fd);
+
+ pclose(fd);
+}
diff --git a/tests/size.c b/tests/size.c
new file mode 100644
index 0000000..6b08f46
--- /dev/null
+++ b/tests/size.c
@@ -0,0 +1,83 @@
+#include <fcntl.h>
+#include <a.out.h>
+
+int verbose = 0;
+
+void size(filename)
+ char *filename;
+{
+ int f;
+ struct exec ex;
+ long total;
+ int cc;
+
+ if ((f = open(filename, O_RDONLY)) < 0 )
+ {
+ perror(filename);
+ return;
+ }
+ cc = read(f, &ex, sizeof(ex));
+
+ if (cc == sizeof(ex) && !BADMAG(ex))
+ {
+ total = ex.a_text + ex.a_data + ex.a_bss;
+ if( verbose )
+ {
+ printf("Text segment of %s = %5ld (0x%lx)\n",
+ filename, ex.a_text, ex.a_text);
+ printf("Init data of %s = %5ld (0x%lx)\n",
+ filename, ex.a_data, ex.a_data);
+ printf("Uninit data of %s = %5ld (0x%lx)\n",
+ filename, ex.a_bss, ex.a_bss);
+ printf("Data segment of %s = %5ld (0x%lx)\n",
+ filename, ex.a_total, ex.a_total);
+ printf("Minimum size of %s = %5ld (0x%lx)\n",
+ filename, total, total);
+
+ total = ex.a_total;
+ if( ex.a_flags & A_SEP )
+ total += ex.a_text;
+ printf("Maximum size of %s = %5ld (0x%lx)\n",
+ filename, total, total);
+ }
+ else
+ printf("%-ld\t%-ld\t%-ld\t%-ld\t%-lx\t%s\n",
+ ex.a_text, ex.a_data, ex.a_bss, total, total,
+ filename);
+ }
+ else if( cc > 16 && memcmp(&ex, "\243\206\001\000*", 5) == 0 )
+ { /* *.o file */
+ total = ((unsigned char*)&ex)[9] +
+ ((unsigned char*)&ex)[10] * 256;
+ if( verbose )
+ printf("Size of object %s = %5ld (0x%lx)\n",
+ filename, total, total);
+ else
+ printf("\t\t\t%-ld\t%-lx\t%s\n",
+ total, total, filename);
+ }
+ else
+ printf("%s: Not an a.out file\n", filename);
+ close(f);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ if (argc > 1 && strcmp(argv[1], "-v") == 0 )
+ {
+ verbose++;
+ argc--, argv++;
+ }
+ if (argc < 2)
+ {
+ printf("Usage: %s [-v] file\n", argv[0]);
+ exit(1);
+ }
+ if(!verbose)
+ printf("text\tdata\tbss\tdec\thex\tfilename\n");
+ for (--argc, ++argv; argc > 0; --argc, ++argv)
+ size(*argv);
+ exit(0);
+}
diff --git a/tests/sync.c b/tests/sync.c
new file mode 100644
index 0000000..03ca096
--- /dev/null
+++ b/tests/sync.c
@@ -0,0 +1 @@
+int main() { return sync(); }
diff --git a/tests/ucomp.c b/tests/ucomp.c
new file mode 100644
index 0000000..cc3eef8
--- /dev/null
+++ b/tests/ucomp.c
@@ -0,0 +1,108 @@
+
+/*
+ * Uncompress program this is very very fast
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MAXLEN 255
+
+#define maxno 61000U
+#define USE_BSS
+
+#ifdef USE_BSS
+unsigned char fptr[maxno];
+#else
+unsigned char *fptr;
+#endif
+FILE * fd;
+int key;
+
+main(argc, argv)
+int argc;
+char ** argv;
+{
+#ifndef USE_BSS
+ fptr = (unsigned char * ) malloc(maxno);
+
+ if( fptr == 0 )
+ {
+ perror("Cannot allocate memory");
+ exit(1);
+ }
+#endif
+
+ if( argc < 2 )
+ {
+ fd = stdin;
+ key = getc(fd);
+ uncompress();
+ }
+ else
+ {
+ fd = fopen(argv[1], "r" );
+ if( fd == 0 ) { perror("Open failed"); exit(1); }
+
+ key = getc(fd);
+ uncompress();
+ }
+}
+
+/*
+
+ Uncompression routine -- v.v.fast
+*/
+
+uncompress()
+{
+ register unsigned char * mainscan;
+ register unsigned char * secondscan;
+ register unsigned char * ptr = (unsigned char * ) fptr;
+ register unsigned char * eptr = ptr+maxno;
+ register unsigned int len;
+ register int ch;
+
+ mainscan = ptr;
+
+ for(;;)
+ {
+ ch = getc(fd);
+ if(ch == EOF) break;
+ ch &= 0xFF;
+ if(ch == key)
+ {
+ ch = getc(fd);
+ if( ch == 0 )
+ *mainscan++ = key;
+ else
+ {
+ len = (unsigned char) getc(fd);
+ if( ch & 0x80 )
+ len += ((unsigned char) getc(fd)) << 8;
+ secondscan = mainscan - len;
+ if(len > mainscan - ptr) secondscan += maxno;
+ len = (unsigned char) ch & 0x7F;
+ for( ; len>0; len-- )
+ {
+ *mainscan++ = *secondscan++;
+ if( secondscan == eptr ) secondscan = ptr;
+ if( mainscan == eptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+ }
+ }
+ }
+ else
+ *mainscan++ = ch;
+
+ if( mainscan == eptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+ }
+ if( mainscan != ptr )
+ { write(1, ptr, (int)(mainscan-ptr)); mainscan = ptr; }
+}
+
diff --git a/tests/wc.c b/tests/wc.c
new file mode 100644
index 0000000..08b93ca
--- /dev/null
+++ b/tests/wc.c
@@ -0,0 +1,133 @@
+
+#include <stdio.h>
+#include <ctype.h>
+
+int lflag; /* Want count lines */
+int wflag; /* Want count words */
+int cflag; /* Want count characters */
+
+long lcount; /* File count of lines */
+long wcount; /* File count of words */
+long ccount; /* File count of characters */
+
+long ltotal; /* Total count of lines */
+long wtotal; /* Total count of words */
+long ctotal; /* Total count of characters */
+
+int
+main(argc, argv)
+int argc;
+char **argv;
+{
+ char *p;
+ int ar;
+
+ if (argc > 1 && argv[1][0] == '-')
+ {
+ for (p = argv[1] + 1; *p; p++)
+ {
+ switch (*p)
+ {
+ case 'l':
+ lflag++;
+ break;
+ case 'w':
+ wflag++;
+ break;
+ case 'c':
+ cflag++;
+ break;
+ default:
+ Usage();
+ }
+ }
+ argc--;
+ argv++;
+ }
+
+ /* If no flags are set, treat as wc -lwc. */
+ if (!lflag && !wflag && !cflag)
+ lflag = wflag = cflag = 1;
+
+ /* No filename, use stdin */
+ if (argc == 1)
+ {
+ count(stdin, "");
+ exit(0);
+ }
+
+ /* There is an explicit list of files. Loop on files. */
+ for (ar = 1; ar < argc; ar++)
+ {
+ FILE *f;
+
+ if ((f = fopen(argv[ar], "r")) == NULL)
+ fprintf(stderr, "wc: cannot open %s\n", argv[ar]);
+ else
+ {
+ count(f, argv[ar]);
+ fclose(f);
+ }
+ }
+
+ if (argc > 2)
+ {
+ if (lflag)
+ printf("%7ld ", ltotal);
+ if (wflag)
+ printf("%7ld ", wtotal);
+ if (cflag)
+ printf("%7ld ", ctotal);
+ printf("total\n");
+ }
+ exit(0);
+}
+
+count(f, fname)
+FILE *f;
+char *fname;
+{
+ register int c;
+ register int inword = 0;
+
+ lcount = 0;
+ wcount = 0;
+ ccount = 0;
+
+ while ((c = getc(f)) != EOF)
+ {
+ ccount++;
+
+ if (isspace(c))
+ {
+ if (inword)
+ wcount++;
+ inword = 0;
+ }
+ else
+ inword = 1;
+
+ if (c == '\n' || c == '\f')
+ lcount++;
+ }
+
+ ltotal += lcount;
+ wtotal += wcount;
+ ctotal += ccount;
+
+ if (lflag)
+ printf("%7ld ", lcount);
+ if (wflag)
+ printf("%7ld ", wcount);
+ if (cflag)
+ printf("%7ld ", ccount);
+ if (fname && *fname)
+ printf("%s", fname);
+ printf("\n");
+}
+
+Usage()
+{
+ fprintf(stderr, "Usage: wc [-lwc] [name ...]\n");
+ exit(1);
+}