1/*********************************************************************** 2* * 3* This software is part of the ast package * 4* Copyright (c) 1992-2011 AT&T Intellectual Property * 5* and is licensed under the * 6* Common Public License, Version 1.0 * 7* by AT&T Intellectual Property * 8* * 9* A copy of the License is available at * 10* http://www.opensource.org/licenses/cpl1.0.txt * 11* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12* * 13* Information and Software Systems Research * 14* AT&T Research * 15* Florham Park NJ * 16* * 17* Glenn Fowler <gsf@research.att.com> * 18* David Korn <dgk@research.att.com> * 19* * 20***********************************************************************/ 21#pragma prototyped 22/* 23 * David Korn 24 * AT&T Bell Laboratories 25 * 26 * output the beginning portion of one or more files 27 */ 28 29static const char usage[] = 30"[-n?\n@(#)$Id: head (AT&T Research) 2006-09-27 $\n]" 31USAGE_LICENSE 32"[+NAME?head - output beginning portion of one or more files ]" 33"[+DESCRIPTION?\bhead\b copies one or more input files to standard " 34 "output stopping at a designated point for each file or to the end of " 35 "the file whichever comes first. Copying ends at the point indicated by " 36 "the options. By default a header of the form \b==> \b\afilename\a\b " 37 "<==\b is output before all but the first file but this can be changed " 38 "with the \b-q\b and \b-v\b options.]" 39"[+?If no \afile\a is given, or if the \afile\a is \b-\b, \bhead\b " 40 "copies from standard input starting at the current location.]" 41"[+?The option argument for \b-c\b, and \b-s\b can optionally be " 42 "followed by one of the following characters to specify a different unit " 43 "other than a single byte:]" 44 "{" 45 "[+b?512 bytes.]" 46 "[+k?1-killobyte.]" 47 "[+m?1-megabyte.]" 48 "}" 49"[+?For backwards compatibility, \b-\b\anumber\a is equivalent to \b-n\b " 50 "\anumber\a.]" 51"[n:lines?Copy \alines\a lines from each file.]#[lines:=10]" 52"[c:bytes?Copy \achars\a bytes from each file.]#[chars]" 53"[q:quiet|silent?Never ouput filename headers.]" 54"[s:skip?Skip \askip\a characters or lines from each file before " 55 "copying.]#[skip]" 56"[v:verbose?Always ouput filename headers.]" 57 "\n\n" 58"[ file ... ]" 59 "\n\n" 60"[+EXIT STATUS?]" 61 "{" 62 "[+0?All files copied successfully.]" 63 "[+>0?One or more files did not copy.]" 64 "}" 65"[+SEE ALSO?\bcat\b(1), \btail\b(1)]" 66; 67 68#include <cmd.h> 69 70int 71b_head(int argc, register char** argv, void* context) 72{ 73 static const char header_fmt[] = "\n==> %s <==\n"; 74 75 register Sfio_t* fp; 76 register char* cp; 77 register off_t keep = 10; 78 register off_t skip = 0; 79 register int delim = '\n'; 80 int header = 1; 81 char* format = (char*)header_fmt+1; 82 83 cmdinit(argc, argv, context, ERROR_CATALOG, 0); 84 for (;;) 85 { 86 switch (optget(argv, usage)) 87 { 88 case 'c': 89 delim = -1; 90 /*FALLTHROUGH*/ 91 case 'n': 92 if (opt_info.offset && argv[opt_info.index][opt_info.offset] == 'c') 93 { 94 delim = -1; 95 opt_info.offset++; 96 } 97 if ((keep = opt_info.number) <=0) 98 error(2, "%s: %I*d: positive numeric option argument expected", opt_info.name, sizeof(keep), keep); 99 continue; 100 case 'q': 101 header = argc; 102 continue; 103 case 'v': 104 header = 0; 105 continue; 106 case 's': 107 skip = opt_info.number; 108 continue; 109 case '?': 110 error(ERROR_usage(2), "%s", opt_info.arg); 111 continue; 112 case ':': 113 error(2, "%s", opt_info.arg); 114 continue; 115 } 116 break; 117 } 118 argv += opt_info.index; 119 argc -= opt_info.index; 120 if (error_info.errors) 121 error(ERROR_usage(2), "%s", optusage(NiL)); 122 if (cp = *argv) 123 argv++; 124 do 125 { 126 if (!cp || streq(cp, "-")) 127 { 128 cp = "/dev/stdin"; 129 fp = sfstdin; 130 sfset(fp, SF_SHARE, 1); 131 } 132 else if (!(fp = sfopen(NiL, cp, "r"))) 133 { 134 error(ERROR_system(0), "%s: cannot open", cp); 135 continue; 136 } 137 if (argc > header) 138 sfprintf(sfstdout, format, cp); 139 format = (char*)header_fmt; 140 if (skip > 0) 141 sfmove(fp, NiL, skip, delim); 142 if (sfmove(fp, sfstdout, keep, delim) < 0 && errno != EPIPE) 143 error(ERROR_system(0), "%s: read error", cp); 144 if (fp != sfstdin) 145 sfclose(fp); 146 } while (cp = *argv++); 147 if (sfsync(sfstdout)) 148 error(ERROR_system(0), "write error"); 149 return error_info.errors != 0; 150} 151