2 * pg - A clone of the System V CRT paging utility.
4 * Copyright (c) 2000-2001 Gunnar Ritter. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * 4. Neither the name of Gunnar Ritter nor the names of his contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY GUNNAR RITTER AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL GUNNAR RITTER OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 /* Sccsid @(#)pg.c 1.44 (gritter) 2/8/02 - modified for util-linux */
34 #include <sys/types.h>
38 #include <sys/ioctl.h>
40 #include <sys/termios.h>
56 #elif defined(HAVE_NCURSES_NCURSES_H)
57 #include <ncurses/ncurses.h>
65 #define READBUF LINE_MAX /* size of input buffer */
66 #define CMDBUF 255 /* size of command buffer */
67 #define TABSIZE 8 /* spaces consumed by tab character */
70 * Avoid the message "`var' might be clobbered by `longjmp' or `vfork'"
72 #define CLOBBGRD(a) (void)(&(a));
74 #define cuc(c) ((c) & 0377)
76 enum { FORWARD = 1, BACKWARD = 2 }; /* search direction */
77 enum { TOP, MIDDLE, BOTTOM }; /* position of matching line */
80 * States for syntax-aware command line editor.
101 char pattern[CMDBUF];
106 * Position of file arguments on argv[] to main()
114 void (*oldint)(int); /* old SIGINT handler */
115 void (*oldquit)(int); /* old SIGQUIT handler */
116 void (*oldterm)(int); /* old SIGTERM handler */
117 char *tty; /* result of ttyname(1) */
118 char *progname; /* program name */
119 unsigned ontty; /* whether running on tty device */
120 unsigned exitstatus; /* exit status */
121 int pagelen = 23; /* lines on a single screen page */
122 int ttycols = 79; /* screen columns (starting at 0) */
123 struct termios otio; /* old termios settings */
124 int tinfostat = -1; /* terminfo routines initialized */
125 int searchdisplay = TOP; /* matching line position */
126 regex_t re; /* regular expression to search for */
127 int remembered; /* have a remembered search string */
128 int cflag; /* clear screen before each page */
129 int eflag; /* suppress (EOF) */
130 int fflag; /* do not split lines */
131 int nflag; /* no newline for commands required */
132 int rflag; /* "restricted" pg */
133 int sflag; /* use standout mode */
134 char *pstring = ":"; /* prompt string */
135 char *searchfor; /* search pattern from argv[] */
136 int havepagelen; /* page length is manually defined */
137 long startline; /* start line from argv[] */
138 int nextfile = 1; /* files to advance */
139 jmp_buf jmpenv; /* jump from signal handlers */
140 int canjump; /* jmpenv is valid */
141 wchar_t wbuf[READBUF]; /* used in several widechar routines */
143 const char *copyright =
144 "@(#)pg 1.44 2/8/02. Copyright (c) 2000-2001 Gunnar Ritter. ";
145 const char *helpscreen = N_("All rights reserved.\n\
146 -------------------------------------------------------\n\
148 q or Q quit program\n\
149 <newline> next page\n\
150 f skip a page forward\n\
151 d or ^D next halfpage\n\
154 /regex/ search forward for regex\n\
155 ?regex? or ^regex^ search backward for regex\n\
156 . or ^L redraw screen\n\
157 w or z set page size and go to next page\n\
158 s filename save current file to filename\n\
159 !command shell escape\n\
160 p go to previous file\n\
163 Many commands accept preceding numbers, for example:\n\
164 +1<newline> (next page); -1<newline> (previous page); 1<newline> (first page).\n\
166 See pg(1) for more information.\n\
167 -------------------------------------------------------\n");
170 static int fseeko(FILE *f, off_t off, int whence) {
171 return fseek(f, (long) off, whence);
173 static off_t ftello(FILE *f) {
174 return (off_t) ftell(f);
178 #ifdef USE_SIGSET /* never defined */
179 /* sigset and sigrelse are obsolete - use when POSIX stuff is unavailable */
180 #define my_sigset sigset
181 #define my_sigrelse sigrelse
183 static int my_sigrelse(int sig) {
186 if (sigemptyset(&sigs) || sigaddset(&sigs, sig))
188 return sigprocmask(SIG_UNBLOCK, &sigs, NULL);
190 typedef void (*my_sighandler_t)(int);
191 static my_sighandler_t my_sigset(int sig, my_sighandler_t disp) {
192 struct sigaction act, oact;
194 act.sa_handler = disp;
195 if (sigemptyset(&act.sa_mask))
198 if (sigaction(sig, &act, &oact))
200 if (my_sigrelse(sig))
202 return oact.sa_handler;
212 exit(status < 0100 ? status : 077);
216 * Memory allocator including check.
221 char *m = (char *)malloc(s);
223 const char *p = _("Out of memory\n");
224 write(2, p, strlen(p));
231 * Usage message and similar routines.
236 fprintf(stderr, _("%s: Usage: %s [-number] [-p string] [-cefnrs] "
237 "[+line] [+/pattern/] [files]\n"),
245 fprintf(stderr, _("%s: option requires an argument -- %s\n"),
253 fprintf(stderr, _("%s: illegal option -- %s\n"), progname, s);
259 * A mbstowcs()-alike function that transparently handles invalid sequences.
262 xmbstowcs(wchar_t *pwcs, const char *s, size_t nwcs)
267 mbtowc(pwcs, NULL, MB_CUR_MAX);
269 if ((c = mbtowc(pwcs, s, MB_CUR_MAX)) < 0) {
279 mbtowc(pwcs, NULL, MB_CUR_MAX);
285 * Helper function for tputs().
291 return write(1, &c, 1);
295 * Write messages to terminal.
302 if (*message != '\n' && sflag)
303 vidputs(A_STANDOUT, outcap);
304 write(1, message, strlen(message));
305 if (*message != '\n' && sflag)
306 vidputs(A_NORMAL, outcap);
310 * Get the window size.
315 static int initialized, envlines, envcols, deflines, defcols;
317 struct winsize winsz;
322 if (initialized == 0) {
323 if ((p = getenv("LINES")) != NULL && *p != '\0')
324 if ((envlines = atoi(p)) < 0)
326 if ((p = getenv("COLUMNS")) != NULL && *p != '\0')
327 if ((envcols = atoi(p)) < 0)
329 /* terminfo values. */
330 if (tinfostat != 1 || columns == 0)
334 if (tinfostat != 1 || lines == 0)
341 badioctl = ioctl(1, TIOCGWINSZ, &winsz);
344 ttycols = envcols - 1;
347 ttycols = winsz.ws_col - 1;
350 ttycols = defcols - 1;
351 if (havepagelen == 0) {
353 pagelen = envlines - 1;
356 pagelen = winsz.ws_row - 1;
359 pagelen = deflines - 1;
364 * Message if skipping parts of files.
370 mesg(_("...skipping forward\n"));
372 mesg(_("...skipping backward\n"));
376 * Signal handler while reading from input file.
379 sighandler(int signum)
381 if (canjump && (signum == SIGINT || signum == SIGQUIT))
382 longjmp(jmpenv, signum);
383 tcsetattr(1, TCSADRAIN, &otio);
388 * Check whether the requested file was specified on the command line.
393 if (files.current + nextfile >= files.last) {
394 mesg(_("No next file"));
397 if (files.current + nextfile < files.first) {
398 mesg(_("No previous file"));
406 * Return the last character that will fit on the line at col columns
407 * in case MB_CUR_MAX > 1.
410 endline_for_mb(unsigned col, char *s)
418 if ((wl = xmbstowcs(wbuf, t, sizeof wbuf - 1)) == (size_t)-1)
421 while (*p != L'\0') {
431 * No cursor movement.
448 pos += TABSIZE - (pos % TABSIZE);
456 else if (pos > col + 1)
458 * wcwidth() found a character that
459 * has multiple columns. What happens
460 * now? Assume the terminal will print
461 * the entire character onto the next
476 if ((pos = wcstombs(NULL, p, READBUF)) == -1)
483 * Return the last character that will fit on the line at col columns.
486 endline(unsigned col, char *s)
493 return endline_for_mb(col, s);
506 * No cursor movement.
523 pos += TABSIZE - (pos % TABSIZE);
544 * Clear the current line on the terminal's screen.
549 char *buf = (char *)smalloc(ttycols + 2);
550 memset(buf, ' ', ttycols + 2);
552 buf[ttycols + 1] = '\r';
553 write(1, buf, ttycols + 2);
558 * Evaluate a command character's semantics.
564 case '1': case '2': case '3': case '4': case '5':
565 case '6': case '7': case '8': case '9': case '0':
570 case 'l': case 'd': case '\004': case 'f': case 'z':
571 case '.': case '\014': case '$': case 'n': case 'p':
572 case 'w': case 'h': case 'q': case 'Q':
574 case '/': case '?': case '^':
578 case 'm': case 'b': case 't':
583 tputs(bell, 1, outcap);
590 * Get the count and ignore last character of string.
593 getcount(char *cmdstr)
601 buf = (char *)smalloc(strlen(cmdstr) + 1);
603 if (cmd.key != '\0') {
604 if (cmd.key == '/' || cmd.key == '?' || cmd.key == '^') {
605 if ((p = strchr(buf, cmd.key)) != NULL)
608 *(buf + strlen(buf) - 1) = '\0';
612 if (buf[0] == '-' && buf[1] == '\0') {
625 * Read what the user writes at the prompt. This is tricky because
626 * we check for valid input.
629 prompt(long long pageno)
635 char b[LINE_MAX], *p;
638 if ((p = strstr(pstring, "%d")) == NULL) {
642 sprintf(b + (p - pstring), "%lld", pageno);
647 cmd.key = cmd.addon = cmd.cmdline[0] = '\0';
650 tio.c_lflag &= ~(ICANON | ECHO);
653 tcsetattr(1, TCSADRAIN, &tio);
654 tcflush(1, TCIFLUSH);
656 switch (read(1, &key, 1)) {
661 if (key == tio.c_cc[VERASE]) {
663 write(1, "\b \b", 3);
664 cmd.cmdline[--cmd.cmdlen] = '\0';
678 if (cmd.cmdline[cmd.cmdlen - 1]
681 while(cmd.cmdline[cmd.cmdlen
688 if (strchr(cmd.cmdline, cmd.key)
697 if (cmd.cmdlen == 0) {
703 if (key == tio.c_cc[VKILL]) {
706 cmd.cmdline[0] = '\0';
711 if (key == '\n' || (nflag && state == COUNT && key == ' '))
713 if (cmd.cmdlen >= CMDBUF - 1)
728 if (getstate(key) != ADDON_FIN)
737 searchdisplay = MIDDLE;
740 searchdisplay = BOTTOM;
748 state = getstate(key);
751 if (cmd.cmdlen != 0) {
767 cmd.cmdline[cmd.cmdlen++] = key;
768 cmd.cmdline[cmd.cmdlen] = '\0';
769 if (nflag && state == CMD_FIN)
773 tcsetattr(1, TCSADRAIN, &otio);
775 cmd.count = getcount(cmd.cmdline);
780 * Remove backspace formatting, for searches
781 * in case MB_CUR_MAX > 1.
788 size_t l = strlen(s), wl;
791 if ((wl = xmbstowcs(wbuf, p, sizeof wbuf)) == (size_t)-1)
793 for (wp = wbuf, wq = wbuf, i = 0; *wp != L'\0' && i < wl;
805 wcstombs(s, wp, l + 1);
812 * Remove backspace formatting, for searches.
821 return colb_for_mb(s);
824 for (q = s; *p != '\0'; p++, q++) {
840 * Convert nonprintable characters to spaces
841 * in case MB_CUR_MAX > 1.
844 makeprint_for_mb(char *s, size_t l)
850 if ((wl = xmbstowcs(wbuf, t, sizeof wbuf)) == (size_t)-1)
853 if (!iswprint(*wp) && *wp != L'\n' && *wp != L'\r'
854 && *wp != L'\b' && *wp != L'\t')
864 * Convert nonprintable characters to spaces.
867 makeprint(char *s, size_t l)
871 return makeprint_for_mb(s, l);
875 if (!isprint(cuc(*s)) && *s != '\n' && *s != '\r'
876 && *s != '\b' && *s != '\t')
883 * Strip backslash characters from the given string.
895 } while (*s++ != '\0');
899 * Extract the search pattern off the command line.
906 if (cmd.addon == '\0')
907 p = cmd.cmdline + strlen(cmd.cmdline) - 1;
909 p = cmd.cmdline + strlen(cmd.cmdline) - 2;
914 if ((p = strchr(cmd.cmdline, cmd.key)) != NULL) {
922 * Process errors that occurred in temporary file operations.
925 tmperr(FILE *f, char *ftype)
928 fprintf(stderr, _("%s: Read error from %s file\n"),
932 * Most likely '\0' in input.
934 fprintf(stderr, _("%s: Unexpected EOF in %s file\n"),
937 fprintf(stderr, _("%s: Unknown error in %s file\n"),
943 * perror()-like, but showing the program's name.
946 pgerror(int eno, char *string)
948 fprintf(stderr, "%s: %s: %s\n", progname, string, strerror(eno));
952 * Read the file and respond to user input.
953 * Beware: long and ugly.
956 pgfile(FILE *f, char *name)
958 off_t pos, oldpos, fpos;
959 off_t line = 0, fline = 0, bline = 0, oldline = 0, eofline = 0;
962 * These are the line counters:
963 * line the line desired to display
964 * fline the current line of the input file
965 * bline the current line of the file buffer
966 * oldline the line before a search was started
967 * eofline the last line of the file if it is already reached
968 * dline the line on the display
971 unsigned searchcount = 0;
973 * Advance to EOF immediately.
977 * EOF has been reached by `line'.
981 * f and fbuf refer to the same file.
990 * fbuf an exact copy of the input file as it gets read
991 * find index table for input, one entry per line
992 * save for the s command, to save to a file
994 FILE *fbuf, *find, *save;
996 /* silence compiler - it may warn about longjmp() */
1005 CLOBBGRD(searchcount);
1014 * Just copy stdin to stdout.
1016 while ((sz = fread(b, sizeof *b, READBUF, f)) != 0)
1019 pgerror(errno, name);
1024 if ((fpos = fseeko(f, (off_t)0, SEEK_SET)) == -1)
1031 if (fbuf == NULL || find == NULL) {
1032 fprintf(stderr, _("%s: Cannot create tempfile\n"), progname);
1039 rerror = regcomp(&re, searchfor, REG_NOSUB | REG_NEWLINE);
1041 mesg(_("RE error: "));
1042 regerror(rerror, &re, b, READBUF);
1049 for (line = startline; ; ) {
1051 * Get a line from input file or buffer.
1054 fseeko(find, line * sizeof pos, SEEK_SET);
1055 if (fread(&pos, sizeof pos, 1, find) == 0)
1056 tmperr(find, "index");
1057 fseeko(find, (off_t)0, SEEK_END);
1058 fseeko(fbuf, pos, SEEK_SET);
1059 if (fgets(b, READBUF, fbuf) == NULL)
1060 tmperr(fbuf, "buffer");
1061 } else if (eofline == 0) {
1062 fseeko(find, (off_t)0, SEEK_END);
1065 fseeko(fbuf, (off_t)0, SEEK_END);
1067 if ((sig = setjmp(jmpenv)) != 0) {
1073 fseeko(fbuf, pos, SEEK_SET);
1079 fseeko(f, fpos, SEEK_SET);
1081 p = fgets(b, READBUF, f);
1083 if ((fpos = ftello(f)) == -1)
1084 pgerror(errno, name);
1087 if (p == NULL || *b == '\0') {
1089 pgerror(errno, name);
1096 fwrite(&pos, sizeof pos, 1, find);
1100 while (*(p = endline(ttycols,
1103 pos = oldpos + (p - b);
1113 } while (line > bline++);
1120 if (search == FORWARD && remembered == 1) {
1123 search = searchcount = 0;
1124 mesg(_("Pattern not found"));
1130 if (regexec(&re, b, 0, NULL, 0) == 0) {
1133 if (searchcount == 0) {
1135 switch (searchdisplay) {
1140 line -= pagelen / 2 + 1;
1149 } else if (eof) { /*
1150 * We are not searching.
1153 } else if (*b != '\0') {
1154 if (cflag && clear_screen) {
1157 tputs(clear_screen, 1, outcap);
1162 if (eofline && line == eofline)
1165 if ((sig = setjmp(jmpenv)) != 0) {
1173 p = endline(ttycols, b);
1181 if (dline >= pagelen || eof) {
1183 * Time for prompting!
1185 if (eof && seekeof) {
1187 if (line >= pagelen)
1196 if (fline == 0 || eflag)
1200 prompt((line - 1) / pagelen + 1);
1208 searchcount = cmd.count;
1210 if (p != NULL && *p) {
1211 if (remembered == 1)
1213 rerror = regcomp(&re, p,
1214 REG_NOSUB | REG_NEWLINE);
1216 mesg(_("RE error: "));
1217 sz = regerror(rerror, &re,
1223 } else if (remembered == 0) {
1224 mesg(_("No remembered search string"));
1235 searchcount = cmd.count;
1237 if (p != NULL && *p) {
1238 if (remembered == 1)
1240 rerror = regcomp(&re, p,
1241 REG_NOSUB | REG_NEWLINE);
1243 mesg(_("RE error: "));
1244 regerror(rerror, &re,
1250 } else if (remembered == 0) {
1251 mesg(_("No remembered search string"));
1258 fseeko(find, --line * sizeof pos,
1260 if(fread(&pos, sizeof pos, 1,find)==0)
1261 tmperr(find, "index");
1262 fseeko(find, (off_t)0, SEEK_END);
1263 fseeko(fbuf, pos, SEEK_SET);
1264 if (fgets(b, READBUF, fbuf) == NULL)
1265 tmperr(fbuf, "buffer");
1267 if (regexec(&re, b, 0, NULL, 0) == 0)
1269 if (searchcount == 0)
1274 search = searchcount = 0;
1275 mesg(_("Pattern not found"));
1278 eof = search = dline = 0;
1280 switch (searchdisplay) {
1285 line -= pagelen / 2;
1301 while (*++p == ' ');
1304 save = fopen(p, "wb");
1307 mesg(_("Cannot open "));
1310 mesg(strerror(cmd.count));
1316 fseeko(find, (off_t)0, SEEK_END);
1319 fseeko(fbuf,(off_t)0,SEEK_END);
1321 if (fgets(b, READBUF, f) == NULL) {
1327 fwrite(&pos, sizeof pos, 1, find);
1331 while (*(p = endline(ttycols,
1334 pos = oldpos + (p - b);
1345 fseeko(fbuf, (off_t)0, SEEK_SET);
1346 while ((sz = fread(b, sizeof *b, READBUF,
1349 * No error check for compat.
1351 fwrite(b, sizeof *b, sz, save);
1354 fseeko(fbuf, (off_t)0, SEEK_END);
1361 if (*cmd.cmdline != 'l')
1364 cmd.count = 1; /* compat */
1365 if (isdigit(cuc(*cmd.cmdline))) {
1366 line = cmd.count - 2;
1369 if (cmd.count != 1) {
1370 line += cmd.count - 1
1376 * Nothing to do if count==1.
1382 * Half screen forward.
1384 case '\004': /* ^D */
1385 if (*cmd.cmdline != cmd.key)
1388 cmd.count = 1; /* compat */
1389 line += (cmd.count * pagelen / 2)
1399 cmd.count = 1; /* compat */
1400 line += cmd.count * pagelen - 2;
1403 if (*cmd.cmdline != 'f')
1407 if (eofline && line >= eofline)
1414 * Just a number, or '-', or <newline>.
1417 cmd.count = 1; /* compat */
1418 if (isdigit(cuc(*cmd.cmdline)))
1419 line = (cmd.count - 1) * pagelen - 2;
1421 line += (cmd.count - 1)
1422 * (pagelen - 1) - 2;
1423 if (*cmd.cmdline != '\0')
1425 if (cmd.count != 1) {
1445 case '\014': /* ^L */
1450 if (line >= pagelen)
1462 mesg(_(": !command not allowed in "
1467 write(1, cmd.cmdline,
1468 strlen(cmd.cmdline));
1470 my_sigset(SIGINT, SIG_IGN);
1471 my_sigset(SIGQUIT, SIG_IGN);
1472 switch (cpid = fork()) {
1474 p = getenv("SHELL");
1475 if (p == NULL) p = "/bin/sh";
1479 if (isatty(0) == 0) {
1481 open(tty, O_RDONLY);
1485 my_sigset(SIGINT, oldint);
1486 my_sigset(SIGQUIT, oldquit);
1487 my_sigset(SIGTERM, oldterm);
1489 cmd.cmdline + 1, NULL);
1494 mesg(_("fork() failed, "
1495 "try again later\n"));
1498 while (wait(NULL) != cpid);
1500 my_sigset(SIGINT, sighandler);
1501 my_sigset(SIGQUIT, sighandler);
1510 const char *help = _(helpscreen);
1511 write(1, copyright + 4, strlen(copyright + 4));
1512 write(1, help, strlen(help));
1521 nextfile = cmd.count;
1534 nextfile = 0 - cmd.count;
1555 if (*cmd.cmdline != cmd.key)
1556 pagelen = ++cmd.count;
1564 if (cflag && dline == 1) {
1578 main(int argc, char **argv)
1584 progname = basename(argv[0]);
1586 setlocale(LC_MESSAGES, "");
1587 bindtextdomain(PACKAGE, LOCALEDIR);
1588 textdomain(PACKAGE);
1590 if (tcgetattr(1, &otio) == 0) {
1592 oldint = my_sigset(SIGINT, sighandler);
1593 oldquit = my_sigset(SIGQUIT, sighandler);
1594 oldterm = my_sigset(SIGTERM, sighandler);
1595 setlocale(LC_CTYPE, "");
1596 setlocale(LC_COLLATE, "");
1598 setupterm(NULL, 1, &tinfostat);
1600 helpscreen = _(helpscreen);
1602 for (arg = 1; argv[arg]; arg++) {
1603 if (*argv[arg] == '+')
1605 if (*argv[arg] != '-' || argv[arg][1] == '\0')
1608 for (i = 1; argv[arg][i]; i++) {
1609 switch (argv[arg][i]) {
1611 if (i != 1 || argv[arg][i + 1])
1612 invopt(&argv[arg][i]);
1614 case '1': case '2': case '3': case '4': case '5':
1615 case '6': case '7': case '8': case '9': case '0':
1616 pagelen = atoi(argv[arg] + i);
1632 if (argv[arg][i + 1]) {
1633 pstring = &argv[arg][i + 1];
1634 } else if (argv[++arg]) {
1636 pstring = argv[arg];
1647 invopt(&argv[arg][i]);
1654 for (arg = 1; argv[arg]; arg++) {
1655 if (*argv[arg] == '-') {
1656 if (argv[arg][1] == '-') {
1660 if (argv[arg][1] == '\0')
1662 if (argv[arg][1] == 'p' && argv[arg][2] == '\0')
1666 if (*argv[arg] != '+')
1669 switch (*(argv[arg] + 1)) {
1673 case '1': case '2': case '3': case '4': case '5':
1674 case '6': case '7': case '8': case '9': case '0':
1675 startline = atoi(argv[arg] + 1);
1678 searchfor = argv[arg] + 2;
1679 if (*searchfor == '\0')
1681 p = searchfor + strlen(searchfor) - 1;
1682 if (*p == '/') *p = '\0';
1683 if (*searchfor == '\0')
1691 pgfile(stdin, "stdin");
1694 files.last = arg + argc - 1;
1695 for ( ; argv[arg]; arg += nextfile) {
1697 files.current = arg;
1699 static int firsttime;
1701 if (firsttime > 1) {
1702 mesg(_("(Next file: "));
1715 nextfile = cmd.count;
1728 nextfile = 0 - cmd.count;
1742 if (strcmp(argv[arg], "-") == 0)
1745 input = fopen(argv[arg], "r");
1746 if (input == NULL) {
1747 pgerror(errno, argv[arg]);
1752 if (ontty == 0 && argc > 2) {
1754 * Use the prefix as specified by SUSv2.
1756 write(1, "::::::::::::::\n", 15);
1757 write(1, argv[arg], strlen(argv[arg]));
1758 write(1, "\n::::::::::::::\n", 16);
1760 pgfile(input, argv[arg]);