diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile | 33 | ||||
-rw-r--r-- | tests/README | 24 | ||||
-rw-r--r-- | tests/compr.c | 383 | ||||
-rw-r--r-- | tests/env.c | 81 | ||||
-rw-r--r-- | tests/ft.c | 1209 | ||||
-rw-r--r-- | tests/grab.c | 81 | ||||
-rw-r--r-- | tests/hd.c | 185 | ||||
-rw-r--r-- | tests/line2.c | 15 | ||||
-rw-r--r-- | tests/lines.c | 36 | ||||
-rw-r--r-- | tests/ouch.c | 27 | ||||
-rw-r--r-- | tests/rand.c | 16 | ||||
-rw-r--r-- | tests/size.c | 83 | ||||
-rw-r--r-- | tests/sync.c | 1 | ||||
-rw-r--r-- | tests/ucomp.c | 108 | ||||
-rw-r--r-- | tests/wc.c | 133 |
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); +} |