summaryrefslogtreecommitdiff
path: root/usr/src/cmd/bfs
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/bfs
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/bfs')
-rw-r--r--usr/src/cmd/bfs/Makefile44
-rw-r--r--usr/src/cmd/bfs/bfs.c1502
2 files changed, 1546 insertions, 0 deletions
diff --git a/usr/src/cmd/bfs/Makefile b/usr/src/cmd/bfs/Makefile
new file mode 100644
index 0000000000..bc9004cbc0
--- /dev/null
+++ b/usr/src/cmd/bfs/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1989 by Sun Microsystems, Inc.
+#
+
+PROG= bfs
+
+include ../Makefile.cmd
+
+LDLIBS += -lgen
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTPROG)
+
+clean:
+
+lint: lint_PROG
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/bfs/bfs.c b/usr/src/cmd/bfs/bfs.c
new file mode 100644
index 0000000000..86a9905c9d
--- /dev/null
+++ b/usr/src/cmd/bfs/bfs.c
@@ -0,0 +1,1502 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+#include <setjmp.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <regexpr.h>
+#include <limits.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <locale.h>
+#include <stdio.h>
+#include <string.h>
+#include <wait.h>
+#include <fcntl.h>
+int setjmp();
+static jmp_buf env;
+
+extern int scrwidth(wchar_t);
+
+#define BRKTYP char
+#define BRKSIZ 8192
+#define BRKTWO 4
+#define BFSAND
+#define BFSLIM 511
+#define BFSTRU 511
+#define BFSBUF 512
+
+struct Comd {
+ int Cnumadr;
+ int Cadr[2];
+ char Csep;
+ char Cop;
+};
+
+static int Dot, Dollar;
+static int markarray[26], *mark;
+static int fstack[15] = {1, -1};
+static int infildes = 0;
+static int outfildes = 1;
+static char internal[512], *intptr;
+static char comdlist[100];
+static char *endds;
+static char charbuf = '\n';
+static int peeked;
+static char currex[100];
+static int trunc = BFSTRU;
+static int crunch = -1;
+static int segblk[512], segoff[512], txtfd, prevblk, prevoff;
+static int oldfd = 0;
+static int flag4 = 0;
+static int flag3 = 0;
+static int flag2 = 0;
+static int flag1 = 0;
+static int flag = 0;
+static int lprev = 1;
+static int status[1];
+static BRKTYP *lincnt;
+static char *perbuf;
+static char *rebuf;
+static char *glbuf;
+static char tty, *bigfile;
+static char fle[80];
+static char prompt = 1;
+static char verbose = 1; /* 1=print # of bytes read in; 0=silent. */
+static char varray[10][100]; /* Holds xv cmd parameters. */
+static double outcnt;
+static char strtmp[32];
+
+static void reset();
+static void begin(struct Comd *p);
+static int bigopen(char file[]);
+static void sizeprt(int blk, int off);
+static void bigread(int l, char rec[]);
+static int gcomd(struct Comd *p, int k);
+static int fcomd(struct Comd *p);
+static void ecomd();
+static int kcomd(struct Comd *p);
+static int xncomd(struct Comd *p);
+static int pcomd(struct Comd *p);
+static int qcomd();
+static int xcomds(struct Comd *p);
+static int xbcomd(struct Comd *p);
+static int xccomd(struct Comd *p);
+static int xfcomd(struct Comd *p);
+static int xocomd(struct Comd *p);
+static int xtcomd(struct Comd *p);
+static int xvcomd();
+static int wcomd(struct Comd *p);
+static int nlcomd(struct Comd *p);
+static int eqcomd(struct Comd *p);
+static int colcomd(struct Comd *p);
+static int excomd();
+static int xcomdlist(struct Comd *p);
+static int defaults(struct Comd *p, int prt, int max,
+ int def1, int def2, int setdot, int errsok);
+static int getcomd(struct Comd *p, int prt);
+static int getadrs(struct Comd *p, int prt);
+static int getadr(struct Comd *p, int prt);
+static int getnumb(struct Comd *p, int prt);
+static int rdnumb(int prt);
+static int getrel(struct Comd *p, int prt);
+static int getmark(struct Comd *p, int prt);
+static int getrex(struct Comd *p, int prt, char c);
+static int hunt(int prt, char rex[], int start, int down, int wrap, int errsok);
+static int jump(int prt, char label[]);
+static int getstr(int prt, char buf[], char brk, char ignr, int nonl);
+static int regerr(int c);
+static int err(int prt, char msg[]);
+static char mygetc();
+static int readc(int f, char *c);
+static int percent(char line[256]);
+static int newfile(int prt, char f[]);
+static void push(int s[], int d);
+static int pop(int s[]);
+static int peekc();
+static void eat();
+static int more();
+static void quit();
+static void out(char *ln);
+static char *untab(char l[]);
+static int patoi(char *b);
+static int equal(char *a, char *b);
+
+void
+main(int argc, char *argv[])
+{
+ struct Comd comdstruct, *p;
+ (void) setlocale(LC_ALL, "");
+ if (argc < 2 || argc > 3) {
+ (void) err(1, "arg count");
+ quit();
+ }
+ mark = markarray-'a';
+ if (argc == 3) {
+ verbose = 0;
+ }
+ setbuf(stdout, 0);
+ if (bigopen(bigfile = argv[argc-1]))
+ quit();
+ tty = isatty(0);
+ p = &comdstruct;
+ /* Look for 0 or more non-'%' char followed by a '%' */
+ perbuf = compile("[^%]*%", (char *)0, (char *)0);
+ if (regerrno)
+ (void) regerr(regerrno);
+ (void) setjmp(env);
+#if defined(__STDC__)
+ (void) signal(SIGINT, (void (*)(int))reset);
+#else
+ (void) signal(SIGINT, reset);
+#endif
+ (void) err(0, "");
+ (void) printf("\n");
+ flag = 0;
+ prompt = 0;
+ /*CONSTCOND*/ for (;;)
+ begin(p);
+}
+
+static void
+reset() /* for longjmp on signal */
+{
+ longjmp(env, 1);
+}
+
+static void
+begin(struct Comd *p)
+{
+ char line[256];
+ strtagn:
+ if (flag == 0)
+ eat();
+ if (infildes != 100) {
+ if (infildes == 0 && prompt)
+ (void) printf("*");
+ flag3 = 1;
+ if (getstr(1, line, 0, 0, 0))
+ exit(1);
+ flag3 = 0;
+ if (percent(line) < 0)
+ goto strtagn;
+ (void) newfile(1, "");
+ }
+ if (!(getcomd(p, 1) < 0)) {
+ switch (p->Cop) {
+ case 'e':
+ if (!flag)
+ ecomd();
+ else
+ (void) err(0, "");
+ break;
+
+ case 'f':
+ (void) fcomd(p);
+ break;
+
+ case 'g':
+ if (flag == 0)
+ (void) gcomd(p, 1);
+ else
+ (void) err(0, "");
+ break;
+
+ case 'k':
+ (void) kcomd(p);
+ break;
+
+ case 'p':
+ (void) pcomd(p);
+ break;
+
+ case 'q':
+ (void) qcomd();
+ break;
+
+ case 'v':
+ if (flag == 0)
+ (void) gcomd(p, 0);
+ else
+ (void) err(0, "");
+ break;
+
+ case 'x':
+ if (!flag)
+ (void) xcomds(p);
+ else
+ (void) err(0, "");
+ break;
+
+ case 'w':
+ (void) wcomd(p);
+ break;
+
+ case '\n':
+ (void) nlcomd(p);
+ break;
+
+ case '=':
+ (void) eqcomd(p);
+ break;
+
+ case ':':
+ (void) colcomd(p);
+ break;
+
+ case '!':
+ (void) excomd();
+ break;
+
+ case 'P':
+ prompt = !prompt;
+ break;
+
+ default:
+ if (flag)
+ (void) err(0, "");
+ else
+ (void) err(1, "bad command");
+ break;
+ }
+ }
+}
+
+static int
+bigopen(char file[])
+{
+ int l, off, cnt;
+ int blk, newline, n, s;
+ char block[512];
+ size_t totsiz;
+ BRKTYP *tptr;
+ if ((txtfd = open(file, 0)) < 0)
+ return (err(1, "can't open"));
+ blk = -1;
+ newline = 1;
+ l = cnt = s = 0;
+ off = 512;
+ totsiz = 0;
+ if ((lincnt = (BRKTYP *)malloc(BRKSIZ)) == (BRKTYP *)NULL)
+ return (err(1, "too many lines"));
+ endds = (BRKTYP *)lincnt;
+ totsiz += BRKSIZ;
+ while ((n = read(txtfd, block, 512)) > 0) {
+ blk++;
+ for (off = 0; off < n; off++) {
+ if (newline) {
+ newline = 0;
+ if (l > 0 && !(l&07777)) {
+ totsiz += BRKSIZ;
+ tptr = (BRKTYP *)
+ realloc(lincnt, totsiz);
+ if (tptr == NULL)
+ return
+ (err(1, "too many lines"));
+ else
+ lincnt = tptr;
+ }
+ lincnt[l] = (char)cnt;
+ cnt = 0;
+ if (!(l++ & 077)) {
+ segblk[s] = blk;
+ segoff[s++] = off;
+ }
+ if (l < 0 || l > 32767)
+ return (err(1, "too many lines"));
+ }
+ if (block[off] == '\n') newline = 1;
+ cnt++;
+ }
+ }
+ if (!(l&07777)) {
+ totsiz += BRKTWO;
+ tptr = (BRKTYP *)realloc(lincnt, totsiz);
+ if (tptr == NULL)
+ return (err(1, "too many lines"));
+ else
+ lincnt = tptr;
+ }
+ lincnt[Dot = Dollar = l] = (char)cnt;
+ sizeprt(blk, off);
+ return (0);
+}
+
+static void
+sizeprt(int blk, int off)
+{
+ if (verbose)
+ (void) printf("%.0f", 512.*blk+off);
+}
+
+static int saveblk = -1;
+
+static void
+bigread(int l, char rec[])
+{
+ int i;
+ char *r, *b;
+ int off;
+ static char savetxt[512];
+
+ if ((i = l-lprev) == 1) prevoff += lincnt[lprev]BFSAND;
+ else if (i >= 0 && i <= 32)
+ for (i = lprev; i < l; i++) prevoff += lincnt[i]BFSAND;
+ else if (i < 0 && i >= -32)
+ for (i = lprev-1; i >= l; i--) prevoff -= lincnt[i]BFSAND;
+ else {
+ prevblk = segblk[i = (l-1)>>6];
+ prevoff = segoff[i];
+ for (i = (i<<6)+1; i < l; i++) prevoff += lincnt[i]BFSAND;
+ }
+
+ prevblk += prevoff>>9;
+ prevoff &= 0777;
+ lprev = l;
+ if (prevblk != saveblk) {
+ (void) lseek(txtfd, ((long)(saveblk = prevblk))<<9, 0);
+ (void) read(txtfd, savetxt, 512);
+ }
+ r = rec;
+ off = prevoff;
+ /*CONSTCOND*/while (1) {
+ for (b = savetxt+off; b < savetxt+512; b++) {
+ if ((*r++ = *b) == '\n') {
+ *(r-1) = '\0';
+ return;
+ }
+ if (((unsigned)r - (unsigned)rec) > BFSLIM) {
+
+ (void) write(2,
+ "Line too long--output truncated\n", 32);
+ return;
+ }
+ }
+ (void) read(txtfd, savetxt, 512);
+ off = 0;
+ saveblk++;
+ }
+}
+
+static void
+ecomd()
+{
+ int i = 0;
+ while (peekc() == ' ')
+ (void) mygetc();
+ while ((fle[i++] = mygetc()) != '\n');
+ fle[--i] = '\0';
+ /* Without this, ~20 "e" cmds gave "can't open" msg. */
+ (void) close(txtfd);
+ free(endds);
+ /* Reset parameters. */
+ lprev = 1;
+ prevblk = 0;
+ prevoff = 0;
+ saveblk = -1;
+ if (bigopen(bigfile = fle))
+ quit();
+ (void) printf("\n");
+}
+
+static int
+fcomd(struct Comd *p)
+{
+ if (more() || defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+ (void) printf("%s\n", bigfile);
+ return (0);
+}
+
+static int
+gcomd(struct Comd *p, int k)
+{
+ char d;
+ int i, end;
+ char line[BFSBUF];
+ if (defaults(p, 1, 2, 1, Dollar, 0, 0))
+ return (-1);
+ if ((d = mygetc()) == '\n')
+ return (err(1, "syntax"));
+ if (peekc() == d)
+ (void) mygetc();
+ else
+ if (getstr(1, currex, d, 0, 1))
+ return (-1);
+ glbuf = compile(currex, (char *)0, (char *)0);
+ if (regerrno) {
+ (void) regerr(regerrno);
+ return (-1);
+ } else {
+ if (glbuf)
+ free(glbuf);
+ }
+
+ if (getstr(1, comdlist, 0, 0, 0))
+ return (-1);
+ i = p->Cadr[0];
+ end = p->Cadr[1];
+ while (i <= end) {
+ bigread(i, line);
+ if (!(step(line, glbuf))) {
+ if (!k) {
+ Dot = i;
+ if (xcomdlist(p))
+ return (err(1, "bad comd list"));
+ }
+ i++;
+ } else {
+ if (k) {
+ Dot = i;
+ if (xcomdlist(p))
+ return (err(1, "bad comd list"));
+ }
+ i++;
+ }
+ }
+ return (0);
+}
+
+static int
+kcomd(struct Comd *p)
+{
+ char c;
+ if ((c = peekc()) < 'a' || c > 'z')
+ return (err(1, "bad mark"));
+ (void) mygetc();
+ if (more() || defaults(p, 1, 1, Dot, 0, 1, 0))
+ return (-1);
+ mark[c] = Dot = p->Cadr[0];
+ return (0);
+}
+
+static int
+xncomd(struct Comd *p)
+{
+ char c;
+ if (more() || defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+
+ for (c = 'a'; c <= 'z'; c++)
+ if (mark[c])
+ (void) printf("%c\n", c);
+
+ return (0);
+}
+
+static int
+pcomd(struct Comd *p)
+{
+ int i;
+ char line[BFSBUF];
+ if (more() || defaults(p, 1, 2, Dot, Dot, 1, 0))
+ return (-1);
+ for (i = p->Cadr[0]; i <= p->Cadr[1] && i > 0; i++) {
+ bigread(i, line);
+ out(line);
+ }
+ return (0);
+}
+
+static int
+qcomd()
+{
+ if (more())
+ return (-1);
+ quit();
+ return (0);
+}
+
+static int
+xcomds(struct Comd *p)
+{
+ switch (mygetc()) {
+ case 'b': return (xbcomd(p));
+ case 'c': return (xccomd(p));
+ case 'f': return (xfcomd(p));
+ case 'n': return (xncomd(p));
+ case 'o': return (xocomd(p));
+ case 't': return (xtcomd(p));
+ case 'v': return (xvcomd());
+ default: return (err(1, "bad command"));
+ }
+}
+
+static int
+xbcomd(struct Comd *p)
+{
+ int fail, n;
+ char d;
+ char str[50];
+
+ fail = 0;
+ if (defaults(p, 0, 2, Dot, Dot, 0, 1))
+ fail = 1;
+ else {
+ if ((d = mygetc()) == '\n')
+ return (err(1, "syntax"));
+ if (d == 'z') {
+ if (status[0] != 0)
+ return (0);
+ (void) mygetc();
+ if (getstr(1, str, 0, 0, 0))
+ return (-1);
+ return (jump(1, str));
+ }
+ if (d == 'n') {
+ if (status[0] == 0)
+ return (0);
+ (void) mygetc();
+ if (getstr(1, str, 0, 0, 0))
+ return (-1);
+ return (jump(1, str));
+ }
+ if (getstr(1, str, d, ' ', 0))
+ return (-1);
+ if ((n = hunt(0, str, p->Cadr[0]-1, 1, 0, 1)) < 0)
+ fail = 1;
+ if (getstr(1, str, 0, 0, 0))
+ return (-1);
+ if (more())
+ return (err(1, "syntax"));
+ }
+ if (!fail) {
+ Dot = n;
+ return (jump(1, str));
+ }
+ return (0);
+}
+
+static int
+xccomd(struct Comd *p)
+{
+ char arg[100];
+ if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+ if (equal(arg, ""))
+ crunch = -crunch;
+ else if (equal(arg, "0"))
+ crunch = -1;
+ else if (equal(arg, "1"))
+ crunch = 1;
+ else
+ return (err(1, "syntax"));
+
+ return (0);
+}
+
+static int
+xfcomd(struct Comd *p)
+{
+ char fl[100];
+ char *f;
+ if (defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+
+ while (peekc() == ' ')
+ (void) mygetc();
+ for (f = fl; (*f = mygetc()) != '\n'; f++);
+ if (f == fl)
+ return (err(1, "no file"));
+ *f = '\0';
+
+ return (newfile(1, fl));
+}
+
+static int
+xocomd(struct Comd *p)
+{
+ int fd;
+ char arg[100];
+
+ if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+
+ if (!arg[0]) {
+ if (outfildes == 1)
+ return (err(1, "no diversion"));
+ (void) close(outfildes);
+ outfildes = 1;
+ } else {
+ if (outfildes != 1)
+ return (err(1, "already diverted"));
+ if ((fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC,
+ (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))) < 0)
+ return (err(1, "can't create"));
+ outfildes = fd;
+ }
+ return (0);
+}
+
+static int
+xtcomd(struct Comd *p)
+{
+ int t;
+
+ while (peekc() == ' ')
+ (void) mygetc();
+ if ((t = rdnumb(1)) < 0 || more() || defaults(p, 1, 0, 0, 0, 0, 0))
+ return (-1);
+
+ trunc = t;
+ return (0);
+}
+
+static int
+xvcomd()
+{
+ char c;
+ int i;
+ int temp0, temp1, temp2;
+ int fildes[2];
+
+ if ((c = peekc()) < '0' || c > '9')
+ return (err(1, "digit required"));
+ (void) mygetc();
+ c -= '0';
+ while (peekc() == ' ')
+ (void) mygetc();
+ if (peekc() == '\\')
+ (void) mygetc();
+ else if (peekc() == '!') {
+ if (pipe(fildes) < 0) {
+ (void) printf("Try again");
+ return (-1);
+ }
+ temp0 = dup(0);
+ temp1 = dup(1);
+ temp2 = infildes;
+ (void) close(0);
+ (void) dup(fildes[0]);
+ (void) close(1);
+ (void) dup(fildes[1]);
+ (void) close(fildes[0]);
+ (void) close(fildes[1]);
+ (void) mygetc();
+ flag4 = 1;
+ (void) excomd();
+ (void) close(1);
+ infildes = 0;
+ }
+ for (i = 0; (varray[c][i] = mygetc()) != '\n'; i++);
+ varray[c][i] = '\0';
+ if (flag4) {
+ infildes = temp2;
+ (void) close(0);
+ (void) dup(temp0);
+ (void) close(temp0);
+ (void) dup(temp1);
+ (void) close(temp1);
+ flag4 = 0;
+ charbuf = ' ';
+ }
+ return (0);
+}
+
+static int
+wcomd(struct Comd *p)
+{
+ int i, fd, savefd;
+ int savecrunch, savetrunc;
+ char arg[100], line[BFSBUF];
+
+ if (getstr(1, arg, 0, ' ', 0) || defaults(p, 1, 2, 1, Dollar, 1, 0))
+ return (-1);
+ if (!arg[0])
+ return (err(1, "no file name"));
+ if (equal(arg, bigfile))
+ return (err(1, "no change indicated"));
+ if ((fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC,
+ (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH))) < 0)
+ return (err(1, "can't create"));
+
+ savefd = outfildes;
+ savetrunc = trunc;
+ savecrunch = crunch;
+ outfildes = fd;
+ trunc = BFSTRU;
+ crunch = -1;
+
+ outcnt = 0;
+ for (i = p->Cadr[0]; i <= p->Cadr[1] && i > 0; i++) {
+ bigread(i, line);
+ out(line);
+ }
+ if (verbose)
+ (void) printf("%.0f\n", outcnt);
+ (void) close(fd);
+
+ outfildes = savefd;
+ trunc = savetrunc;
+ crunch = savecrunch;
+ return (0);
+}
+
+static int
+nlcomd(struct Comd *p)
+{
+ if (defaults(p, 1, 2, Dot+1, Dot+1, 1, 0)) {
+ (void) mygetc();
+ return (-1);
+ }
+ return (pcomd(p));
+}
+
+static int
+eqcomd(struct Comd *p)
+{
+ if (more() || defaults(p, 1, 1, Dollar, 0, 0, 0))
+ return (-1);
+ (void) printf("%d\n", p->Cadr[0]);
+ return (0);
+}
+
+static int
+colcomd(struct Comd *p)
+{
+ return (defaults(p, 1, 0, 0, 0, 0, 0));
+}
+
+static int
+xcomdlist(struct Comd *p)
+{
+ flag = 1;
+ flag2 = 1;
+ (void) newfile(1, "");
+ while (flag2)
+ begin(p);
+ if (flag == 0)
+ return (1);
+ flag = 0;
+ return (0);
+}
+
+static int
+excomd()
+{
+ pid_t i;
+ int j;
+ if (infildes != 100)
+ charbuf = '\n';
+ while ((i = fork()) < (pid_t)0)
+ (void) sleep(10);
+ if (i == (pid_t)0) {
+ /* Guarantees child can be intr. */
+ (void) signal(SIGINT, SIG_DFL);
+ if (infildes == 100 || flag4) {
+ (void) execl("/usr/bin/sh", "sh", "-c", intptr, 0);
+ exit(0);
+ }
+ if (infildes != 0) {
+ (void) close(0);
+ (void) dup(infildes);
+ }
+ for (j = 3; j < 15; j++) (void) close(j);
+ (void) execl("/usr/bin/sh", "sh", "-t", 0);
+ exit(0);
+ }
+ (void) signal(SIGINT, SIG_IGN);
+ while (wait(status) != i);
+ status[0] = status[0] >> 8;
+
+#if defined(__STDC__)
+ (void) signal(SIGINT, (void (*)(int))reset);
+#else
+ (void) signal(SIGINT, reset); /* Restore signal to previous status */
+#endif
+
+ if (((infildes == 0) || ((infildes == 100) &&
+ (fstack[fstack[0]] == 0)))&& verbose && (!flag4))
+ (void) printf("!\n");
+ return (0);
+}
+
+static int
+defaults(struct Comd *p, int prt, int max,
+ int def1, int def2, int setdot, int errsok)
+{
+ if (!def1)
+ def1 = Dot;
+ if (!def2)
+ def2 = def1;
+ if (p->Cnumadr >= max)
+ return (errsok?-1:err(prt, "adr count"));
+ if (p->Cnumadr < 0) {
+ p->Cadr[++p->Cnumadr] = def1;
+ p->Cadr[++p->Cnumadr] = def2;
+ } else if (p->Cnumadr < 1)
+ p->Cadr[++p->Cnumadr] = p->Cadr[0];
+ if (p->Cadr[0] < 1 || p->Cadr[0] > Dollar ||
+ p->Cadr[1] < 1 || p->Cadr[1] > Dollar)
+ return (errsok?-1:err(prt, "range"));
+ if (p->Cadr[0] > p->Cadr[1])
+ return (errsok?-1:err(prt, "adr1 > adr2"));
+ if (setdot)
+ Dot = p->Cadr[1];
+ return (0);
+}
+
+static int
+getcomd(struct Comd *p, int prt)
+{
+ int r;
+ int c;
+
+ p->Cnumadr = -1;
+ p->Csep = ' ';
+ switch (c = peekc()) {
+ case ',':
+ case ';': p->Cop = mygetc();
+ return (0);
+ }
+
+ if ((r = getadrs(p, prt)) < 0)
+ return (r);
+
+ if ((c = peekc()) < 0)
+ return (err(prt, "syntax"));
+ if (c == '\n')
+ p->Cop = '\n';
+ else
+ p->Cop = mygetc();
+
+ return (0);
+}
+
+static int
+getadrs(struct Comd *p, int prt)
+{
+ int r;
+ char c;
+
+ if ((r = getadr(p, prt)) < 0)
+ return (r);
+
+ switch (c = peekc()) {
+ case ';':
+ Dot = p->Cadr[0];
+ (void) mygetc();
+ p->Csep = c;
+ return (getadr(p, prt));
+ case ',':
+ (void) mygetc();
+ p->Csep = c;
+ return (getadr(p, prt));
+ }
+
+ return (0);
+}
+
+static int
+getadr(struct Comd *p, int prt)
+{
+ int r;
+ char c;
+
+ r = 0;
+ while (peekc() == ' ')
+ (void) mygetc(); /* Ignore leading spaces */
+ switch (c = peekc()) {
+ case '\n':
+ case ',':
+ case ';': return (0);
+ case '\'': (void) mygetc();
+ r = getmark(p, prt);
+ break;
+
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9': r = getnumb(p, prt);
+ break;
+ case '.': (void) mygetc();
+ p->Cadr[++p->Cnumadr] = Dot;
+ break;
+ case '+':
+ case '-': p->Cadr[++p->Cnumadr] = Dot;
+ break;
+ case '$': (void) mygetc();
+ p->Cadr[++p->Cnumadr] = Dollar;
+ break;
+ case '^': (void) mygetc();
+ p->Cadr[++p->Cnumadr] = Dot - 1;
+ break;
+ case '/':
+ case '?':
+ case '>':
+ case '<': (void) mygetc();
+ r = getrex(p, prt, c);
+ break;
+ default: return (0);
+ }
+
+ if (r == 0)
+ r = getrel(p, prt);
+ return (r);
+}
+
+static int
+getnumb(struct Comd *p, int prt)
+{
+ int i;
+
+ if ((i = rdnumb(prt)) < 0)
+ return (-1);
+ p->Cadr[++p->Cnumadr] = i;
+ return (0);
+}
+
+static int
+rdnumb(int prt)
+{
+ char num[20], *n;
+ int i;
+
+ n = num;
+ while ((*n = peekc()) >= '0' && *n <= '9') {
+ n++;
+ (void) mygetc();
+ }
+
+ *n = '\0';
+ if ((i = patoi(num)) >= 0)
+ return (i);
+ return (err(prt, "bad num"));
+}
+
+static int
+getrel(struct Comd *p, int prt)
+{
+ int op, n;
+ char c;
+ int j;
+
+ n = 0;
+ op = 1;
+ while ((c = peekc()) == '+' || c == '-') {
+ if (c == '+')
+ n++;
+ else
+ n--;
+ (void) mygetc();
+ }
+ j = n;
+ if (n < 0)
+ op = -1;
+ if (c == '\n')
+ p->Cadr[p->Cnumadr] += n;
+ else {
+ if ((n = rdnumb(0)) > 0 && p->Cnumadr >= 0) {
+ p->Cadr[p->Cnumadr] += op*n;
+ (void) getrel(p, prt);
+ } else {
+ p->Cadr[p->Cnumadr] += j;
+ }
+ }
+ return (0);
+}
+
+static int
+getmark(struct Comd *p, int prt)
+{
+ char c;
+
+ if ((c = peekc()) < 'a' || c > 'z')
+ return (err(prt, "bad mark"));
+ (void) mygetc();
+
+ if (!mark[c])
+ return (err(prt, "undefined mark"));
+ p->Cadr[++p->Cnumadr] = mark[c];
+ return (0);
+}
+
+static int
+getrex(struct Comd *p, int prt, char c)
+{
+ int down, wrap, start;
+
+ if (peekc() == c)
+ (void) mygetc();
+ else if (getstr(prt, currex, c, 0, 1))
+ return (-1);
+
+ switch (c) {
+ case '/': down = 1; wrap = 1; break;
+ case '?': down = 0; wrap = 1; break;
+ case '>': down = 1; wrap = 0; break;
+ case '<': down = 0; wrap = 0; break;
+ }
+
+ if (p->Csep == ';')
+ start = p->Cadr[0];
+ else
+ start = Dot;
+
+ if ((p->Cadr[++p->Cnumadr] = hunt(prt, currex, start, down, wrap, 0))
+ < 0)
+ return (-1);
+ return (0);
+}
+
+static int
+hunt(int prt, char rex[], int start, int down, int wrap, int errsok)
+{
+ int i, end1, incr;
+ int start1, start2;
+ char line[BFSBUF];
+
+ if (down) {
+ start1 = start + 1;
+ end1 = Dollar;
+ start2 = 1;
+ incr = 1;
+ } else {
+ start1 = start - 1;
+ end1 = 1;
+ start2 = Dollar;
+ incr = -1;
+ }
+
+ rebuf = compile(rex, (char *)0, (char *)0);
+ if (regerrno)
+ (void) regerr(regerrno);
+ else
+ if (rebuf)
+ free(rebuf);
+
+ for (i = start1; i != end1+incr; i += incr) {
+ bigread(i, line);
+ if (step(line, rebuf)) {
+ return (i);
+ }
+ }
+
+ if (!wrap)
+ return (errsok?-1:err(prt, "not found"));
+
+ for (i = start2; i != start1; i += incr) {
+ bigread(i, line);
+ if (step(line, rebuf)) {
+ return (i);
+ }
+ }
+
+ return (errsok?-1:err(prt, "not found"));
+}
+
+static int
+jump(int prt, char label[])
+{
+ char *l;
+ char line[256];
+
+ if (infildes == 0 && tty)
+ return (err(prt, "jump on tty"));
+ if (infildes == 100)
+ intptr = internal;
+ else
+ (void) lseek(infildes, 0L, 0);
+
+ (void) snprintf(strtmp,
+ sizeof (strtmp) * sizeof (char), "^: *%s$", label);
+ rebuf = compile(strtmp, (char *)0, (char *)0);
+ if (regerrno) {
+ (void) regerr(regerrno);
+ return (-1);
+ }
+
+ for (l = line; readc(infildes, l); l++) {
+ if (*l == '\n') {
+ *l = '\0';
+ if (step(line, rebuf)) {
+ charbuf = '\n';
+ return (peeked = 0);
+ }
+ l = line - 1;
+ }
+ }
+
+ return (err(prt, "label not found"));
+}
+
+static int
+getstr(int prt, char buf[], char brk, char ignr, int nonl)
+{
+ char *b, c, prevc;
+
+ prevc = 0;
+ for (b = buf; c = peekc(); prevc = c) {
+ if (c == '\n') {
+ if (prevc == '\\' && (!flag3)) *(b-1) = mygetc();
+ else if (prevc == '\\' && flag3) {
+ *b++ = mygetc();
+ } else if (nonl)
+ break;
+ else
+ return (*b = '\0');
+ } else {
+ (void) mygetc();
+ if (c == brk) {
+ if (prevc == '\\') *(b-1) = c;
+ else return (*b = '\0');
+ } else if (b != buf || c != ignr) *b++ = c;
+ }
+ }
+ return (err(prt, "syntax"));
+}
+
+static int
+regerr(int c)
+{
+ if (prompt) {
+ switch (c) {
+ case 11: (void) printf("Range endpoint too large.\n");
+ break;
+ case 16: (void) printf("Bad number.\n");
+ break;
+ case 25: (void) printf("``\\digit'' out of range.\n");
+ break;
+ case 41: (void) printf("No remembered search string.\n");
+ break;
+ case 42: (void) printf("() imbalance.\n");
+ break;
+ case 43: (void) printf("Too many (.\n");
+ break;
+ case 44: (void) printf("More than 2 numbers given in { }.\n");
+ break;
+ case 45: (void) printf("} expected after \\.\n");
+ break;
+ case 46: (void) printf("First number exceeds second in { }.\n");
+ break;
+ case 49: (void) printf("[] imbalance.\n");
+ break;
+ case 50: (void) printf("Regular expression overflow.\n");
+ break;
+ case 67: (void) printf("Illegal byte sequence.\n");
+ break;
+ default: (void) printf("RE error.\n");
+ break;
+ }
+ } else {
+ (void) printf("?\n");
+ }
+ return (-1);
+}
+
+static int
+err(int prt, char msg[])
+{
+ if (prt) (prompt? (void) printf("%s\n", msg): (void) printf("?\n"));
+ if (infildes != 0) {
+ infildes = pop(fstack);
+ charbuf = '\n';
+ peeked = 0;
+ flag3 = 0;
+ flag2 = 0;
+ flag = 0;
+ }
+ return (-1);
+}
+
+static char
+mygetc()
+{
+ if (!peeked) {
+ while ((!(infildes == oldfd && flag)) && (!flag1) &&
+ (!readc(infildes, &charbuf))) {
+ if (infildes == 100 && (!flag)) flag1 = 1;
+ if ((infildes = pop(fstack)) == -1) quit();
+ if ((!flag1) && infildes == 0 && flag3 && prompt)
+ (void) printf("*");
+ }
+ if (infildes == oldfd && flag) flag2 = 0;
+ flag1 = 0;
+ } else peeked = 0;
+ return (charbuf);
+}
+
+static int
+readc(int f, char *c)
+{
+ if (f == 100) {
+ if (!(*c = *intptr++)) {
+ intptr--;
+ charbuf = '\n';
+ return (0);
+ }
+ } else if (read(f, c, 1) != 1) {
+ (void) close(f);
+ charbuf = '\n';
+ return (0);
+ }
+ return (1);
+}
+
+static int
+percent(char line[256])
+{
+ char *lp, *var;
+ char *front, *per, c[2], *olp, p[2], fr[256];
+ int i, j;
+
+ per = p;
+ var = c;
+ front = fr;
+ j = 0;
+ while (!j) {
+ j = 1;
+ olp = line;
+ intptr = internal;
+ while (step(olp, perbuf)) {
+ while (loc1 < loc2) *front++ = *loc1++;
+ *(--front) = '\0';
+ front = fr;
+ *per++ = '%';
+ *per = '\0';
+ per = p;
+ *var = *loc2;
+ if ((i = 1 + strlen(front)) >= 2 && fr[i-2] == '\\') {
+ (void) strcat(front, "");
+ --intptr;
+ (void) strcat(per, "");
+ } else {
+ if (!(*var >= '0' && *var <= '9'))
+ return (err(1, "usage: %digit"));
+ (void) strcat(front, "");
+ (void) strcat(varray[*var-'0'], "");
+ j = 0;
+ loc2++; /* Compensate for removing --lp above */
+ }
+ olp = loc2;
+ }
+ (void) strcat(olp, "");
+ *intptr = '\0';
+ if (!j) {
+ intptr = internal;
+ lp = line;
+ (void)
+ strncpy(intptr, lp, sizeof (intptr)*sizeof (char));
+ }
+ }
+ return (0);
+}
+
+static int
+newfile(int prt, char f[])
+{
+ int fd;
+
+ if (!*f) {
+ if (flag != 0) {
+ oldfd = infildes;
+ intptr = comdlist;
+ } else intptr = internal;
+ fd = 100;
+ } else if ((fd = open(f, 0)) < 0) {
+ (void) snprintf(strtmp, sizeof (strtmp) * sizeof (char),
+ "cannot open %s", f);
+ return (err(prt, strtmp));
+ }
+
+ push(fstack, infildes);
+ if (flag4) oldfd = fd;
+ infildes = fd;
+ return (peeked = 0);
+}
+
+static void
+push(int s[], int d)
+{
+ s[++s[0]] = d;
+}
+
+static int
+pop(int s[])
+{
+ return (s[s[0]--]);
+}
+
+static int
+peekc()
+{
+ int c;
+
+ c = mygetc();
+ peeked = 1;
+
+ return (c);
+}
+
+static void
+eat()
+{
+ if (charbuf != '\n')
+ while (mygetc() != '\n');
+ peeked = 0;
+}
+
+static int
+more()
+{
+ if (mygetc() != '\n')
+ return (err(1, "syntax"));
+ return (0);
+}
+
+static void
+quit()
+{
+ exit(0);
+}
+
+static void
+out(char *ln)
+{
+ char *rp, *wp, prev;
+ int w, width;
+ char *oldrp;
+ wchar_t cl;
+ int p;
+ ptrdiff_t lim;
+ if (crunch > 0) {
+
+ ln = untab(ln);
+ rp = wp = ln - 1;
+ prev = ' ';
+
+ while (*++rp) {
+ if (prev != ' ' || *rp != ' ')
+ *++wp = *rp;
+ prev = *rp;
+ }
+ *++wp = '\n';
+ lim = (ptrdiff_t)wp - (ptrdiff_t)ln;
+ *++wp = '\0';
+
+ if (*ln == '\n')
+ return;
+ } else
+ ln[lim = strlen(ln)] = '\n';
+
+ if (MB_CUR_MAX <= 1) {
+ if (lim > trunc)
+ ln[lim = trunc] = '\n';
+ } else {
+ if ((trunc < (BFSBUF -1)) || (lim > trunc)) {
+ w = 0;
+ oldrp = rp = ln;
+ /*CONSTCOND*/while (1) {
+ if ((p = mbtowc(&cl, rp, MB_LEN_MAX)) == 0) {
+ break;
+ }
+ if (p == -1) {
+ width = p = 1;
+ } else {
+ width = scrwidth(cl);
+ if (width == 0)
+ width = 1;
+ }
+ if ((w += width) > trunc)
+ break;
+ rp += p;
+ }
+ *rp = '\n';
+ lim = (ptrdiff_t)rp - (ptrdiff_t)oldrp;
+ }
+ }
+
+ outcnt += write(outfildes, ln, lim+1);
+}
+
+static char *
+untab(char l[])
+{
+ static char line[BFSBUF];
+ char *q, *s;
+
+ s = l;
+ q = line;
+ do {
+ if (*s == '\t')
+ do
+ *q++ = ' ';
+ while (((ptrdiff_t)q-(ptrdiff_t)line)%8);
+ else *q++ = *s;
+ } while (*s++);
+ return (line);
+}
+
+/*
+ * Function to convert ascii string to integer. Converts
+ * positive numbers only. Returns -1 if non-numeric
+ * character encountered.
+ */
+
+static int
+patoi(char *b)
+{
+ int i;
+ char *a;
+
+ a = b;
+ i = 0;
+ while (*a >= '0' && *a <= '9') i = 10 * i + *a++ - '0';
+
+ if (*a)
+ return (-1);
+ return (i);
+}
+
+/*
+ * Compares 2 strings. Returns 1 if equal, 0 if not.
+ */
+
+static int
+equal(char *a, char *b)
+{
+ char *x, *y;
+
+ x = a;
+ y = b;
+ while (*x == *y++)
+ if (*x++ == 0)
+ return (1);
+ return (0);
+}