procedure to process files like classic UNIX filter
Gary Perlman
perlman at wanginst.UUCP
Wed Aug 28 09:51:27 AEST 1985
I have found the following procedure useful for creating
programs that filter files (like cat, sed, and nroff). It
checks for file accessability, allows for - as the standard
input, and prints appropriate error messages before
returning a success status. The only trick (if you can call
it that) involved is to pass it a function of the form:
process (file, ioptr)
that itself returns a success status. The procedure
cooperates nicely with getopt, although getopt's use is not
required.
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create the files:
# filter.3
# filter.c
# This archive created: Tue Aug 27 19:45:55 1985
# By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
export PATH; PATH=/bin:/usr/bin:$PATH
echo shar: "extracting 'filter.3'" '(2479 characters)'
if test -f 'filter.3'
then
echo shar: "will not over-write existing file 'filter.3'"
else
sed 's/^ X//' << \SHAR_EOF > 'filter.3'
X.TH GETOPT 3WI "August 12, 1985" "Wang Institute" "UNIX Programmer's Manual"
X.SH NAME
Xfilter \- filter program operand files in classic UNIX style
X.SH SYNOPSIS
X.ft B
X.nf
X.ta .5i 2i
X#include <stdio.h>
X ...
Xint filter (argc, argv, optind, func)
Xint argc; /* command line argument count */
Xchar **argv; /* command line argument strings */
Xint optind; /* index of first command line operand */
Xint (*func) (); /* processing function */
X ...
Xint func (file, ioptr)
Xchar *file; /* name of file to be read */
XFILE *ioptr; /* opened file pointer */
X.fi
X.ft
X.SH DESCRIPTION
X.I filter
Xsimplies writing C programs that read all their command
Xline operands (those after options) as files.
XIn the classic style of programs like
X.I cat,
X.I nroff,
Xor
X.I sed,
X.I filter
Xtakes each of its operand files, opens it,
Xand passes the name and opened
X.I ioptr
Xto the programmer-suppled
X.I func
Xthat is free to do what it likes with the file.
XAfter each time
X.I func
Xreturns, the
X.I ioptr
Xis closed (except for the standard input).
XAs is conventional,
Xa single minus sign,
X.B -,
Xis the standard input.
XIf no operands are passed to filter,
Xie,
X.I argc==optind,
Xthen the standard input is read.
X.SH DIAGNOSTICS
X.I filter
Xprints error messages on
X.I stderr
Xand returns non-zero status on failure.
XIf a file cannot be opened, or if the standard input
Xis read more than once,
Xthen no files are filtered.
XIf the processing
X.I func
Xfails, processing continues,
Xbut the return status will be the sum of the
Xbad return statuses from
X.I func.
X.SH EXAMPLE
XThe following example shows how
X.I filter
Xcan be used with an initializing routine that returns
Xthe
X.I optind
Xvalue from
X.I getopt.
X(It is not necessary that
X.I getopt
Xbe used.)
X.nf
X.ta .5i +.5i +.5i +.5i +.5i +.5i +.5i
X.sp
X.ne 15v
Xmain (argc, argv) char **argv;
X {
X int process ();
X int C;
X int status = 0;
X while ((C = getopt (argc, argv, "ax:")) != EOF)
X switch (C)
X {
X case 'a': Aopt = 1; break;
X case 'x': Xopt = optarg; break;
X default: status++; break;
X }
X status += (filter (argc, argv, optind, process) != 0);
X exit (status);
X }
X.sp
X.fi
X.PP
XWith the above processing filter,
Xthe following documentation should be included in the
Xmanual entry:
X.nf
X.sp
X.ta .5i
X.ne 5v
X .I process
X reads its input from the named files,
X or if none are supplied, the standard input is read.
X A solitary minus sign as a program argument can be
X used to read the standard input along with named files.
X.sp
X.fi
X.SH SEE ALSO
Xgetopt (3)
X.SH AUTHOR
XGary Perlman
SHAR_EOF
if test 2479 -ne "`wc -c < 'filter.3'`"
then
echo shar: "error transmitting 'filter.3'" '(should have been 2479 characters)'
fi
fi
echo shar: "extracting 'filter.c'" '(3261 characters)'
if test -f 'filter.c'
then
echo shar: "will not over-write existing file 'filter.c'"
else
sed 's/^ X//' << \SHAR_EOF > 'filter.c'
X/*
X Function: filter "Filter Command Line Files In Classic UNIX Style"
X Created: Sat Aug 10 21:57:12 EDT 1985
X By: Gary Perlman (Wang Institute, Tyngsboro, MA 01879 USA)
X Compilation: nothing unusual
X Tester: $Compile: cc -DSTANDALONE -o catfilter %f
X ---------------------------------------------------------------
X Preconditions:
X The index of the first file operand has been determined.
X Postconditions:
X All files have been opened, processed, and closed.
X Returns:
X The return status (non-zero is bad) depends on the accessibility
X of files, the ability to open them, and the return statuses of
X the called function.
X Exceptions:
X If any file cannot be accessed, then none will be processed.
X During processing, if something goes wrong (a file that could
X be accessed cannot be opened, or the file processor returns a
X non-zero status), processing continues.
X Global Data Used:
X None
X Global Data Modified:
X None
X Notes:
X "-" is the conventional name for the standard input.
X It can only be read once.
X Fputs and putc are used to print error messages to avoid
X loading just because filter used it.
X*/
X
X#include <stdio.h>
X#define isstdin(file) (file[0] == '-' && file[1] == '\0')
X/* LINTLIBRARY */
Xint
Xfilter (argc, argv, curarg, process)
Xint argc; /* real number of command line args */
Xchar **argv; /* command line argument pointer */
Xint curarg; /* first argv to filter */
Xint (*process) (); /* status process (char *name, FILE *ioptr) */
X {
X int status = 0; /* return status of this function */
X int arg; /* loop index variable */
X char *file; /* name of the current file */
X char *pgm = argv[0]; /* name of the program */
X FILE *ioptr; /* file pointer for opening */
X int countstdin = 0; /* number of times stdin is processed */
X if (curarg == argc)
X status += ((*process) ("-", stdin));
X else
X {
X /* first check to make sure all files can be opened to read */
X for (arg = curarg; arg < argc; arg++)
X {
X file = argv[arg];
X if (isstdin (file))
X countstdin++;
X else if (access (file, 4))
X {
X fputs (pgm, stderr);
X fputs (": Can't read '", stderr);
X fputs (file, stderr);
X putc ('\'', stderr);
X putc ('\n', stderr);
X status++;
X }
X }
X if (countstdin > 1)
X {
X fputs (pgm, stderr);
X fputs (": Can only read standard input once\n", stderr);
X status++;
X }
X if (status == 0)
X for (arg = curarg; arg < argc; arg++)
X {
X file = argv[arg];
X if (isstdin (file))
X status += ((*process) (file, stdin) != 0);
X else if (ioptr = fopen (file, "r"))
X {
X status += ((*process) (file, ioptr) != 0);
X (void) fclose (ioptr);
X }
X else
X {
X fputs (pgm, stderr);
X fputs (": Can't open '", stderr);
X fputs (file, stderr);
X putc ('\'', stderr);
X putc ('\n', stderr);
X status++;
X }
X }
X }
X return (status);
X }
X
X#ifdef STANDALONE
X
Xint
Xcat (file, ioptr)
Xchar *file;
Xregister FILE *ioptr;
X {
X register int C;
X while ((C = getc (ioptr)) != EOF)
X putchar (C);
X return (0);
X }
X
Xmain (argc, argv) char **argv;
X {
X int cat ();
X if (filter (argc, argv, 1, cat))
X putc ('\007', stderr); /* UNIX friendly error message */
X }
X
X#endif STANDALONE
SHAR_EOF
if test 3261 -ne "`wc -c < 'filter.c'`"
then
echo shar: "error transmitting 'filter.c'" '(should have been 3261 characters)'
fi
fi
exit 0
# End of shell archive
--
Gary Perlman Wang Institute Tyngsboro, MA 01879 (617) 649-9731
UUCP: decvax!wanginst!perlman CSNET: perlman at wanginst
More information about the Comp.sources.unix
mailing list