/*- * Copyright (C) 2007 * Terry *. P*****. All rights reserved. * * permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ // vim: set noexpandtab ts=8 sw=4 ai : // vi: set ai nu ts=8 sw=4 : #include <err.h> #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <unistd.h> struct lnpos { long nl; struct lnpos *next; }; static void readall( FILE *, int ); static void readtop( FILE *, int ); static void readbottom( FILE *, int ); static void usage( void ); /* * rf - read file to standard out v1.1 */ int main( int argc, char *argv[] ) { char *erptr; int t_flag = 0, b_flag = 0; int ch, lncnt; FILE *fp; extern char *optarg; extern int optind; extern int optopt; extern int opterr; extern int optreset; while ( (ch = getopt(argc, argv, "b:t:")) != -1 ) { switch (ch) { case 'b': b_flag++; lncnt = strtol(optarg, &erptr, 10); if ( *erptr || lncnt <= 0 ) errx( 1, "Improper line count -- %s", optarg ); break; case 't': t_flag++; lncnt = strtol(optarg, &erptr, 10); if ( *erptr || lncnt <= 0 ) errx( 1, "Improper line count -- %s", optarg ); break; case '?': default: usage(); return 1; } } if ( (t_flag < 1) && (b_flag < 1) ) { fp = fopen( argv[1], "r" ); if ( fp == NULL ) errx( 1, "File can not be opened or" " does not exist -- %s\n", argv[1] ); readall( fp, lncnt ); } else if ( t_flag > 0 ) { fp = fopen( argv[3], "r" ); if ( fp == NULL ) errx( 1, "File can not be opened or" " does not exist -- %s\n", argv[3] ); readtop( fp, lncnt ); } else if ( b_flag > 0 ) { fp = fopen( argv[3], "r" ); if ( fp == NULL ) errx( 1, "File can not be opened or" " does not exist -- %s\n", argv[3] ); readbottom( fp, lncnt ); } else { usage(); /* NOTREACHED */ } fclose( fp ); return 0; } /* * print out an open file to standard output */ static void readall( FILE *fp, int lncnt ) { while ( (lncnt = fgetc( fp )) != EOF ) { printf( "%c", lncnt ); } } /* Read n lines from the top of the file. * note that it was very inspired by the head(1) implementation of BSD */ static void readtop( FILE *fp, int lncnt ) { char *cp; size_t error, rlen; while ( lncnt && (cp = fgetln( fp, &rlen )) != NULL ) { error = fwrite( cp, sizeof(char), rlen, stdout ); if ( error != rlen ) err( 1, "stdout" ); lncnt--; } } /* Read n lines from the bottom of the file */ static void readbottom( FILE *fp, int lncnt ) { int hmany = lncnt; long nlnum = 0; long where; struct lnpos *root; struct lnpos *cur; root = malloc( sizeof(struct lnpos) ); if ( root == NULL ) err( 1, "can't init the list" ); root->next = 0; cur = root; cur->next = malloc( sizeof(struct lnpos) ); if ( cur->next == NULL ) err( 1, "can't add nodes" ); cur = cur->next; /* read the file, count every '\n' and store them in a new member of * our linked list. */ while ( (lncnt = fgetc( fp )) != EOF ) { if ( lncnt == '\n' ) { nlnum++; cur->nl = ftell( fp ); if ( cur->next != NULL ) cur = cur->next; cur->next = malloc( sizeof(struct lnpos) ); if ( cur->next == NULL ) err( 1, "can't add nodes" ); cur = cur->next; } } /* rewind our linked-list and seek to b_flag + 1 segments short of the * end of the list _before_ calling readall. So readall _starts_ from * the correct fseek offset to print till EOF. */ cur = root->next; hmany++; while ( hmany < nlnum ) { cur = cur->next; nlnum--; } where = fseek( fp, cur->nl, SEEK_SET ); if ( where != 0 ) err( 1, "could not seek through the file\n" ); readall( fp, lncnt ); } static void usage( void ) { fprintf( stderr, "usage:\n rf file\n " "rf [-t number lines from the top] file\n " "rf [ -b number of lines from the bottom ] [ file ]\n" ); }
And the manual which writing got me interested in roff, I'll post when I have time to learn more about it. Basically the problem I had was caused by working on it. Originally under the conditions when 2 + 2 = 5 which is not good, because 2 + 2 is really == 4 !!!! I should never do stuff when I'm like that, but if I don't try nothing gets done.
No comments:
Post a Comment