karl@mstar.UUCP (05/14/87)
Sorry if this is too short -- I didn't know where else to put it. This 'zcat' program works much like the standard public domain zcat (which is usually linked to compress and uncompress), except that it is only a filter -- no command line arguments are used. We use it frequently when shipping compressed software to customers over UUCP, many of whom are not UNIX wizards and don't routinely get good stuff like compress.c from usenet. I was going to submit it to the Obfuscated C contest until I saw the requirement about entries being original work. This program is derived directly from the public domain compress.c. It requires that your machine be able to support 16-bit decompression, which uses very large arrays for hashing. If somebody wanted to make a SHAR that could compress and uuencode files, then include a small program (like this, but with uudecode, too?) that could transform it back, I would kiss their feet. #!/bin/sh # # This is a SHAR archive. To extract, remove everything # above the #!/bin/sh line and type "sh filename" # if `test ! -s ./zcat.c` then echo "Writing ./zcat.c" sed 's/^X//' > ./zcat.c << '\End\of\File\ ./zcat.c' X#include <stdio.h> X#define d define X#d G getchar() X#d I if X#d H(n) ((C*)h)[n] X#d C char X#d U unsigned long X#d u unsigned short X#d R register C* X#d B(n) (1<<(n)) X#d V(a,b) (a&(B(b)-1)) X#d E {fprintf(stderr,"Bad COMPRESS file format\n");exit(1);} Xint i,q,b,n,k=16,e=128,j=0,O=0,S=0;u t[69001];long o,v,c,m,M=B(16),f=0;U h[ X69001];C D[16];long g(){R p=D;I(j>0||O>=S||f>m){I(f>m)m= ++n==k?M:B(n)-1;I(j>0) Xm=B(n=9)-1,j=0;S=fread(D,1,n,stdin);I(S<=0)return-1;O=0;S=(S<<3)-n+1;}q=O;b=n;p X+=q>>3;q&=7;c=V(*p++>>q,8-q);q=8-q;b-=q;I(b>=8)c|=(*p++&255)<<q,q+=8,b-=8;c|=V( X*p,b)<<q;O+=n;return c;}main(){I(G!=31||G!=157)E;k=G;e=k&128;k&=31;M=B(k);I(k> X16)E;z();exit(0);}z(){long w;R s;m=B(n=9)-1;for(w=255;w>=0;w--)t[w]=0,H(w)=(C)w X;f=e?257:256;i=o=g();I(o==-1)return;putchar((C)i);s=(C*)&H(B(16));while((w=g()) X>-1){I(w==256&&e){for(w=255;w>=0;w--)t[w]=0;j=1;f=256;I((w=g())==-1)break;}v=w; XI(w>=f)*s++=i,w=o;while((U)w>=(U)256)*s++=H(w),w=t[w];*s++=i=H(w);do putchar(* X--s);while(s>&H(B(16)));I((w=f)<M)t[w]=(u)o,H(w)=i,f=w+1;o=v;}} \End\of\File\ ./zcat.c else echo "Not overwriting ./zcat.c" fi echo "Finished archive 1 of 1" exit -- Karl Fox, Morning Star Technologies, Inc. ...!{cbatt,cbosgd}!mstar!karl
jaw@aurora.UUCP (James A. Woods) (05/23/87)
# "Summer came and went, and I realized that the book was monstrous. [....] I thought of fire, but I feared that the burning of an infinite book might likewise prove infinite and suffocate the planet with smoke." -- Jorge Luis Borges, "The Book of Sand" Some may doubt the efficacy of what Karl Fox suggested. Though what I proffered is improved below, a self-decompressing shar can pay off in CPU time as well as modem bandwidth. For example, using a 68020-class machine (Sun 3/160), 'shark'ing a 230KB /etc/hosts took about 5 seconds to yield a 104KB file. The inverse (old code) required about 7 CPU (user+sys) seconds to compile (cc, no -O) the decoders, 11 seconds to do the decoding (atob+zcat), and 11 seconds of shell "here" document scanning (two passes). The resulting 7KB per second would likely beat 'uucp' processing time for the data if passed by a Telebit modem, about the best that can be done for phones (10-14 kbits/sec). Bandwidth savings were knocked down to 40% by the 25% expansion of 'btoa' (for the initiate, a base-85 converter by Paul Rutter and Joe Orost, mapping 4->5 chars vs. the meager 3->4 of 'uuencode'). Bandwidth payoff for text starts at ~10KB, considering the 2.5KB overhead. Well, I realized how much slop was still there, so I slimmed 'shark' (or 'sharc'? for 'arc' replacement) by another 250 bytes. The code to follow uses 'tar' instead of 'shar' for speed (it's really just 'tarmail' with decoder source). 'The End' substitutes for 'ZZ' for reliability (let's see, 128 exp 7 gives the rarity of a sabotaged line, or better than disk CRC). In addition to some other changes (assuming globals start life at 0, tightened loops, shift replacement, more quirky #defines, name shortening, etc.), you may dispense with the recursive Capt. Beefheart "echo" for even more. Go back to 'shar' if you mail to non-Unix boxes w/o John Gilmore's PD 'tar'. -- jaw -------- 'cut' here for a new 'shark' (do *not* shar -- keep intact) -------- #!/bin/sh echo 'echo "Cleverly he dialed from within." -- D. Van Vliet, "Trout Mask Replica">/dev/null' echo "echo decoding ..." echo "cat>atob.c<<'ZZ'" cat<<'TROUSER PRESS' #include <stdio.h> #define d define #d R register #d I if #d E else #d D {fprintf(stderr,"bad format or Csum to atob\n");exit(1);} FILE *T;long X,M,C,w,B; d(c)R c;{I(c=='z'){I(B)D E for(c=4;c--;)b(0);}E I(c>='!'&&(c<'!'+85)) {I(!B){w=c-'!';++B;}E I(B<4){w*=85;w+=c-'!';++B;}E{w=w*85+c-'!';b((int)((w>>24) &255));b((int)((w>>16)&255));b((int)((w>>8)&255));b((int)(w&255));w=B=0;}}E D} b(c)R c;{X^=c;M+=c;M++;I(C&0x80000000){C*=2;C++;}E{C*=2;}C+=c;putc(c,T);}main (g,v)char **v;{R c;R long i;char n[99],Q[99];long A,B,x,s,r;I(g!=1){fprintf (stderr,"bad args to %s\n",v[0]);exit(2);}sprintf(n,"/tmp/atob.%x",getpid()); T=fopen(n,"w+");I(!T)D unlink(n);for(;;){I(!fgets(Q,99,stdin))D I(!strcmp(Q, "xbtoa Begin\n"))break;}while((c=getchar())!=EOF){I(c=='\n')continue;E I(c=='x') break;E d(c);}I(scanf("btoa End N %ld %lx E %lx S %lx R %lx\n",&A,&B,&x,&s,&r)!= 5)D I(A!=B||x!=X||s!=M||r!=C)D E{fseek(T,0L,0);for(i=A;i--;)putchar(getc(T));}} TROUSER PRESS echo "ZZ" echo "cc -o atob atob.c" echo "cat>zcat.c<<'ZZ'" cat<<'BAFFLE RHINOCEROSES' #include <stdio.h> #define d define #d G getchar() #d I if #d H(n) ((C*)h)[n] #d C char #d U unsigned long #d u unsigned short #d R register C* #d B(n) (1<<(n)) #d V(a,b) (a&(B(b)-1)) #d E {fprintf(stderr,"Bad COMPRESS file format\n");exit(1);} #d N 256 #d L for(w=N;w--;)t[w]=0 int i,q,b,n,k=16,e=128,j,O,S;u t[69001];long o,v,c,m,M=B(16),f;U h[69001];C D[16];long g(){R p=D;I(j>0||O>=S||f>m){I(f>m)m= ++n==k?M:B(n)-1;I(j>0)m=B(n=9) -1,j=0;S=fread(D,1,n,stdin);I(S<=0)return-1;O=0;S=S*8-n+1;}q=O;b=n;p+=q>>3;q&=7; c=V(*p++>>q,8-q);q=8-q;b-=q;I(b>=8)c|=(*p++&255)<<q,q+=8,b-=8;c|=V(*p,b)<<q; O+=n;return c;}main(){I(G!=31||G!=157)E;k=G;e=k&128;k&=31;M=B(k);I(k>16)E;z();} z(){long w;R s;m=B(n=9)-1;L,H(w)=(C)w;f=e?257:N;i=o=g();I(o==-1)return; putchar((C)i);s=(C*)&H(B(16));while((w=g())>-1){I(w==N&&e){L;j=1;f=N;I((w=g()) ==-1)break;}v=w;I(w>=f)*s++=i,w=o;while((U)w>=(U)N)*s++=H(w),w=t[w];*s++=i=H(w); do putchar(*--s);while(s>&H(B(16)));I((w=f)<M)t[w]=(u)o,H(w)=i,f=w+1;o=v;}} BAFFLE RHINOCEROSES echo "ZZ" echo "cc -o zcat zcat.c" echo "(atob|zcat|tar xvf - )<<'The End'" tar cf - $* |compress|btoa echo "The End" echo "rm zcat* atob*"