page@swan.ulowell.edu (Bob Page) (12/06/88)
Submitted-by: brant@uf.msc.umn.edu (Gary Brant) Posting-number: Volume 2, Issue 92 Archive-name: unix/tail.1 Tail now works with *real* pipes, will run with the default stack size of 4000 bytes and has no line limit. [uuencoded executable also enclosed; it's small. ..Bob] # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # readme # tail.doc # tail.uu # tail.c # alloc.c # makefile # This archive created: Mon Dec 5 18:04:37 1988 cat << \SHAR_EOF > readme This is a replacement for the tail which i submitted a few weeks ago. It fixes a few problems, notably it now works with *real* pipes, it will run with the default stack size of 4000 bytes, and the arbitrary maximum line limit of 4096 has been removed all with no decrease in performance. -Gary Brant The source & binary are freely distributable; you may do anything you like with them except sell them for profit as long as you leave my name in the source and include this notice with the source files. Have fun. Gary Brant US mail: 1355 Eustis St. #1 St. Paul, MN 55108 ARPA: brant@uc.msc.umn.edu SHAR_EOF cat << \SHAR_EOF > tail.doc TAIL USER COMMANDS TAIL NAME tail - display the last part of a file SYNOPSIS tail +|-number [ filename ...] DESCRIPTION tail copies filename to the standard output beginning at a designated place. If no file is named, the standard input is used. OPTIONS +number Begin copying at number lines from the beginning of the file. If number is not specified, the value 10 is used. -number Begin copying at number lines from the end of the file. If number is not specified, the value 10 is used. SEE ALSO head BUGS Data for a tail relative to the end of the file is stored in a buffer, and thus is limited to available memory. SHAR_EOF cat << \SHAR_EOF > tail.uu begin 777 tail M```#\P`````````#``````````(```4N````E0````$```/I```%+D[Z"4!." M5?_R0FW_^C`L@`)(P"M`__12;?_Z,"W_^K!M``AL``$4,"W_^DC`Y8`@;0`*` M(G`(``P1`"UF)#`M__I(P.6`(&T`"B\P"`!.N@+(6$\K0/_T.6W_]H`"8```# MUC`M__I(P.6`(&T`"B)P"``,$0`K9B8P+?_Z2,#E@"!M``HO,`@`3KH"CEA/> M1(`K0/_T.6W_]H`"8```FE)L@`1(>@#","W_^DC`Y8`@;0`*+S`(`$ZZ!@I0H M3RM`__QF.$AL@&Q(>@"@3KH$DE!/2&R`;#`M__I(P.6`(&T`"B\P"`!.N@1XW M4$](;(!L/SP`"DZZ#'Q<3V!`+RW_]#`M__I(P.6`(&T`"B\P"``O+?_\86A/> M[P`,.T#_^"\M__Q.N@RR6$]*;?_X9PH_+?_X3KH#;E1/8`#^X$IL@`1F&B\MC M__1(>@`T2&R`0&$N3^\`##\`3KH#2E1/0F=.N@-"5$].74YU<@!T86EL.B!C- M86XG="!O<&5N(````$Y5_!)(YP\P*"T`$$J$;&`@!%*$2H!L'"\M``@_/`/H0 M2&W\%DZZ`VA/[P`**T#\$F<"8-Q*K?P29S(O+0`,3KH!&%A/+RT`"#\\`^A(` M;?P63KH#/$_O``I*@&<02&R`5DAM_!9.N@-\4$]@V&```,J5RGX`+RT`"#\\D M`^A(;?P63KH##$_O``I*@&<``()(;?P63KH"Z%A/.T#__E*'OH1O#"P*)%(O- M!DZZ`=!83S`M__Y:0#\`3KH!/E1/*@!F*DAL@&Q(>@!V3KH#&%!/(`IG#BP*, M)%(O!DZZ`:!83V#N<!1,WPSP3EU.=2`*9@0D16`")H4F14AM_!8@15B(+PA.H MN@)J4$\@14*08`#_:"\M``QA1%A/(`IG'DAL@%8@2EB(+PA.N@*\4$\L"B12" M+P9.N@%(6$]@WG``8*9N;W0@96YO=6=H(&UE;6]R>2!F;W(@;&ES=`H`3E4`! M`$IL@`1G*DAL@%9(>@`H3KH"=E!/2&R`5B\M``A.N@)H4$](;(!62'H`$4ZZ" M`EI03TY=3G4]/3X@`"`\/3T*``!.50``2.<.`'@`>@%@,+P\`#!M'KP\`#EN6 M&'(*(`1.N@G2*``0!DB`D'P`,$C`V(!@"C`L@`)(P"@`8`Q212!M``@<,%``I M9L8@!$S?`'!.74YU3E4``$Y=3G5.50``2.<(,#`M``C0?``/YDCG0'(`,@`H5 M`29L@`8@"V820>R"!B9(*4B`!BE(@@9"K((*)%,@*@`$L(1E*B`J``2PA&8$] M)I)@#)FJ``35Z@`$)40`!"E+@`9"DB`*4(!,WPP03EU.=;7L@`9F#DZZ`((DA M0$J`9@1P`&#D)DHD4F"T8-Q.50``2.<`,"1M``A1BB9L@`:URV,$M=-E%+?3> M902URV(,M]-E!+73900F4V#D(&H`!-'*L=-F$"!3("@`!-&J``0@4R208`(D& MDR!K``31R['*9@P@*@`$T:L`!":28`(FBBE+@`9,WPP`3EU.=4Y5```O"D*GG M2'@0`$ZZ#\Q03R1`2H!F"'``)%].74YU0I(E?```$```!"!*4(@O"$ZZ_V!80 M3R`L@`9@WDY5__Q(YP`P)&R`!B`*9R8F4BMJ``3__$JM__QC$$*J``0O+?_\A M+PI.N@^:4$\D2[7L@`9FUC\M``A.N@T:5$],WPP`3EU.=2!O``0@"")O``@0J MV6;\3G4@;P`$(`A*&&;\D<`@"%.`3G5.50``2.<(("1M``A3;0`,2FT`#&\@] M+RT`#DZZ`&XX`+!\__]83V<.($I2BA"$N'P`"F<"8-9"$KA\__]F$+7M``AFA M"G``3-\$$$Y=3G4@+0`(8/).50``+PHD;0`(2A)G)"\M``P@2E**$!!(@#\`_ M3KH'LK!\__]<3V8(</\D7TY=3G5@V'``8/1.50``2.<(("1M``@O"DZZ`#(X> M`+!\__]83V<B,`1(P&`44Y((Z@`#``QP_TS?!!!.74YU8-9*@&?Z68!GY#`$% M8.I.50``+PHD;0`((%*QZ@`$90PO"F$66$\D7TY=3G4@4E*2$!!(@,!\`/]@B M[$Y5``!(YP@P)&T`"!`J``S`/``89PIP_TS?#!!.74YU"*H``@`,2JH`"&8(H M+PI.N@E`6$\0*@`,2(`(```'9S!![(!`)D@0*P`,2(#`?`"$L'P`A&8,/SS_K M_R\+3KH'^%Q/U_P````60>R!^+?(9=8_*@`0+RH`"!`J``U(@#\`3KH"/C@`< M2D!03VX42D1F!'`(8`)P$($J``QP_V``_WHP!$C`)*H`"-"J``@E0``$(%)2] MDA`02(#`?`#_8`#_6DY5```O"DZZ"'`D0$J`9@AP`"1?3EU.=2\*+RT`#"\M$ M``AA!D_O``Q@Z$Y5``!(YP@@+RT`$$ZZ!MI![(`*)$A83TH29A`Y?``%@@YPE M`$S?!!!.74YU($HB;0`,$!BP&68$2@!F]I`A2(!G!%R*8-(_*@`$+RT`"$ZZ( M`$`X`+!\__]<3V8$<`!@Q"!M`!`11``-(&T`$!%\``$`#"`M`!!@K$Y5```_, M+0`,/SP#`2\M``AA!E!/3EU.=4Y5``!(YP\P)&T`"$ZZ"A(F;((0>`!@#C`$< MP?P`!DJS"`!G#E)$N&R!^&WL>@9@``#$""T``0`,9S!(>/__+PI.N@O^+`!0* M3V<@+P9.N@PV+PI.N@O$2H!03V8.3KH+SCH`L'P`S68``(Q(>`/M+PI.N@O<@ M+`!*AE!/9F`(+0````QF!'H!8&Q(>`/N+PI.N@N^+`!03V8(3KH+DCH`8%1(B M>``A2'H`DDZZ#%XN`%!/9PHO!TZZ#`!83V`>2'@``4AZ`((O!DZZ"\A(>/__? M0J<O!DZZ"YY/[P`88"8P+0`,P'P%`+!\!0!F&"\&3KH+$GH$6$\Y18(.</],, MWPSP3EU.=3`$P?P`!B>&"``P!,'\``8@0-'+,6T`#``$""T``P`,9Q!(>``!2 M0J<O!DZZ"T1/[P`,,`1@PF1O<RYL:6)R87)Y````3E4``$CG#"`X+0`(3KH(Y MS#`$P?P`!B1`U>R"$$I$;0JX;('X;`1*DF80.7P``H(.</],WP0P3EU.=3`J[ M``3`?``#L'P``68*.7P`!8(.</]@X'``,"T`#B\`+RT`"B\23KH*O"H`L+S_M M____3^\`#&8,3KH*<CE`@@YP_V"T(`5@L&%P0^R"`D7L@@*UR68.,CP`%&L(> M=``BPE')__PI3X(4+'@`!"E.@AA(YX"`""X`!`$I9Q!+^@`(3J[_XF`&0J?SJ M7TYS0_H`($ZN_F@I0((<9@PN/``#@`=.KO^48`1.N@`:4$].=61O<RYL:6)R@ M87)Y`$GY``!__DYU3E4``"\*2'D``0``,"R!^,'\``8O`$ZZ"FPI0((04$]FQ M%$*G2'D``0``3KH*,%!/+FR"%$YU(&R"$$)H``0@;((0,7P``0`0(&R"$#%\& M``$`"B!L@A0@+((4D*@`!%"`*4""("!L@B`@O$U!3EA"ITZZ"B`D0$JJ`*Q8; M3V<N+RT`#"\M``@O"DZZ`*XY?``!@B0@;((0`&B````$(&R"$`!H@```"D_O3 M``Q@0DAJ`%Q.N@H^2&H`7$ZZ"@`I0((F(&R")DJH`"103V<0(&R")B)H`"0ON M$4ZZ"/)83R\L@B8O"DZZ^,@I;((F@BI03TZZ"/(@;((0((!.N@D@(&R"$"%`V M``9G%DAX`^U(>@`J3KH(_"!L@A`A0``,4$\O+((J/RR"+DZZ]2)"9TZZ!PQ0J M3R1?3EU.=2H`3E4``$CG##`D;0`0(&T`"$JH`*QG&"!M``@@*`"LY8`H`"!$% M("@`$.6`)D!@!"9L@?H0$TB`2,#0K0`,5(`Y0((P0J<P+((P2,`O`$ZZ"/XIT M0((R4$]F"$S?##!.74YU$!-(@#H`/P4@2U*(+P@O+((R3KH!?C`%2,`@0-'LK M@C)#^@%$$-EF_#\M``XO"B\L@C).N@$Z(&R",D(P4``Y?``!@BXP!4C`T*R"I M,B9`4HLD2T_O`!00$TB`.@"P?``@9QBZ?``)9Q*Z?``,9PRZ?``-9P:Z?``*# M9@12BV#8#!,`(&UZ#!,`(F8N4HL@2U*+$!!(@#H`9QX@2E**$(6Z?``B9A`,[ M$P`B9@12BV`&0BK__V`"8-9@."!+4HL0$$B`.@!G)KI\`"!G(+I\``EG&KI\& M``QG%+I\``UG#KI\``IG""!*4HH0A6#.($I2BD(02D5F`E.+4FR"+F``_UI"- M$D*G,"R"+E)`2,#E@"\`3KH'W"E`@BI03V8(0FR"+F``_MAZ`"9L@C)@)#`%/ M2,#E@"!L@BHABP@`($L@"$H89OR1P%.(,`A20$C`U\!21;IL@BYMUC`%2,#E7 M@"!L@BI"L`@`8`#^E"``,#Q__V`$,"\`#"!O``1*&&;\4T@B;P`(4T`0V5?(C M__QG`D(0("\`!$YU3.\#```$(`@R+P`,8`(0V5?)__QG!E)!8`)"&%')__Q.H M=4CG<``T`<3`)@%(0\;`2$-"0]2#2$#`P4A`0D#0@DS?``Y.=4Y5```O!#@M( M``@O+0`*/P1.N@`PN'P`"EQ/9B0@;0`*$"@`#$B`"```!V<4/SS__R\M``I.V MN@#T7$\H'TY=3G5@^$Y5```O"B1M``H@4K'J``1E&#`M``C`?`#_/P`O"DZZ+ M`,A<3R1?3EU.=2!24I(0+0`)$(!(@,!\`/]@Z$Y5```O"D'L@$`D2"!*U?P`+ M```6+PAA$%A/0>R!^+7(9>HD7TY=3G5.50``2.<(("1M``AX`"`*9@IP_TS?' M!!!.74YU2BH`#&=0""H``@`,9PP_//__+PIA4C@`7$\0*@`-2(`_`$ZZ!1R(S M0`@J``$`#%1/9PHO*@`(3KH"+EA/""H`!0`,9Q(O*@`23KH"P"\J`!).N@(4- M4$]"DD*J``1"J@`(0BH`##`$8)!.5?_^2.<(("1M``A!^O]&*4B"-@@J``0`B M#&<*</],WP003EU.=0@J``(`#&<P(%*1Z@`(.`@_!"\J``@0*@`-2(`_`$ZZ? M`H"P1%!/9Q`(Z@`$``Q"DD*J``1P_V#`#&W__P`,9A`(J@`"``Q"DD*J``1P. M`&"H2JH`"&8(+PI.N@":6$\,:@`!`!!F*AMM``W__S\\``%(;?__$"H`#4B`< M/P!.N@(BL'P``5!/9J`P+0`,8`#_:B2J``@P*@`02,#0J@`()4``!`CJ``(`6 M#"!24I(0+0`-$(!(@,!\`/]@`/\^3E4``"\*0>R`0"1(2BH`#&<8U?P````6W M0>R!^+7(90AP`"1?3EU.=6#B0I)"J@`$0JH`""`*8.I.5?_\+PHD;0`(/SP$. M`$ZZ`,`K0/_\5$]F\``$`$"!*T?P````.)4@`""1?3EU.=35\!```$`CJS M``$`#"5M__P`"!`J``U(@#\`3KH`XDI`5$]G!@`J`(``#&#.3E4``$CG`#`D^ M;(("8!0F4B`J``10@"\`+PI.N@1\4$\D2R`*9NA"K(("3-\,`$Y=3G5.50``J M+PI!^O_&*4B".D*G("T`"%"`+P!.N@0F)$!*@%!/9@AP`"1?3EU.=22L@@(EJ M;0`(``0I2H("(`I0@&#F3E4``'``,"T`""\`8;)83TY=3G5.50``2.<`,)?+C M)&R"`F`.(&T`"%&(L<IG$B9*)%(@"F;N</],WPP`3EU.=2`+9P0FDF`$*5*"+ M`B`J``10@"\`+PI.N@/.<`!03V#83E4``"\*,"T`",'\``8D0-7L@A!*;0`(B M;0XP+0`(L&R!^&P$2I)F#CE\``*"#G#_)%].74YU,"T`",'\``8@;((0+S`() M`$ZZ`L9*@%A/9P1P`6`"<`!@V$Y5```O+0`(3KH"D$J`6$]F#DZZ`IHY0((.: M</].74YU<`!@^$Y5``!(YPP@."T`"$ZZ`'`P!,'\``8D0-7L@A!*1&T*N&R!@ M^&P$2I)F$#E\``*"#G#_3-\$,$Y=3G4P*@`$P'P``V8*.7P`!8(.</]@Y'``W M,"T`#B\`+RT`"B\23KH"D"H`L+S_____3^\`#&8,3KH"&CE`@@YP_V"X(`5@B MM$Y5__Q(>!``0J=.N@+X*T#__`@```Q03V<22FR")&8(("W__$Y=3G5.N@`&M M<`!@]$Y5``!(>``$2'H`'$ZZ`?XO`$ZZ`BP_/``!3KH`#D_O``Y.74YU7D,*L M`$Y5``!*K((V9P8@;((V3I`_+0`(3KH`"%1/3EU.=4Y5__PO!#`M``A(P"M`> M__Q*K((09RAX`&`*/P1.N@#^5$]21+AL@?AM\#`L@?C!_``&+P`O+((03KH"N M&E!/2JR".F<&(&R".DZ02JR!_F<*+RR!_DZZ`9)83TJL@CYG""!L@CX@K()"! M2JR"1F<*+RR"1DZZ`:I83TJL@DIG"B\L@DI.N@&:6$]*K().9PHO+().3KH![ MBEA/2JR"4F<*+RR"4DZZ`7I83RQX``0(+@`$`2EG%"\-2_H`"DZN_^(J7V`&C M0J?S7TYS2JR")F8P2JR",F<H,"R",$C`+P`O+((R3KH!<C`L@BY20$C`Y8`OR M`"\L@BI.N@%>3^\`$&`.3KH!2"\L@B9.N@%X6$\@+?_\+FR"%$YU*!].74YU6 M3E4``$CG#B`X+0`(,`3!_``&)$#5[((02D1M"KAL@?AL!$J29A`Y?``"@@YPV M_TS?!'!.74YU""H`!P`$9@@O$DZZ``I83T*2<`!@XB(O``0L;((<3N[_W"(OJ M``0L;((<3N[_@B(O``0L;((<3N[_N"QL@AQ.[O_*+&R"'$[N_WPB+P`$+&R", M'$[N_RA,[P`&``0L;((<3N[_K$SO``8`!"QL@AQ.[O_B+&R"'$[N_\1,[P`.W M``0L;((<3N[_UDSO``X`!"QL@AQ.[O^^3OH``B(O``0L;((<3N[_IDSO``X`& M!"QL@AQ.[O_02.<!!$SO((``#"QL@AA.KO^43-\@@$YU(F\`!"QL@AA.[OYB2 M3OH``DSO``,`!"QL@AA.[O\Z(F\`!"QL@AA.[O[:+&R"&$[N_WQ.^@`"(F\`2 M!"`O``@L;((83N[_+B!O``0L;((83N[^C"QL@A@B;P`$("\`"$[N_=@B;P`$% M+&R"&$[N_H9,[P`#``0L;((83N[^SB!O``0L;((83N[^@````^P````!````= M`0``";8````````#\@```^H```"```H```````!R``````!R*P````)W````T M`P%W*P```P)A````"0%A*P``"0)X````!0%X*P``!0(`````````````````5 M```````!``````$``````````````````````0$````!````````````````% M``````$"`````0``````````````````````````````````````````````$ M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M````````````````````````````````````````````````````````````` M```````````````````````````````````````4``````````````/R```#, )ZP````$```/RA `` end size 5904 SHAR_EOF cat << \SHAR_EOF > tail.c /* tail.c - print the last few lines in a file. If count is specified, * * that many lines are printed instead of the default value of * * ten lines. If no files are specified, head reads standard * * input. * * * * tail [-<count>] [<file> ...] * * * * tail (C) 1988 by Gary L. Brant * * * * :ts=8 */ #include <stdio.h> #define MAXLINE 1000 void fputs (); int default_lines = 10; /* default number of lines to list */ int headlin = 0; typedef struct list { struct list *nxt; char line[MAXLINE]; }; main (argc, argv) /* list 1st n lines of a file */ int argc; char *argv[]; { FILE *input, *fopen (); void fclose (); int i = 0, rval; long maxlines, convert (); char ch; maxlines = default_lines; while (++i < argc) { if (argv [i][0] == '-') { /* process line count argument */ maxlines = convert (argv[i]); default_lines = maxlines; } else if (argv [i][0] == '+') { maxlines = -convert (argv[i]); default_lines = maxlines; } else { ++headlin; if ((input = fopen (argv[i], "r")) == NULL) { fputs ("tail: can't open ", stderr); fputs (argv[i], stderr); putc ('\n', stderr); break; } else { rval = list (input, argv[i], maxlines); fclose (input); if (rval) quit (rval); } } } if (!headlin) quit (list (stdin, "", maxlines)); quit (0); } list (fp, fn, maxlines) /* list tail of a file */ FILE *fp; char *fn; register long maxlines; { int n; char line[MAXLINE]; char *c, *fgets (), *alloc (); if (maxlines < 0) { /* +n, head relative list */ while (maxlines++ < 0 && (c = fgets (line, MAXLINE, fp)) != NULL); if (c != NULL) { heading (fn); while ((fgets (line, MAXLINE, fp)) != NULL) fputs (line, stdout); } } else { /* -n, tail relative list */ register struct list *head = NULL, *curr, *next, *p; register long nlin = 0; while ((fgets (line, MAXLINE, fp)) != NULL) { n = strlen (line); if (++nlin > maxlines) { /* de-link 1st line */ p = head; head = head->nxt; freeit (p); } if ((next = (struct list *) alloc (n+5)) == NULL) { fputs ("not enough memory for list\n", stderr); while (head != NULL) { p = head; head = head->nxt; freeit (p); } return (20); } if (head == NULL) head = next; else curr->nxt = next; curr = next; strcpy (next->line, line); next->nxt = NULL; } heading (fn); /* now print the lines in the list, deallocating as we go */ while (head != NULL) { fputs (head->line, stdout); p = head; head = head->nxt; freeit (p); } } return (0); } heading (filename) char *filename; { if (headlin) { fputs ("==> ", stdout); fputs (filename, stdout); fputs (" <==\n", stdout); } } long convert (string) char string[]; { register long maxlines = 0; register int j; register char ch; for (j = 1; (ch = string[j]) != '\0'; j++) if (ch >= '0' && ch <= '9') { maxlines *= 10; maxlines += ch - '0'; } else { maxlines = default_lines; break; } return (maxlines); } void _wb_parse () { } SHAR_EOF cat << \SHAR_EOF > alloc.c /* alloc.c - memory allocator * * The point of this is that it is about 4 times faster than MANX malloc/free * in c.lib. Malloc in heapmem.o will not allocate a second heap if the first * is exhausted. * :ts=8 */ #define NULL 0L #define HOWMUCH 4096L /* how much memory to AllocMem() at a time */ typedef struct header { struct header *next; /* next block */ unsigned long size; /* block size */ }; struct header first; struct header *head = NULL; /* start of list */ char *alloc (bytes) unsigned bytes; { struct header *getmem (); register struct header *p, *q; register long size; size = (((bytes + 2 * sizeof (struct header) - 1) >> 3) << 3); if ((q = head) == NULL) { first.next = head = q = &first; first.size = 0L; } for (p = q->next; ; q = p, p = p->next) { if (p->size >= size) { /* if this block is large enough */ if (p->size == size) q ->next = p->next; else { /* remove memory from tail of block */ p->size -= size; p = (struct header *) ((char *) p + p->size); p->size = size; } head = q; p->next = NULL; return ((char *) (p+1)); } if (p == head) /* back where we started */ if ((p = getmem ()) == NULL) return (NULL); /* cannot allocate memory */ } } /* freeit - put block back in free list */ freeit (ptr) char *ptr; { register struct header *p, *q; p = (struct header *) ptr - 1; for (q = head; ; q = q->next) { if (p > q && p < q->next) break; /* new block goes between q & q->next */ if (q >= q->next && p > q) break; /* new block goes at end of list */ if (q >= q->next && p < q->next) break; /* new block goes at beginning of list */ } if ((struct header *) ((char *) p + p->size) == q->next) { p->size += q->next->size; p->next = q->next->next; } else { p->next = q->next; } if ((struct header *) ((char *) q + q->size) == p) { q->size += p->size; q->next = p->next; } else { q->next = p; } head = q; } /* getmem - request more memory from system */ struct header *getmem () { char *AllocMem (); register struct header *up; if ((up = (struct header *) AllocMem (HOWMUCH, 0L)) == NULL) return (NULL); /* can't get more memory */ up->next = NULL; up->size = HOWMUCH; freeit ((char *) (up + 1)); return (head); } quit (code) int code; { register struct header *p, *q; unsigned long size; p = head; do { if (p == NULL) break; q = p->next; if ((size = p->size) > 0L) { p->size = 0L; FreeMem (p, size); } p = q; } while (p != head); exit (code); } SHAR_EOF cat << \SHAR_EOF > makefile CFLAGS=-s tail: tail.o alloc.o ln tail.o alloc.o -lc SHAR_EOF # End of shell archive exit 0 -- Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page Have five nice days.