1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1992-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* Glenn Fowler <gsf@research.att.com> *
1N/A* David Korn <dgk@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * David Korn
1N/A * AT&T Bell Laboratories
1N/A *
1N/A * output the beginning portion of one or more files
1N/A */
1N/A
1N/Astatic const char usage[] =
1N/A"[-n?\n@(#)$Id: head (AT&T Research) 2006-09-27 $\n]"
1N/AUSAGE_LICENSE
1N/A"[+NAME?head - output beginning portion of one or more files ]"
1N/A"[+DESCRIPTION?\bhead\b copies one or more input files to standard "
1N/A "output stopping at a designated point for each file or to the end of "
1N/A "the file whichever comes first. Copying ends at the point indicated by "
1N/A "the options. By default a header of the form \b==> \b\afilename\a\b "
1N/A "<==\b is output before all but the first file but this can be changed "
1N/A "with the \b-q\b and \b-v\b options.]"
1N/A"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bhead\b "
1N/A "copies from standard input starting at the current location.]"
1N/A"[+?The option argument for \b-c\b, and \b-s\b can optionally be "
1N/A "followed by one of the following characters to specify a different unit "
1N/A "other than a single byte:]"
1N/A "{"
1N/A "[+b?512 bytes.]"
1N/A "[+k?1-killobyte.]"
1N/A "[+m?1-megabyte.]"
1N/A "}"
1N/A"[+?For backwards compatibility, \b-\b\anumber\a is equivalent to \b-n\b "
1N/A "\anumber\a.]"
1N/A"[n:lines?Copy \alines\a lines from each file.]#[lines:=10]"
1N/A"[c:bytes?Copy \achars\a bytes from each file.]#[chars]"
1N/A"[q:quiet|silent?Never ouput filename headers.]"
1N/A"[s:skip?Skip \askip\a characters or lines from each file before "
1N/A "copying.]#[skip]"
1N/A"[v:verbose?Always ouput filename headers.]"
1N/A "\n\n"
1N/A"[ file ... ]"
1N/A "\n\n"
1N/A"[+EXIT STATUS?]"
1N/A "{"
1N/A "[+0?All files copied successfully.]"
1N/A "[+>0?One or more files did not copy.]"
1N/A "}"
1N/A"[+SEE ALSO?\bcat\b(1), \btail\b(1)]"
1N/A;
1N/A
1N/A#include <cmd.h>
1N/A
1N/Aint
1N/Ab_head(int argc, register char** argv, void* context)
1N/A{
1N/A static const char header_fmt[] = "\n==> %s <==\n";
1N/A
1N/A register Sfio_t* fp;
1N/A register char* cp;
1N/A register off_t keep = 10;
1N/A register off_t skip = 0;
1N/A register int delim = '\n';
1N/A int header = 1;
1N/A char* format = (char*)header_fmt+1;
1N/A
1N/A cmdinit(argc, argv, context, ERROR_CATALOG, 0);
1N/A for (;;)
1N/A {
1N/A switch (optget(argv, usage))
1N/A {
1N/A case 'c':
1N/A delim = -1;
1N/A /*FALLTHROUGH*/
1N/A case 'n':
1N/A if (opt_info.offset && argv[opt_info.index][opt_info.offset] == 'c')
1N/A {
1N/A delim = -1;
1N/A opt_info.offset++;
1N/A }
1N/A if ((keep = opt_info.number) <=0)
1N/A error(2, "%s: %I*d: positive numeric option argument expected", opt_info.name, sizeof(keep), keep);
1N/A continue;
1N/A case 'q':
1N/A header = argc;
1N/A continue;
1N/A case 'v':
1N/A header = 0;
1N/A continue;
1N/A case 's':
1N/A skip = opt_info.number;
1N/A continue;
1N/A case '?':
1N/A error(ERROR_usage(2), "%s", opt_info.arg);
1N/A continue;
1N/A case ':':
1N/A error(2, "%s", opt_info.arg);
1N/A continue;
1N/A }
1N/A break;
1N/A }
1N/A argv += opt_info.index;
1N/A argc -= opt_info.index;
1N/A if (error_info.errors)
1N/A error(ERROR_usage(2), "%s", optusage(NiL));
1N/A if (cp = *argv)
1N/A argv++;
1N/A do
1N/A {
1N/A if (!cp || streq(cp, "-"))
1N/A {
1N/A cp = "/dev/stdin";
1N/A fp = sfstdin;
1N/A sfset(fp, SF_SHARE, 1);
1N/A }
1N/A else if (!(fp = sfopen(NiL, cp, "r")))
1N/A {
1N/A error(ERROR_system(0), "%s: cannot open", cp);
1N/A continue;
1N/A }
1N/A if (argc > header)
1N/A sfprintf(sfstdout, format, cp);
1N/A format = (char*)header_fmt;
1N/A if (skip > 0)
1N/A sfmove(fp, NiL, skip, delim);
1N/A if (sfmove(fp, sfstdout, keep, delim) < 0 && errno != EPIPE)
1N/A error(ERROR_system(0), "%s: read error", cp);
1N/A if (fp != sfstdin)
1N/A sfclose(fp);
1N/A } while (cp = *argv++);
1N/A if (sfsync(sfstdout))
1N/A error(ERROR_system(0), "write error");
1N/A return error_info.errors != 0;
1N/A}