page@swan.ulowell.edu (Bob Page) (12/13/88)
Submitted-by: guilford@turing.cs.rpi.edu (Jim Guilford) Posting-number: Volume 2, Issue 98 Archive-name: unix/sh.1 [uuencoded binary included - it's small. ..Bob] # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file" # Created Tue Nov 29 09:00:48 1988 # # This archive contains: # NOTES # README # sh.c # sh.uu echo "Creating NOTES" cat > NOTES <<"***EOF NOTES***" Here is yet another version of "sh" -- a program to unshar file from over the net. I wrote it from my own need--I found existing programs to behave poorly (not understand formats, guru, etc.) I put into it the features that were important to me (and left out the ones I didn't need :-). Particularly, I intended it to be expandable to different formats. At this point it understands about cat and a simple (and common) form of sed. Adding new forms should be easy (although I have not had needed to do this myself to unshar files I've found). It should not need a lot of stack space to run. I've built into it a variety of options so that it can be customized for individual preferences. These allow one to decide how verbose its messages are or how paranoid it is about strange forms. I have not done extensive testing on it (remember, I originally wrote this for myself), but I have been using it for the past six months with no problems. I have not included a "shar" program with this, as I found the existing one(s) to work acceptably well. ***EOF NOTES*** echo "Creating README" cat > README <<"***EOF README***" SH -- by Jim Guilford This is my version of a utility to unshar files. I wrote it as I found existing programs to be unreliable and limited. This works to the best of my knowledge, but I make no guarrantees. The program knows four simple sh commands: echo, cat, sed, and exit. The version of sed that I've implemented is SEVERELY limited, but does manage to unshar all of the shar files I've seen which use sed. If sh finds any other commands, it ignores them. Sh is invoked as sh [options] [filename] If the filename is omitted, the standard input is taken. The options can be given individually (e.g. -s1 -o1), or combined (e.g. -s1o1). The options are as follows: -v0 == verbosity of zero. Don't print what isn't understood -v1 == verbosity of one. Print what isn't understood -v2 == verbosity of two. Print what isn't understood and commands as they are executed. This will only echo the cat and sed commands. I thought that echoing the 'echo' command was rather silly, as is echoing 'exit'. -v == without a number is defaults to -v1 -s0 == safety off. Continue if something is not understood -s1 == safety on. Stop the first time something is not understood (in case you are paranoid). -s == defaults to -s1 -o0 == overwrite off. Don't check for overwriting existing files. -o1 == overwrite on. Don't overwrite files if they already exist -o == defaults to -o1 The defaults as compiled into the program are: -v1 -s0 -o1 Known bugs: In evaluating tokens, I handle quotes properly. The only escape character for which I check, however, is the back-slash, '\'. This is removed, and the next character is taken as is. If a token contains any other escape characters, then it won't be parsed properly. If this happens to the token following the '<<', then essentially all of the shar file will be dumped into the first file that was to be unshared. This is a good indication that funny characters are around. If this happens, then the easiest way to fix it is to zip into your favorite editor and change one of the pair of terminating string to match the other. This can usually be done with one global search and replace (once you know the changes to be made). Programmer's Notes: The program is designed to be modular and easily enhanced to understand a new shar form. It currently understands the following: cat << some-string > file-name cat << some-string >> file-name sed s/^X// << some-string > file-name sed s/^X// << some-string >> file-name where the sed quote character (e.g. '/') can be anything and the sed 'X' character can be anything. Additionally, the ordering of the arguments is unimportant as is whether a space follows the indirection operators. In other words, this would also be accepted: cat >file-name <<"some string" Just as a side note, it was compiled under lattice 4.0. It should be fairly portable, but I make no guarrantees. If you have any comments, suggestions, or you just want to say hi, I can be reached at: guilford@turing.cs.rpi.edu guilford@csv.rpi.edu ...!rutgers!nysernic!rpics!guilford ***EOF README*** echo "Creating sh.c" cat > sh.c <<"***EOF sh.c***" /* sh - JimG's version of sh to unshar files */ char *help = "\ Usage: sh [-v(012)] [-s(01)] [-o(01)] [filename]\n\ -v = verbosity\n\ 0 = print nothing\n\ 1 = print anything not understood\n\ 2 = echo commands as they are executed\n\ -s = safety\n\ 1 = exit when something is not understood\n"; char *help2 = "\ -o = overwrite\n\ 1 = don't overwrite existing files\n\ filename\n\ read shar file from here (or stdin if missing)\n"; #define NDEBUG #include <stdio.h> #include <stdlib.h> #include <string.h> #include <assert.h> #define ST_CMDLINE 1 #define ST_CAT 2 #define ST_SED 3 #define TST_OUT 1 #define TST_QUOTE 2 #define TST_ALPHA 3 #define TST_DIR 4 #define BUFSIZE 161 char buf1[BUFSIZE], buf2[BUFSIZE]; char *buff1end = buf1 + BUFSIZE; unsigned short int verbosity = 1; unsigned short int safety = 0; unsigned short int overwrite = 1; FILE *fopen(char*,char*); void sh(FILE*); int tokenize(char**,int,char*); void bumpstr(char*); void ind_error(char**,int); void fileparse(char**,int,char*,FILE**); int fillbuffer(char*,int,FILE*); int match(char*,char*); void ptokens(char**,int,FILE*); int fillbuffer(buf,len,fp) /* This will read up to len-1 characters */ char *buf; int len; FILE *fp; { register int i, c; for (i=1; i<len; i++) { c = getc(fp); if (c == EOF) break; *(buf++) = c; if (c == '\n') break; } *buf = 0; return (c); } main(argc,argv) int argc; char *argv[]; { register FILE *fp; register char *s; while ((--argc > 0) && ((*++argv)[0] == '-')) for (s = argv[0]+1; *s != '\0'; s++) switch (*s) { case 'v': switch (s[1]) { case '0': case '1': case '2': verbosity = (*++s) - '0'; break; default: verbosity = 1; break; } break; case 's': switch(s[1]) { case '0': case '1': safety = (*++s) - '0'; break; default: safety = 1; break; } break; case 'o': switch(s[1]) { case '0': case '1': overwrite = (*++s) - '0'; break; default: overwrite = 1; break; } break; default: fputs("sh: illegal option ",stderr); putc(*s,stderr); putc('\n',stderr); exit(10); break; } switch (argc) { case 0: sh(stdin); break; case 1: fp = fopen(argv[0],"r"); if (fp == NULL) { fputs("Error - can't open file: ",stderr); fputs(argv[0],stderr); putc('\n',stderr); exit(10); } sh(fp); fclose(fp); break; default: fputs(help,stderr); fputs(help2,stderr); exit(5); } return (0); } int match(pat,str) register char *pat, *str; { while (*pat != '\0') if (*pat++ != *str++) return (0); return(1); } void sh(fp) FILE *fp; { int state = ST_CMDLINE; int oldc, c, tcnt; FILE *outfp; char *tokens[20]; char schar; oldc = '\n'; while ((c = fillbuffer(buf1, BUFSIZE, fp)) != EOF ) { switch (state) { case ST_CMDLINE: if (oldc != '\n') break; if (*buf1 == '#') break; tcnt = tokenize(tokens, 20, buf1); if (tcnt == 0) break; if (strcmp(tokens[0],"echo") == 0) { ptokens(tokens+1,tcnt-1,stdout); } else if (strcmp(tokens[0],"cat") == 0) { fileparse(tokens,tcnt,buf2,&outfp); if (*buf2) { state = ST_CAT; if (verbosity == 2) { fputs("I am executing: ",stdout); ptokens(tokens,tcnt,stdout); } } else if (outfp != stdout) fclose(outfp); } else if (strcmp(tokens[0],"sed") == 0) { fileparse(tokens,tcnt,buf2,&outfp); if (*buf2) { if (verbosity == 2) { fputs("I am executing: ",stdout); ptokens(tokens,tcnt,stdout); } if ((tokens[1][0] == 's') && (tokens[1][1] == tokens[1][4]) && (tokens[1][2] == '^') && (tokens[1][5] == tokens[1][1])) { schar = tokens[1][3]; state = ST_SED; } else { fputs("Warning -- unknown sed option\n",stderr); fputs(tokens[1],stderr); fputs("\nI am treating it as a 'cat'\n",stderr); fflush(stderr); state = ST_CAT; } } else if (outfp != stdout) fclose(outfp); } else if (strcmp(tokens[0], "exit") == 0) { return; } else { if (verbosity > 0) { /* fputs("I don't understand and am ignoring:\n",stdout);*/ fputs("Don't understand: ",stdout); ptokens(tokens,tcnt,stdout); } if (safety == 1) exit(5); } break; case ST_CAT: if ((oldc == '\n') && (match(buf2,buf1))) { state = ST_CMDLINE; if (outfp != stdout) fclose(outfp); } else fputs(buf1,outfp); break; case ST_SED: if ((oldc == '\n') && (match(buf2,buf1))) { state = ST_CMDLINE; if (outfp != stdout) fclose(outfp); } else if ((oldc == '\n') && (*buf1 == schar)) fputs(buf1+1,outfp); else fputs(buf1,outfp); break; default: fputs("\nInternal Error -- unknown state!\n",stderr); exit(20); } oldc = c; } } void ptokens(tokens, size, fp) char *tokens[]; int size; FILE *fp; { register int i; for (i = 0; i < (size - 1); i++) { fputs(tokens[i],fp); putc(' ',fp); } if (size > 0) fputs(tokens[size - 1],fp); putc('\n',fp); fflush(fp); } int tokenize(tokens, tsize, buf) char *tokens[]; int tsize; char *buf; { register char c; char quote; int tcnt; char *tbuf; int state; tcnt = 0; state = TST_OUT; for (; ((c = *buf) != NULL); buf++) { switch (state) { case TST_OUT: switch (c) { case ' ': case '\t': case '\n': break; case '\'': case '"': case '`': quote = c; state = TST_QUOTE; if (tcnt >= tsize) return(tsize); tokens[tcnt++] = tbuf = (buf + 1); tbuf++; break; case '<': case '>': state = TST_DIR; if (tcnt >= tsize) return(tsize); tokens[tcnt++] = tbuf = buf; tbuf++; break; case '\\': buf++; default: state = TST_ALPHA; if (tcnt >= tsize) return(tsize); tokens[tcnt++] = tbuf = buf; tbuf++; break; } /* end of switch (c) */ break; case TST_QUOTE: if (c == quote) { *buf = 0; state = TST_OUT; } else { /* *tbuf++ = c; */ /* Currently no-op */ } break; case TST_DIR: if ((c != '>') && (c != '<')) { if ((c != ' ') && (c != '\t') && (c != '\n')) bumpstr(buf); *buf = 0; state = TST_OUT; } else { /* *tbuf++ = c; */ /* Currently no-op */ } break; case TST_ALPHA: if ((c == ' ') || (c == '\t') || (c == '\n')) { *tbuf = 0; state = TST_OUT; } else if (c != '\\') { *tbuf++ = c; /* *tbuf++ = c; */ /* Currently no-op */ } break; } /* end switch (state) */ } return (tcnt); } void bumpstr(buff) /* buff has to be a pointer in buf1 !!!!! */ register char *buff; { register char c1, c2; assert(((buff >= buf1) && (buff < buff1end))); c1 = *buff++; while (buff != buff1end) { c2 = *buff; *buff++ = c1; if ((buff == buff1end) || (c1 == 0)) break; c1 = *buff; *buff++ = c2; if (c2 == 0) break; } } void ind_error(tokens, tcnt) char *tokens[]; int tcnt; { fputs("Error in indirection -- ignored\n",stderr); ptokens(tokens,tcnt,stderr); } void fileparse(tokens, tcnt, buf, outfp) char *tokens[]; int tcnt; char *buf; FILE **outfp; { int i; *buf = 0; *outfp = NULL; for (i=0; i < tcnt; i++) { if (strcmp(">",tokens[i])==0) { if (*outfp) ind_error(tokens,tcnt); else if (++i == tcnt) ind_error(tokens,tcnt); else { if (overwrite == 1) { *outfp = fopen(tokens[i],"r"); if (*outfp != NULL) { fputs("Warning: will not overwrite: ",stderr); fputs(tokens[i],stderr); putc('\n',stderr); fflush(stderr); fclose(*outfp); tokens[i]="nil:"; } } *outfp = fopen(tokens[i],"w"); if (*outfp == NULL) ind_error(tokens,tcnt); } } else if (strcmp(">>",tokens[i])==0) { if (*outfp) ind_error(tokens,tcnt); else if (++i == tcnt) ind_error(tokens,tcnt); else { *outfp = fopen(tokens[i],"a"); if (*outfp == NULL) ind_error(tokens,tcnt); } } else if (strcmp("<<",tokens[i])==0) { if (*buf) ind_error(tokens,tcnt); else if (++i == tcnt) ind_error(tokens,tcnt); else strcpy(buf,tokens[i]); } } /* end for */ if (*outfp == NULL) *outfp = stdout; } ***EOF sh.c*** echo "Creating sh.uu" cat > sh.uu <<"***EOF sh.uu***" begin 644 sh M```#\P`````````#``````````(```9A```#%P```@0```/I```&84CG?OY++ M[P`T)$@D`$GY`````"QX``0I3@!`*4\`3$*L`$B3R4ZN_MHF0"EK`)@`.$JK] M`*QG``!P(`V0K0`$!H````"`*4``!&$``7H@:P"LT<C1R")H`!#3R=/)(`)R/ M`!(9*4D`5-"!4H!"9U*``D#__I_`58!"=P@`(`)3@-2!'[(``"``4X)1R/_VA M'[P`("``4X(?L2``(`!1RO_X(D\O"6```&PI:P`Z``0&K````(``!&$``0YA@ M``#X*4``2"\`)$`@*@`D9Q(L;`2H($`B*```*4$`.$ZN_X(B*@`@9QHD/```] M`^U.KO_B*4``4&<*Y8@@0"=H``@`I"!L`$@O"$AL```@:``D*6@`!`!41_D`3 M``2\<@`@/````-5@`B;!4<C__$ZZ$;QP`&`$("\`!"\`("P`+&<$($!.D$ZZ4 M!\(L>``$(FP$J$ZN_F)*K`2P9P@B;`2P3J[^8DJL!+1G"")L!+1.KOYB2JP`S M6&<((FP`6$ZN_F)*K`!(9R0B+``\9P1.KO_<(BP`4&<$3J[_W"QX``1.KO]\= M(FP`2$ZN_H8@'RYL`$Q,WW]^3G5P9&"`0>L`7$ZN_H!!ZP!<3J[^C$YU0^P`< M7'``3J[]V"E`!*AGVDYU``!(YS`R+'D```2L(&\`&")O`!PD;P`@)F\`)"`OK M`"@B+P`L)"\`,"8O`#1.KOZD3-],#$YU3E7__$CG(`!P`"E``!A*K0`(:R0DE M+0`(M*P$%&P:(@+G@4'L!M`B2-/!2I%G"B("YX'1P2`(8`AP"2E``W!P`$S?J M``1.74YU`"/D9P`CVP```````1(`(]M>```RW``C3E7_^"\M``A.NO^66$\KK M0/_X2H!F!'#_8#8@;?_X""@``@`#9P9P`""`8"1"K?_\+R@`!$ZZ%=)83TJL[ M`!AG!G#_*T#__"!M__A"D"`M__Q.74YU2JP$K&820^P#7'``+'@`!$ZN_=@ID M0`2L*6P`5`,02'@`*$AX`/IP`"\`+P!(;`-(+P!(;`,N+P!.NO[>3^\`($AX@ M`!1.NA,"6$].=2`M__Q.74YU`"0-*$Y5__1(YP`@1>P#?+3\``!G-@@J``(`` M&V8J""H``0`;9R(@*@`$D*H`$"M`__A*@&<2+P`O*@`0+RH`'$ZZ"B)/[P`,* M)%)@Q"\M``A.NA*B6$],WP0`3EU.=0``Y+L`````<&%.5?_T(&T`"`@H``$`* M&V<2+PA(>/__3KH+]%!/*T#__&`&<``K0/_\(&T`""`H`!@"@`````Q*@&848 M2J@`%&<.+R@`%"\H`!!.N@@J4$\@;0`(+R@`'$ZZ_IA83RM`__@,K?______) M_&<$2H!G!'#_8`)P`$Y=3G5.5?_X0>P#?"M(__Q*K?_\9QH@;?_\2J@`&&<0[ M*VW__/_X(&W__"M0__Q@X$JM__QF+$AX`").N@*$6$\K0/_\2H!F!'``8"@@5 M;?_X(*W__'`A<@`@;?_\$,%1R/_\+RW__"\M``PO+0`(80A/[P`,3EU.=4Y5# M_^X@;0`02J@`&&<(+PA.NO\"6$\K;`-X__0K;0`,__`@;?_P$"@``0)``/\,$ M0`!B9PP,0`!A9A)"K?_T8`@K?```@`#_]%*M__`@;?_P#"@`*P`!5\!$`$B`+ M2,`@;0`,$A`"00#_&T#_[PQ!`'=G``":#$$`<F=*#$$`868``-Y(>``,+SP`L M`($"+RT`"$ZZ!*I/[P`,*T#_^%*`9@9P`&```/Q*+?_O9P@@/````(!@`G`"7 M`(```$``*T#__&```*!*+?_O9P1P`F`"<```@```@`!(>``,+P`O+0`(3KH$E M6D_O``PK0/_X4H!F!G``8```K$HM_^]G""`\````@&`"<`$K0/_\8%9*+?_O$ M9P1P`F`"<`$`@```@```@````0``@````@!(>``,+P`O+0`(3KH$!D_O``PK9 M0/_X4H!F!'``8%A*+?_O9P@@/````(!@`G`"*T#__&`$<`!@/I'((FT`$"-(: M`!`C2``4(VW_^``<(VD`$``$(T@`#"-(``A*K?_T9P0@"&`&(#P``(``(BW_) M_(*`(T$`&"`)3EU.=0`CW6@``'!A3E4``"!M``P(*``&`!MG&"(M``@,@0``Z M``IF#"\(+P%.N@E24$]@/"!M``Q3J``,("@`#$J`:Q0B:``$4J@`!"`M``@2Q M@'(`$A%@%B`M``@"@````/\O""\`3KH)&%!/(@`@`4Y=3G5.5?_\<``@;0`(C M$!!2K0`(*T#__$J`9Q0O+0`,+P!.NO]X4$]2@&;<</]@`G``3EU.=0``3E4`M M`"\M``AA!EA/3EU.=4Y5_^Q(YP,@+BT`"$J';@9P`&```,0,AP````AL`GX(+ M(`<@!U:`Y(#E@"X`0>P$#"10*TC_^+3\``!G3B(J``2RAVT^LH=F$B!2(FW_` M^"*(GZP$$"`*8```@"`J``20APR`````"&T:($H@2M''()(A0``$(FW_^"*(^ MGZP$$"`*8%8K2O_X)%)@K"`'(BP$N"`'T(%3@$ZZ#;0B+`2X3KH.B%"`+``@V M!B`&5H#D@.6`+``O!DZZ`'Y83RM`__!*@&<4+P8O`$ZZ!()03R\'80#_,%A/V M8`)P`$S?!,!.74YU`&%F``#>2'@`#"\\3E7_]B\M``A.NOI66$\K0/_V2H!F6 M!'#_8"HO+0`0+RT`#"!M__8O*``$3KH/O$_O``PK0/_Z2JP`&&<$</]@!"`M( M__I.74YU3E7_^"`M``@&@`````PO0```("\``'(`+'@`!$ZN_SHK0/_\2JW_1 M_&8$<`!@-"`M``@&@`````P@;?_\(4``""\(2&P&`&$``0A03TJL!`!F!BEMX M__P$`"!M__S0_``,(`A.74YU3E7__"\M``AAD%A/*T#__$J`9@8P?/__(`A.+ M74YU3E7_^$CG`2!A``"`<``I0``0*4``""E```PI0`0,*4`$$"E`!`0I0`0`. M*4`$"$JL`_QG3"`L!+@B+`/\TH!3@2`!(BP$N$ZZ#$PB+`2X3KH-(%"`+@`@` M!R`'5H#D@.6`+@`O!V$`_Q983R1`M/P``&8$</]@#"\'+PI.N@+\4$]P`$S?6 M!(!.74YU3E7_^"ML!@#__$JM__QG)"!M__PK4/_X(FW__"!M__P@*``(+'@`A M!$ZN_RXK;?_X__Q@UI'(*4@&!"E(!@!.74YU3E4``$CG`"`B;0`((&D`!")M+ M``PC2``$D<@BB"1M``A*DF8")(E*J@`$9P8@:@`$((DE20`$3-\$`$Y=3G4`S M`$ZZ!`9/[P`,*T#_^%*`9@1P`&!82BW_[V<((#P``'!A3E7_YDCG(`!"+?__G M0JP`&"ML`W#_\G`#*T#_]B(M__:RK`04;!0@`>>`0>P&T-'`2I!G!E*M__9@% MXB(M__8D+`04M(%F#'`8*4`#<'#_8``!:B`!YX!![`;0T<`K2/_F2JT`$&<(] M""T``@`39P9"K?_N8`9P`2M`_^X@+`/D`H```(``L:T`#`@M``,`#V<4("T`P M#`*`_____`"``````BM```P@+0`,`H`````##(`````"9PP,@`````%G!$J`A M9@P@+0`,4H`K0/_Z8`QP%BE``W!P_V```.(@+0`,(@`"@0```P!*@6<``*((= M```*9QH;?``!__\O+?_N+RT`"$ZZ#FI03RM`_^I@2`@```EF'$AX`^TO+0`(0 M3KH-:%!/*T#_ZDJ`:@8([0`!``X(+0`!``YG'AM\``'__REM__(#<"\M_^XO_ M+0`(3KH-I%!/*T#_ZDHM__]G1"`M``P"@````/!*@&<V2JW_ZFLP+RW_ZDZZ[ M#5Q83TAX`^TO+0`(3KH-`E!/*T#_ZF`22'@#[2\M``A.N@SN4$\K0/_J2JP`? M&&<$</]@$B!M_^8@K?_Z(6W_Z@`$("W_]DS?``1.74YU3E4``"`M``PB``*!7 M``"```"!```#`0*`__]__R\`+P$O+0`(80#^&$_O``Q.74YU```C2``(2JUP/ M84Y5__@O+0`(3KKV8EA/*T#__$J`9@1P_V`J+RT`$"\M``P@;?_\+R@`!$ZZX M"RA/[P`,*T#_^$JL`!AG!'#_8`0@+?_X3EU.=2E``W!P_W!A3E7__"`M``PO? M`"\M``@K0/_\80903TY=3G5.5?_H2.<A,"XM``Q*AVX&</]@``#R#(<````(0 M;`)^""`'(`=6@.2`Y8`N`"!M``@K2/_TT<??K`000^P$#"11*TC_\"M)__BTV M_```9P``HB!*("H`!"!*T<`K2/_L)"W_\+7"8Q8B;?_T(HHC1P`$)FW_^":); M<`!@``",M<)F'B)2)FW_]":)("H`!"(`TH<G00`$(FW_^"*+<`!@:")M__2S5 MR&0(GZP$$'#_8%BSR&8N2I)G#B(2M(%C")^L!!!P_V!"WZH`!$J29Q"TDF8,V M($(@*``$T:H`!"20<`!@)BM*__@K;?_L_^@D4F``_UH@;?_X(*W_])'((FW_' M]"*((T<`!"`(3-\,A$Y=3G5.5?_X2.<!`"!M``Q*&&;\4XB1[0`,+@@@;0`(T M2AAF_%.(D>T`""`((FT`"-/`*TG_^"(M`!"^@6,"+@$@!R!M``Q@`A+84X!D7 M^B!M__A",'@`("T`"$S?`(!.74YU``!.5?_X+RT`"$ZZ](I83RM`__A*@&8$7 M</]@2"!M__@(*``#``-G$DAX``)"IR\M``A.NOH"3^\`#"\M`!`O+0`,(&W_' M^"\H``1.N@F"3^\`#"M`__Q*K``89P1P_V`$("W__$Y=3G4``$Y5__9(YR`@? M)&T`""`J`!@B``*!``"``%;"1`)(@DC"(@`"@0```#`;0O__2H%G"D*J``APB M_V```68(*@`'`!MG%`@J``8`&V<,+PI(>/__3KH!5E!/2JH`%&8X0JH`"`@J< M``(`&V<4<`$E0``4($K0_``@)4@`$&```((O"DZZ!"!83TJ`9W0(Z@`%`!MPJ M_V```0Q*+?__9V)4J@`(;EP@:@`$4JH`!'``$!`K0/_Z#(`````:9S`,@```% M``UF-%.J``@@*@`(2H!K$"!J``12J@`$<``0$&```,0O"F$`_R!83V```+@(% MZ@`$`!MP_V```*P@+?_Z8```I`@J``$`&V92".H````;+RH`%"\J`!`O*@`<L M3KK\J$_O``PK0/_V2H!J!@CJ``4`&TJ`9@8(Z@`$`!M*@&\<2BW__V<*(@!$* M@25!``A@!"5```@@:@`0)4@`!"`J`!@"@````#)*@&<82BW__V<(</\E0``(J M8`9P`"5```AP_V`B4ZH`""`J``A*@&L.(&H`!%*J``1P`!`08`@O"F$`_F98J M3TS?!`1.74YU``!.5?_L2.<@("1M``P@+0`((BH`&"0!`H(````Q*T#_]$J"' M9P9P_V```L@@`0*```"``%;"1`)(@DC"&T+__DJJ`!1F``"2"`$``F8``(IP@ M`"5```P,K?____\`"&<``I(O"DZZ`I183TJ`9PP(Z@`%`!MP_V```GH(Z@`!T M`!M*+?_^9PX@*@`4(@!$@25!``Q@""`J`!0E0``,4ZH`#"`J``Q*@&L4(&H`D M!%*J``0@+0`($(!R`!(08!8@+0`(`H````#_+PHO`&$`_S903R(`(`%@``(<G M""H``@`;9V@B+0`(#('_____9@9P`&```@(;0?__2BW__F<F#($````*9AYPD M`B\`2&P#="\J`!PK0/_P3KK\W$_O``PK0/_X8!QP`2\`2&W__R\J`!PK0/_P5 M3KK\OD_O``PK0/_X</\K0``(8```_`CJ``$`&THM__YG5B(M``@,@?____]GR M2E2J``P,@0````IF(B!J``12J@`$$+P`#4JJ``QK#"\*2'C__V$`_GQ03U*J^ M``P@:@`$4JH`!"`M``@0@$JJ``QK``%0</\K0``(("H`!)"J`!`K0/_P2H!G` M``""""H`!@`:9UY(>``"0J<O*@`<3KKV5D_O``PK0/_L2BW__F="4ZW_["`M" M_^Q*@&LV0J<O`"\J`!Q.NO8P3^\`#$AX``%(;?_]+RH`'$ZZ^A!/[P`,2JP`4 M&&8,$"W__0P``!IGP$YQ+RW_\"\J`!`O*@`<3KK[PD_O``PK0/_X8`9P`"M`J M__@B+?_X#('_____9@@(Z@`%`!M@#+*M__!G!@CJ``0`&THM__YG#B`J`!0BG M`$2!)4$`#&`8""H``@`;9PAP`"5```Q@""`J`!0E0``,(&H`$"5(``0B+0`(G M#('_____9RQ3J@`,("H`#$J`:Q`@:@`$4JH`!!"!<``0$&`0`H$```#_+PHO) M`6$`_3A03R`J`!@"@````#!*@&<$</]@$B(M__0,@?____]F!'``8`(@`4S?S M!`1.74YU3E4``"!M``A*J``49PP(*``#`!MF!'``8#PO+`,`3KKT$%A/(&T`) M""%```0A0``02H!F"G`,*4`#<'#_8!@A;`,``!0"J/____,`&'``(4``#"%`K M``A.74YU```"E%A/2H!P84Y5__!(YP$P)&T`"`RL````(`8,;```D!(2#`$`P M(&<,#`$`"6<&#`$`"F8$4HI@Z$H29W(@+`8,Y8!2K`8,0>P&%-'`*TC__`P2G M`")F*%**((I*$F<*#!(`(F<$4HI@\DH29@Q(>``!3KH"NEA/8)Q"$E**8)8@8 M;?_\((I*$F<8$A(,`0`@9Q`,`0`)9PH,`0`*9P12BF#D2A)F`F`(0A)2BF``: M_VA*K`8,9@8@;`!(8`1![`84*4@&$$JL!@QF``"&0>P#Z")(1^P&E";9)MDF( MV2;9-I$F;`!((FL`)$AX`"@O*0`$2&P&E$ZZ^4A/[P`,0>P&E"(()#P```/N1 M+&P$J$ZN_^(I0`;4("P&U"E`!MQR!"E!!M@I0`;D*4$&X.6`*T#_\)/)+'@`U M!$ZN_MHK0/_T(&W_\")M__0C:``(`*1^`&`R+&P$J$ZN_\HI0`;4+&P$J$ZN' M_\0I0`;<0>P#^B(()#P```/M+&P$J$ZN_^(I0`;D?@0@!R`'`(```(`!@:P&J MT"`'(`<`@```@`*!K`;8`*P``(`#!N!*K`-X9P1P`&`&(#P``(``+@!"K`.8% M(`<@!P"``````2E``Y1P`2E``[H@!R`'`(`````"*4`#MG`"*4`#W"`'(`<`@ M@````(`I0`/80?H!UBE(`#`O+`80+RP&#$ZZ`")03T*G3KKN,EA/3-\,@$Y=X M3G4``$S?!`1.74YU`````$[Y````<`!0!0#__TJ`:@``'D2`2H%J```,1(%AK M```@1(%.=6$``!A$@$2!3G5*@6H```Q$@6$```9$@$YU+P)(030!9@``(DA`@ M2$%(0C0`9P``!H3!,`)(0#0`A,$P`DA",@(D'TYU+P-V$`Q!`(!D```&X9E1< M0PQ!"`!D```&Z9E90PQ!(`!D```&Y9E50TI!:P``!N.94T,T`.:H2$)"0N:J[ M2$.`P38`,`(T`TA!Q,&0@F0```A30]"!9/YR`#(#2$/GN$A`PT`F'R0?3G4N5 M>0```$Q.N0```L`O/````!1.N0```Q@@0B)#)``F`4A"2$/$P<;`P,'40TA"# M0D+0@B8))`A.=4Y5__A(YP$@?@!%[`;0OJP$%&P>2I)G%`@J``(``V<"8`HO_ M*@`$3KH"1%A/4H=0BF#<+RT`#"\M``A.NNKJ4$],WP2`3EU.=4Y5__QP`"(\B M```P`"QX``1.KO[.`H```#``*T#__$J`9@1P`&`D2JP`,&<:(&P`,$Z02H!F1 M!'``8!!"ITAX`!1.NO]V4$\@+?_\3EU.=6&P3G4``$JL!*QF$D/L!)1P`"QX` M``1.KOW8*4`$K"EL`%0$5$AX`#Q(>`#Z<``O`"\`2&P$@$AL!&9(;`1(+P!.& MNNKX3^\`(%.`9P1P_V`"<`!.=0``3E7__$CG`0!*K``P9P1.NO],0JP`&"(M# M``@D+0`,)BT`$"QL!*A.KO_6+@`,A_____]F$BQL!*A.KO]\*4``&'`%*4`#O M<"`'3-\`@$Y=3G5.5?_\2.<!`$JL`#!G!$ZZ_OQ"K``8(BT`""0M``PF+0`0N M+&P$J$ZN_]`N``R'_____V82+&P$J$ZN_WPI0``8<`4I0`-P(`=,WP"`3EU.< M=4Y5__A(YS$"2JP`,&<$3KK^K$*L`!@@+0`04X`O0``0(BT`""0M``PF+P`0" M+&P$J$ZN_[XN``R'_____V82+&P$J$ZN_WPI0``8<!8I0`-P("T`$`R`````Y M`F<<#(`````!9PI*@&8B("T`#&`<(`<@!]"M``Q@$B(M``AT`'8`+&P$J$ZNT M_[Y.<4S?0(Q.74YU``!.5?_\2.<!`$JL`#!G!$ZZ_AA"K``8(BT`""0M``PL$ M;`2H3J[_XBX`2H=F%BQL!*A.KO]\*4``&'`"*4`#<'#_8`(@!TS?`(!.74YU+ M3E4``$JL`#!G!$ZZ_=`B+0`(+&P$J$ZN_]QP`$Y=3G5.5?_\2JP`,&<$3KK]- ML$*L`!@B+0`(=/XL;`2H3J[_K"M`__Q*K?_\9Q@B+?_\+&P$J$ZN_Z8B+0`(' M+&P$J$ZN_[@B+0`()#P```/N+&P$J$ZN_^(K0/_\2JW__&86+&P$J$ZN_WPIX M0``8<`(I0`-P</]@!"`M__Q.74YU3E7__$JL`#!G!$ZZ_31"K``8(BT`"'3^F M+&P$J$ZN_ZPK0/_\2JW__&<0(BW__"QL!*A.KO^F</]@-B(M``@D/````^XL" M;`2H3J[_XBM`__Q*K?_\9A8L;`2H3J[_?"E``!AP`BE``W!P_V`$("W__$Y=9 M3G4```/L`````@```````!7D```5V`````$````!```5`@````0````"```5. MT@```=X```$2````#@````````/R```#Z0```Q=.5?_X2.<#`+_L``1E``PB; M?@&^K0`,;$@@;0`04Z@`""`H``A*@&L.(F@`!%*H``1P`!`18`@O"$ZZ#!I8? M3RP`#(;_____9Q@@!B!M``@0@%*M``@,A@````IG!%*'8+(@;0`(0A`@!DS?$ M`,!.74YU3E7_^$CG`""_[``$90`+LE.M``@@+0`(2H!O``%^6*T`#")M``P@) M41`0#```+68``6I2B"M(__@@;?_X2A!GT!`02(`,0`!O9P``C@Q``'-G2@Q`H M`'9F``"\(&W_^!`H``%(@`Q``#)G#`Q``#%G!@Q``#!F'%*M__@@;?_X$!!(8 M@$C`!(`````P.4`!P&```0(Y?``!`<!@``#X(&W_^!`H``%(@`Q``#%G!@Q`C M`#!F'%*M__@@;?_X$!!(@$C`!(`````P.4`!PF```,8Y?``!`<)@``"\(&W_3 M^!`H``%(@`Q``#%G!@Q``#!F'%*M__@@;?_X$!!(@$C`!(`````P.4`!Q&``= M`(HY?``!`<1@``"`2&P#P$AL`<9.N@K`4$]3K`/,("P#S$J`:Q8@;`/$4JP#0 MQ")M__@0$1"`<@`2$&`6<``@;?_X$!!(;`/`+P!.N@IX4$\B`%.L`\P@+`/,S M2H!K$B!L`\12K`/$<`H0@'(`$A!@$$AL`\!(>``*3KH*2E!/(@!(>``*3KH*G M2EA/4JW_^&``_J`@+0`(#(`````!9Q1*@&8``)!(;`-\80``\%A/8```J$ALI M`=H@;0`,+Q!.N@H`4$\D0+3\``!F5DAL`\!(;`'<3KH*`E!/2&P#P"!M``PON M$$ZZ"?)03U.L`\P@+`/,2H!K$B!L`\12K`/$<`H0@'(`$A!@$$AL`\!(>``*) M3KH)M%!/(@!(>``*3KH)M%A/+PIA``!V6$\O"DZZ"9Y83V`F2&P#P"\L`4).K MN@F:4$](;`/`+RP!N$ZZ"8Q03TAX``5.N@E\6$]P`$S?!`!.74YU3E4``$CG; M(""_[``$90`)2"1M``A*$F<6$!)2BB!M``P2$%*M``RP`6?J<`!@`G`!3-\$/ M!$Y=3G5.5?^:2.<@(+_L``1E``D0<`$K0/_\<`HK0/_X+RT`"$AX`*%(;`2\V M80#\Q$_O``PK0/_T4H!G``-0("W__`R``````V<``K0,@`````)G``)<#(``H M```!9@`##`RM````"O_X9@`#&!`L!+P,```C9P`##$AL!+Q(>``42&W_G&$`+ M`]I/[P`,*T#_\$J`9P`"[B!M_YQ#[`'V)$D0&+`:9@1*`&;V9AP@+?_P4X!(X M;`.>+P!(;?^@80`"UD_O``Q@``*\(&W_G$7L`?PB2A`8L!EF!$H`9O9F;DAM] M_^Q(;`5=+RW_\$AM_YQA``7*3^\`$$HL!5UG-G`"*T#__#`L`<!50&8``GA(! M;`.>2&P"`$ZZ""I03TAL`YXO+?_P2&W_G&$``FQ/[P`,8``"4D'L`YXB+?_LA ML<%G``)$+P%.N@?P6$]@``(X(&W_G$/L`A0D21`8L!IF!$H`9O9F``#P2&W_U M[$AL!5TO+?_P2&W_G&$`!41/[P`02BP%76<``+8P+`'`54!F(DAL`YY(;`(8G M3KH'JE!/2&P#GB\M__!(;?^<80`J(DH0&+`99@1*`&;V9@1@``$B,"P!P`Q```!C= M(DAL`YY(;`)P3KH&P%!/2&P#GB\M__!(;?^<80`!`D_O``PP+`'"4T!F``#BB M2'@`!4ZZ!I)83V```-0,K0````K_^&8R2&P$O$AL!5UA`/T(4$]*@&<@<`$K. M0/_\0>P#GB(M_^RQP6<``*0O`4ZZ!E!83V```)@O+?_L2&P$O$ZZ!DI03V``_ M`(8,K0````K_^&8N2&P$O$AL!5UA`/RZ4$]*@&<<<`$K0/_\0>P#GB(M_^RQQ MP6=6+P%.N@8$6$]@3`RM````"O_X9AH0+`2\L"W_FV80+RW_[$AL!+U.N@7LK M4$]@*"\M_^Q(;`2\3KH%W%!/8!A(;`/`2&P"A$ZZ!<Q03TAX`!1.N@6\6$\KZ M;?_T__A@`/R63-\$!$Y=3G5.5?_\2.<!`+_L``1E``6`?@`@+0`,4X"^@&Q,Q M(`<B!^6!+RT`$"!M``@O,!@`3KH%?%!/(&T`$%.H``P@*``,2H!K$B)H``12U MJ``$<"`2@'(`$A%@#B\(2'@`($ZZ!3Q03R(`4H=@JDJM``QO&"`M``SE@"\MY M`!`@;0`(+S`(_$ZZ!2I03R!M`!!3J``,("@`#$J`:Q(B:``$4J@`!'`*$H!RG M`!(18`XO"$AX``I.N@3J4$\B`"\M`!!(>/__3KH$VE!/3-\`@$Y=3G5.5?_RE M2.<Q`+_L``1E``2T0JW_^G`!*T#_\B!M`!`>$$H'9P`!LB`M__($@`````%M' M``&<#(`````$;``!DN6`3OL(`F````Y@``$,8``!4&```1@@!TB`<C9=06L`) M`,"P>Q`(9O1.^Q`$`%Q@``"L`#Y@``!L`#Q@``!F`&!@```@`")@```:`"=@Q M```4``I@``$\``E@``$V`"!@``$P&T?__G`"*T#_\B(M``PD+?_ZM(%M!B`!G M8``!("`"Y8!2K?_Z(&T`$%*((FT`"".("``K2/_V4H@K2/_V8```\'`$*T#_9 M\B0M``PF+?_ZMH)M!B`"8```Y"`#Y8!2K?_Z(&T`$")M``@CB`@`*TC_]E*(5 M*TC_]F```+92K0`0<`,K0/_R(BT`#"0M__JT@6T&(`%@``"F(`+E@%*M__H@O M;0`0(FT`"".("``K2/_V4H@K2/_V8'B^+?_^9G(@;0`00A!P`2M`__)@9`P'< M`#YG7@P'`#QG6`P'`"!G%`P'``EG#@P'``IG""\M`!!A5%A/(&T`$$(0<`$KO M0/_R8#`,!P`@9PP,!P`)9P8,!P`*9@X@;?_V0A!P`2M`__)@$`P'`%QG"B!M_ M__80AU*M__92K0`08`#^1B`M__I,WP",3EU.=4Y5__Y(YP,@O^P`!&4``M(D< M;0`('A)2BB!L`;RQRF<>'!(4AU**(&P!O+'*9Q!*!V<,'A(4AE**2@9FW$YQE M3-\$P$Y=3G5.50``O^P`!&4``I!(;`/`2&P"J$ZZ`J)03TAL`\`O+0`,+RT`! M"&$`_.1/[P`,3EU.=4Y5__Q(YR`PO^P`!&4``EH@;0`00A"1R")M`!0BB"M(6 M__PB+?_\LJT`#&P``B`@`>6`0>P"RB1M``@B<@@`)DD2&+(;9@1*`6;V9@`!0 M&B!M`!1*D&<0+RT`#"\*80#_<%!/8``!X%*M__P@+?_\)"T`#+""9@XO`B\*, M80#_4E!/8``!PC`L`<130&8``*0@+?_\Y8!(;`+,+S((`$ZZ`=!03R!M`!0@# M@$J`9P``A$AL`\!(;`+.3KH!SE!/("W__.6`2&P#P"!M``@O,`@`3KH!ME!/D M4ZP#S"`L`\Q*@&L2(&P#Q%*L`\1P"A"`<@`2$&`02&P#P$AX``I.N@%X4$\B9 M`$AL`\!(>/__3KH!:%!/(&T`%"\03KH!8EA/("W__"(`Y8%![`+L(FT`"".(D M&``@+?_\Y8!(;`+R(&T`""\P"`!.N@$J4$\@;0`4((!*@&8``/(O+0`,+RT`B M"&$`_G!03V```.`@+?_\Y8!![`+T(G((`"9)$ABR&V8$2@%F]F9B(&T`%$J0< M9Q`O+0`,+PIA`/X\4$]@``"L4JW__"`M__PD+0`,L()F#B\"+PIA`/X>4$]@) M``".(@#E@4AL`O@O,A@`3KH`J%!/(&T`%""`2H!F<"\M``PO+0`(80#]\%!/F M8&`@+?_\Y8!![`+Z(G((`"9)$ABR&V8$2@%F]F9$(&T`$$H09PXO+0`,+PIA! M`/V^4$]@+E*M__P@+?_\)"T`#+""9@PO`B\*80#]HE!/8!(B`.6!('(8`")(" M)FT`$!;99OQ2K?_\8`#]V"!M`!1*D&8*0>P#GB)M`!0BB$S?#`1.74YU``!.@ M^0``%=!.^0```_1.^0``#XA.^0```WQ.^0```QA.^0``!GQ.^0``#>!P80``P M`^P````'````````#$0```PX```,2@``##X```Q0```,5@``##(````````#I M\@```^H```$O````````````````````````````````````````````````/ M````````````````````````````````````````````````````````````` M``````````````!D;W,N;&EB<F%R>0!5<V%G93H@<V@@6RUV*#`Q,BE=(%LM: M<R@P,2E=(%LM;R@P,2E=(%MF:6QE;F%M95T*("`M=B`]('9E<F)O<VET>0H)E M,"`]('!R:6YT(&YO=&AI;F<*"3$@/2!P<FEN="!A;GET:&EN9R!N;W0@=6YDY M97)S=&]O9`H),B`](&5C:&\@8V]M;6%N9',@87,@=&AE>2!A<F4@97AE8W5TG M960*("`M<R`]('-A9F5T>0H),2`](&5X:70@=VAE;B!S;VUE=&AI;F<@:7,@3 M;F]T('5N9&5R<W1O;V0*`````&@@("UO(#T@;W9E<G=R:71E"@DQ(#T@9&]NL M)W0@;W9E<G=R:71E(&5X:7-T:6YG(&9I;&5S"B`@9FEL96YA;64*"7)E860@Z M<VAA<B!F:6QE(&9R;VT@:&5R92`H;W(@<W1D:6X@:68@;6ES<VEN9RD*````M M``%&```%70`!`````7-H.B!I;&QE9V%L(&]P=&EO;B``<@!%<G)O<B`M(&-A` M;B=T(&]P96X@9FEL93H@`&5C:&\``&-A=`!)(&%M(&5X96-U=&EN9SH@("``) M`'-E9`!)(&%M(&5X96-U=&EN9SH@("```%=A<FYI;F<@+2T@=6YK;F]W;B!S, M960@;W!T:6]N"@``"DD@86T@=')E871I;F<@:70@87,@82`G8V%T)PH`97AIS M=```1&]N)W0@=6YD97)S=&%N9#H@```*26YT97)N86P@17)R;W(@+2T@=6YK[ M;F]W;B!S=&%T92$*``!%<G)O<B!I;B!I;F1I<F5C=&EO;B`M+2!I9VYO<F5DI M"@``/@!R`%=A<FYI;F<Z('=I;&P@;F]T(&]V97)W<FET93H@`&YI;#H``'<`H M/CX``&$`/#P````````"`/__````#@`.````````````````*BH@4W1A8VL@[ M3W9E<F9L;W<@*BH``/__````!``$`````````Q@```,$15A)5```__\````$L M``0````````#0@````!I;G1U:71I;VXN;&EB<F%R>0`````````-"@````"`F M`````YX```````````````````````````````````````````/`````````D M````````````````````````````````````````````````````````````` M``````````````````````"``&-O;CHQ,"\Q,"\S,C`O.#`O`"H`````````? M````````````````````````````*"HJ(%5S97(@06)O<G0@4F5Q=65S=&5DE M("HJ``#__P````X`#@````````08`````/__````!``$``````````````0TH M0T].5$E.544``/__````!``$````````!%P`````04)/4E0`__\````$``0`) M```````$>@````!I;G1U:71I;VXN;&EB<F%R>0``````````````````````$ M``````0````#[`````P````"```$C```!'(```18```$0````YX```-\```#* =5````SX```,Z```!O````;@```%"`````````_)88 `` end size 11144 ***EOF sh.uu*** exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.