diff options
Diffstat (limited to 'text-utils')
-rw-r--r-- | text-utils/Makefile | 79 | ||||
-rw-r--r-- | text-utils/README.col | 48 | ||||
-rw-r--r-- | text-utils/col.1 | 126 | ||||
-rw-r--r-- | text-utils/col.c | 529 | ||||
-rw-r--r-- | text-utils/colcrt.1 | 108 | ||||
-rw-r--r-- | text-utils/colcrt.c | 251 | ||||
-rw-r--r-- | text-utils/colrm.1 | 63 | ||||
-rw-r--r-- | text-utils/colrm.c | 126 | ||||
-rw-r--r-- | text-utils/column.1 | 99 | ||||
-rw-r--r-- | text-utils/column.c | 311 | ||||
-rw-r--r-- | text-utils/conv.c | 124 | ||||
-rw-r--r-- | text-utils/display.c | 364 | ||||
-rw-r--r-- | text-utils/hexdump.1 | 324 | ||||
-rw-r--r-- | text-utils/hexdump.c | 79 | ||||
-rw-r--r-- | text-utils/hexdump.h | 76 | ||||
-rw-r--r-- | text-utils/hexsyntax.c | 130 | ||||
-rw-r--r-- | text-utils/more.1 | 196 | ||||
-rw-r--r-- | text-utils/more.c | 1832 | ||||
-rw-r--r-- | text-utils/more.help | 24 | ||||
-rw-r--r-- | text-utils/od.1 | 76 | ||||
-rw-r--r-- | text-utils/odsyntax.c | 255 | ||||
-rw-r--r-- | text-utils/parse.c | 511 | ||||
-rw-r--r-- | text-utils/rev.1 | 51 | ||||
-rw-r--r-- | text-utils/rev.c | 159 | ||||
-rw-r--r-- | text-utils/strings.1 | 96 | ||||
-rw-r--r-- | text-utils/strings.c | 222 | ||||
-rw-r--r-- | text-utils/ul.1 | 107 | ||||
-rw-r--r-- | text-utils/ul.c | 508 |
28 files changed, 6874 insertions, 0 deletions
diff --git a/text-utils/Makefile b/text-utils/Makefile new file mode 100644 index 000000000..40e8d118e --- /dev/null +++ b/text-utils/Makefile @@ -0,0 +1,79 @@ +# Makefile -- Makefile for util-linux Linux utilities +# Created: Sat Dec 26 20:09:40 1992 +# Revised: Sun Feb 26 16:55:46 1995 by faith@cs.unc.edu +# Copyright 1992, 1993, 1994, 1995 Rickard E. Faith (faith@cs.unc.edu) +# + +include ../MCONFIG + +# Where to put man pages? + +MAN1= col.1 colcrt.1 colrm.1 column.1 hexdump.1 more.1 rev.1 \ + ul.1 + +ifeq "$(HAVE_STRINGS)" "no" +MAN1:=$(MAN1) strings.1 +endif + +# Where to put binaries? +# See the "install" rule for the links. . . + +BIN= more + +USRBIN= col colcrt colrm column hexdump rev ul + +ifeq "$(HAVE_STRINGS)" "no" +USRBIN:=$(USRBIN) strings +endif + +# Where to put datebase files? + +USRLIB= more.help + +# Programs requiring special compilation + +NEEDS_TERMCAP= more ul + +all: $(BIN) $(USRBIN) + +%.o: %.c + $(CC) -c $(CFLAGS) $< -o $@ + +$(NEEDS_TERMCAP): + $(CC) $(LDFLAGS) $^ -o $@ -ltermcap + +# Rules for hexdump + +hexdump: hexdump.o conv.o display.o hexsyntax.o odsyntax.o parse.o \ + $(BSD)/getopt.o +hexdump.o: hexdump.c hexdump.h +conv.o: conv.c hexdump.h +display.o: display.c hexdump.h +hexsyntax.o: hexsyntax.c hexdump.h +odsyntax.o: odsyntax.c hexdump.h +parse.o: parse.c hexdump.h + +# Rules for everything else + +col: col.o $(BSD)/getopt.o +colcrt: colcrt.o +colrm: colrm.o +column: column.o $(BSD)/err.o +more.o: more.c $(BSD)/pathnames.h +more: more.o +rev: rev.o +strings: strings.o $(BSD)/getopt.o +ul: ul.o + +install install.shadow install.text-utils: all + install -d -m 755 /bin /usr/bin /usr/lib /usr/man/man1 + install -m 755 $(BIN) /bin + install -m 755 $(USRBIN) /usr/bin + install -m 644 $(USRLIB) /usr/lib + install -m 644 $(MAN1) /usr/man/man1 + +.PHONY: clean distclean +clean: + -rm -f *.o *~ core $(BIN) $(USRBIN) + +distclean: clean diff --git a/text-utils/README.col b/text-utils/README.col new file mode 100644 index 000000000..2a7dd6ca4 --- /dev/null +++ b/text-utils/README.col @@ -0,0 +1,48 @@ +# @(#)README 5.1 (Berkeley) 5/22/90 + +col - filter out reverse line feeds. + +Options are: + -b do not print any backspaces (last character written is printed) + -f allow half line feeds in output, by default characters between + lines are pushed to the line below + -x do not compress spaces into tabs. + -l num keep (at least) num lines in memory, 128 are kept by default + +In the 32V source code to col(1) the default behavior was to NOT compress +spaces into tabs. There was a -h option which caused it to compress spaces +into tabs. There was no -x flag. + +The 32V documentation, however, was consistent with the SVID (actually, V7 +at the time) and documented a -x flag (as defined above) while making no +mention of a -h flag. Just before 4.3BSD went out, CSRG updated the manual +page to reflect the way the code worked. Suspecting that this was probably +the wrong way to go, this version adopts the SVID defaults, and no longer +documents the -h option. + +The S5 -p flag is not supported because it isn't clear what it does (looks +like a kludge introduced for a particular printer). + +Known differences between AT&T's col and this one (# is delimiter): + Input AT&T col this col + #\nabc\E7def\n# # def\nabc\r# # def\nabc\n# + #a# ## #a\n# + - last line always ends with at least one \n (or \E9) + #1234567 8\n# #1234567\t8\n# #1234567 8\n# + - single space not expanded to tab + -f #a\E8b\n# #ab\n# # b\E9\ra\n# + - can back up past first line (as far as you want) so you + *can* have a super script on the first line + #\E9_\ba\E8\nb\n# #\n_\bb\ba\n# #\n_\ba\bb\n# + - always print last character written to a position, + AT&T col claims to do this but doesn't. + +If a character is to be placed on a line that has been flushed, a warning +is produced (the AT&T col is silent). The -l flag (not in AT&T col) can +be used to increase the number of lines buffered to avoid the problem. + +General algorithm: a limited number of lines are buffered in a linked +list. When a printable character is read, it is put in the buffer of +the current line along with the column it's supposed to be in. When +a line is flushed, the characters in the line are sorted according to +column and then printed. diff --git a/text-utils/col.1 b/text-utils/col.1 new file mode 100644 index 000000000..1bf985277 --- /dev/null +++ b/text-utils/col.1 @@ -0,0 +1,126 @@ +.\" Copyright (c) 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" Michael Rendell. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)col.1 6.8 (Berkeley) 6/17/91 +.\" +.Dd June 17, 1991 +.Dt COL 1 +.Os +.Sh NAME +.Nm col +.Nd filter reverse line feeds from input +.Sh SYNOPSIS +.Nm col +.Op Fl bfx +.Op Fl l Ar num +.Sh DESCRIPTION +.Nm Col +filters out reverse (and half reverse) line feeds so the output is +in the correct order with only forward and half forward line +feeds, and replaces white-space characters with tabs where possible. +This can be useful in processing the output of +.Xr nroff 1 +and +.Xr tbl 1 . +.Pp +.Nm Col +reads from standard input and writes to standard output. +.Pp +The options are as follows: +.Bl -tag -width "-lnum" +.It Fl b +Do not output any backspaces, printing only the last character +written to each column position. +.It Fl f +Forward half line feeds are permitted (``fine'' mode). +Normally characters printed on a half line boundary are printed +on the following line. +.It Fl x +Output multiple spaces instead of tabs. +.It Fl l Ns Ar num +Buffer at least +.Ar num +lines in memory. +By default, 128 lines are buffered. +.El +.Pp +The control sequences for carriage motion that +.Nm col +understands and their decimal values are listed in the following +table: +.Pp +.Bl -tag -width "carriage return" -compact +.It ESC\-7 +reverse line feed (escape then 7) +.It ESC\-8 +half reverse line feed (escape then 8) +.It ESC\-9 +half forward line feed (escape then 9) +.It backspace +moves back one column (8); ignored in the first column +.It carriage return +(13) +.It newline +forward line feed (10); also does carriage return +.It shift in +shift to normal character set (15) +.It shift out +shift to alternate character set (14) +.It space +moves forward one column (32) +.It tab +moves forward to next tab stop (9) +.It vertical tab +reverse line feed (11) +.El +.Pp +All unrecognized control characters and escape sequences are +discarded. +.Pp +.Nm Col +keeps track of the character set as characters are read and makes +sure the character set is correct when they are output. +.Pp +If the input attempts to back up to the last flushed line, +.Nm col +will display a warning message. +.Sh SEE ALSO +.Xr expand 1 , +.Xr nroff 1 , +.Xr tbl 1 +.Sh HISTORY +A +.Nm col +command +appeared in Version 6 AT&T UNIX. diff --git a/text-utils/col.c b/text-utils/col.c new file mode 100644 index 000000000..8be274e03 --- /dev/null +++ b/text-utils/col.c @@ -0,0 +1,529 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Michael Rendell of the Memorial University of Newfoundland. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Wed Jun 22 22:15:41 1994, faith@cs.unc.edu: Added internationalization + * patches from Andries.Brouwer@cwi.nl + * Wed Sep 14 22:31:17 1994: patches from Carl Christofferson + * (cchris@connected.com) + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1990 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)col.c 5.3 (Berkeley) 2/2/91"; +#endif /* not lint */ + +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <stdio.h> +#include <locale.h> + +#define BS '\b' /* backspace */ +#define TAB '\t' /* tab */ +#define SPACE ' ' /* space */ +#define NL '\n' /* newline */ +#define CR '\r' /* carriage return */ +#define ESC '\033' /* escape */ +#define SI '\017' /* shift in to normal character set */ +#define SO '\016' /* shift out to alternate character set */ +#define VT '\013' /* vertical tab (aka reverse line feed) */ +#define RLF '\007' /* ESC-07 reverse line feed */ +#define RHLF '\010' /* ESC-010 reverse half-line feed */ +#define FHLF '\011' /* ESC-011 forward half-line feed */ + +/* build up at least this many lines before flushing them out */ +#define BUFFER_MARGIN 32 + +typedef char CSET; + +typedef struct char_str { +#define CS_NORMAL 1 +#define CS_ALTERNATE 2 + short c_column; /* column character is in */ + CSET c_set; /* character set (currently only 2) */ + char c_char; /* character in question */ +} CHAR; + +typedef struct line_str LINE; +struct line_str { + CHAR *l_line; /* characters on the line */ + LINE *l_prev; /* previous line */ + LINE *l_next; /* next line */ + int l_lsize; /* allocated sizeof l_line */ + int l_line_len; /* strlen(l_line) */ + int l_needs_sort; /* set if chars went in out of order */ + int l_max_col; /* max column in the line */ +}; + +LINE *alloc_line(); +void *xmalloc(); + +CSET last_set; /* char_set of last char printed */ +LINE *lines; +int compress_spaces; /* if doing space -> tab conversion */ +int fine; /* if `fine' resolution (half lines) */ +int max_bufd_lines; /* max # lines to keep in memory */ +int nblank_lines; /* # blanks after last flushed line */ +int no_backspaces; /* if not to output any backspaces */ + +#define PUTC(ch) \ + if (putchar(ch) == EOF) \ + wrerr(); + +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + extern char *optarg; + register int ch; + CHAR *c; + CSET cur_set; /* current character set */ + LINE *l; /* current line */ + int extra_lines; /* # of lines above first line */ + int cur_col; /* current column */ + int cur_line; /* line number of current position */ + int max_line; /* max value of cur_line */ + int this_line; /* line l points to */ + int nflushd_lines; /* number of lines that were flushed */ + int adjust, opt, warned; + + /* we discard characters that do not pass isgraph() */ + setlocale(LC_CTYPE, ""); + + max_bufd_lines = 128; + compress_spaces = 1; /* compress spaces into tabs */ + while ((opt = getopt(argc, argv, "bfhl:x")) != EOF) + switch (opt) { + case 'b': /* do not output backspaces */ + no_backspaces = 1; + break; + case 'f': /* allow half forward line feeds */ + fine = 1; + break; + case 'h': /* compress spaces into tabs */ + compress_spaces = 1; + break; + case 'l': /* buffered line count */ + if ((max_bufd_lines = atoi(optarg)) <= 0) { + (void)fprintf(stderr, + "col: bad -l argument %s.\n", optarg); + exit(1); + } + break; + case 'x': /* do not compress spaces into tabs */ + compress_spaces = 0; + break; + case '?': + default: + usage(); + } + + if (optind != argc) + usage(); + + /* this value is in half lines */ + max_bufd_lines *= 2; + + adjust = cur_col = extra_lines = warned = 0; + cur_line = max_line = nflushd_lines = this_line = 0; + cur_set = last_set = CS_NORMAL; + lines = l = alloc_line(); + + while ((ch = getchar()) != EOF) { + if (!isgraph(ch)) { + switch (ch) { + case BS: /* can't go back further */ + if (cur_col == 0) + continue; + --cur_col; + continue; + case CR: + cur_col = 0; + continue; + case ESC: /* just ignore EOF */ + switch(getchar()) { + case RLF: + cur_line -= 2; + break; + case RHLF: + cur_line--; + break; + case FHLF: + cur_line++; + if (cur_line > max_line) + max_line = cur_line; + } + continue; + case NL: + cur_line += 2; + if (cur_line > max_line) + max_line = cur_line; + cur_col = 0; + continue; + case SPACE: + ++cur_col; + continue; + case SI: + cur_set = CS_NORMAL; + continue; + case SO: + cur_set = CS_ALTERNATE; + continue; + case TAB: /* adjust column */ + cur_col |= 7; + ++cur_col; + continue; + case VT: + cur_line -= 2; + continue; + } + continue; + } + + /* Must stuff ch in a line - are we at the right one? */ + if (cur_line != this_line - adjust) { + LINE *lnew; + int nmove; + + adjust = 0; + nmove = cur_line - this_line; + if (!fine) { + /* round up to next line */ + if (cur_line & 1) { + adjust = 1; + nmove++; + } + } + if (nmove < 0) { + for (; nmove < 0 && l->l_prev; nmove++) + l = l->l_prev; + if (nmove) { + if (nflushd_lines == 0) { + /* + * Allow backup past first + * line if nothing has been + * flushed yet. + */ + for (; nmove < 0; nmove++) { + lnew = alloc_line(); + l->l_prev = lnew; + lnew->l_next = l; + l = lines = lnew; + extra_lines++; + } + } else { + if (!warned++) + warn(cur_line); + cur_line -= nmove; + } + } + } else { + /* may need to allocate here */ + for (; nmove > 0 && l->l_next; nmove--) + l = l->l_next; + for (; nmove > 0; nmove--) { + lnew = alloc_line(); + lnew->l_prev = l; + l->l_next = lnew; + l = lnew; + } + } + this_line = cur_line + adjust; + nmove = this_line - nflushd_lines; + if (nmove >= max_bufd_lines + BUFFER_MARGIN) { + nflushd_lines += nmove - max_bufd_lines; + flush_lines(nmove - max_bufd_lines); + } + } + /* grow line's buffer? */ + if (l->l_line_len + 1 >= l->l_lsize) { + int need; + + need = l->l_lsize ? l->l_lsize * 2 : 90; + l->l_line = (CHAR *)xmalloc((void *) l->l_line, + (unsigned) need * sizeof(CHAR)); + l->l_lsize = need; + } + c = &l->l_line[l->l_line_len++]; + c->c_char = ch; + c->c_set = cur_set; + c->c_column = cur_col; + /* + * If things are put in out of order, they will need sorting + * when it is flushed. + */ + if (cur_col < l->l_max_col) + l->l_needs_sort = 1; + else + l->l_max_col = cur_col; + cur_col++; + } + /* goto the last line that had a character on it */ + for (; l->l_next; l = l->l_next) + this_line++; + flush_lines(this_line - nflushd_lines + extra_lines + 1); + + /* make sure we leave things in a sane state */ + if (last_set != CS_NORMAL) + PUTC('\017'); + + /* flush out the last few blank lines */ + nblank_lines = max_line - this_line; + if (max_line & 1) + nblank_lines++; + else if (!nblank_lines) + /* missing a \n on the last line? */ + nblank_lines = 2; + flush_blanks(); + exit(0); +} + +flush_lines(nflush) + int nflush; +{ + LINE *l; + + while (--nflush >= 0) { + l = lines; + lines = l->l_next; + if (l->l_line) { + flush_blanks(); + flush_line(l); + } + nblank_lines++; + if (l->l_line) + (void)free((void *)l->l_line); + free_line(l); + } + if (lines) + lines->l_prev = NULL; +} + +/* + * Print a number of newline/half newlines. If fine flag is set, nblank_lines + * is the number of half line feeds, otherwise it is the number of whole line + * feeds. + */ +flush_blanks() +{ + int half, i, nb; + + half = 0; + nb = nblank_lines; + if (nb & 1) { + if (fine) + half = 1; + else + nb++; + } + nb /= 2; + for (i = nb; --i >= 0;) + PUTC('\n'); + if (half) { + PUTC('\033'); + PUTC('9'); + if (!nb) + PUTC('\r'); + } + nblank_lines = 0; +} + +/* + * Write a line to stdout taking care of space to tab conversion (-h flag) + * and character set shifts. + */ +flush_line(l) + LINE *l; +{ + CHAR *c, *endc; + int nchars, last_col, this_col; + + last_col = 0; + nchars = l->l_line_len; + + if (l->l_needs_sort) { + static CHAR *sorted; + static int count_size, *count, i, save, sorted_size, tot; + + /* + * Do an O(n) sort on l->l_line by column being careful to + * preserve the order of characters in the same column. + */ + if (l->l_lsize > sorted_size) { + sorted_size = l->l_lsize; + sorted = (CHAR *)xmalloc((void *)sorted, + (unsigned)sizeof(CHAR) * sorted_size); + } + if (l->l_max_col >= count_size) { + count_size = l->l_max_col + 1; + count = (int *)xmalloc((void *)count, + (unsigned)sizeof(int) * count_size); + } + bzero((char *)count, sizeof(int) * l->l_max_col + 1); + for (i = nchars, c = l->l_line; --i >= 0; c++) + count[c->c_column]++; + + /* + * calculate running total (shifted down by 1) to use as + * indices into new line. + */ + for (tot = 0, i = 0; i <= l->l_max_col; i++) { + save = count[i]; + count[i] = tot; + tot += save; + } + + for (i = nchars, c = l->l_line; --i >= 0; c++) + sorted[count[c->c_column]++] = *c; + c = sorted; + } else + c = l->l_line; + while (nchars > 0) { + this_col = c->c_column; + endc = c; + do { + ++endc; + } while (--nchars > 0 && this_col == endc->c_column); + + /* if -b only print last character */ + if (no_backspaces) + c = endc - 1; + + if (this_col > last_col) { + int nspace = this_col - last_col; + + if (compress_spaces && nspace > 1) { + int ntabs; + + ntabs = this_col / 8 - last_col / 8; + if (ntabs > 0) { + nspace = this_col & 7; + while (--ntabs >= 0) + PUTC('\t'); + } + } + while (--nspace >= 0) + PUTC(' '); + last_col = this_col; + } + last_col++; + + for (;;) { + if (c->c_set != last_set) { + switch (c->c_set) { + case CS_NORMAL: + PUTC('\017'); + break; + case CS_ALTERNATE: + PUTC('\016'); + } + last_set = c->c_set; + } + PUTC(c->c_char); + if (++c >= endc) + break; + PUTC('\b'); + } + } +} + +#define NALLOC 64 + +static LINE *line_freelist; + +LINE * +alloc_line() +{ + LINE *l; + int i; + + if (!line_freelist) { + l = (LINE *)xmalloc((void *)NULL, sizeof(LINE) * NALLOC); + line_freelist = l; + for (i = 1; i < NALLOC; i++, l++) + l->l_next = l + 1; + l->l_next = NULL; + } + l = line_freelist; + line_freelist = l->l_next; + + bzero(l, sizeof(LINE)); + return(l); +} + +free_line(l) + LINE *l; +{ + l->l_next = line_freelist; + line_freelist = l; +} + +void * +xmalloc(p, size) + void *p; + size_t size; +{ + if (!(p = (void *)realloc(p, size))) { + (void)fprintf(stderr, "col: %s.\n", strerror(ENOMEM)); + exit(1); + } + return(p); +} + +usage() +{ + (void)fprintf(stderr, "usage: col [-bfx] [-l nline]\n"); + exit(1); +} + +wrerr() +{ + (void)fprintf(stderr, "col: write error.\n"); + exit(1); +} + +warn(line) + int line; +{ + (void)fprintf(stderr, + "col: warning: can't back up %s.\n", line < 0 ? + "past first line" : "-- line already flushed"); +} diff --git a/text-utils/colcrt.1 b/text-utils/colcrt.1 new file mode 100644 index 000000000..a9447af61 --- /dev/null +++ b/text-utils/colcrt.1 @@ -0,0 +1,108 @@ +.\" Copyright (c) 1980, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)colcrt.1 8.1 (Berkeley) 6/30/93 +.\" +.Dd June 30, 1993 +.Dt COLCRT 1 +.Os BSD 3 +.Sh NAME +.Nm colcrt +.Nd filter nroff output for CRT previewing +.Sh SYNOPSIS +.Nm colcrt +.Op Fl +.Op Fl \&2 +.Op Ar +.Sh DESCRIPTION +.Nm Colcrt +provides virtual half-line and reverse line feed sequences +for terminals without such capability, and on which overstriking +is destructive. +Half-line characters and underlining (changed to dashing `\-') +are placed on new lines in between the normal output lines. +.Pp +Available options: +.Bl -tag -width Ds +.It Fl +Suppress all underlining. +This option is especially useful for previewing +.Em allboxed +tables from +.Xr tbl 1 . +.It Fl 2 +Causes all half-lines to be printed, effectively double spacing the output. +Normally, a minimal space output format is used which will suppress empty +lines. +The program never suppresses two consecutive empty lines, however. +The +.Fl 2 +option is useful for sending output to the line printer when the output +contains superscripts and subscripts which would otherwise be invisible. +.El +.Sh EXAMPLES +A typical use of +.Nm colcrt +would be +.Bd -literal +tbl exum2.n \&| nroff \-ms \&| colcrt \- \&| more +.Ed +.Sh SEE ALSO +.Xr nroff 1 , +.Xr troff 1 , +.Xr col 1 , +.Xr more 1 , +.Xr ul 1 +.Sh BUGS +Should fold underlines onto blanks even with the +.Ql Fl +option so that +a true underline character would show. +.Pp +Can't back up more than 102 lines. +.Pp +General overstriking is lost; +as a special case +.Ql \&| +overstruck with +.Ql \- +or underline becomes +.Ql \&+ . +.Pp +Lines are trimmed to 132 characters. +.Pp +Some provision should be made for processing superscripts and subscripts +in documents which are already double-spaced. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/text-utils/colcrt.c b/text-utils/colcrt.c new file mode 100644 index 000000000..9e6136b56 --- /dev/null +++ b/text-utils/colcrt.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)colcrt.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> +/* + * colcrt - replaces col for crts with new nroff esp. when using tbl. + * Bill Joy UCB July 14, 1977 + * + * This filter uses a screen buffer, 267 half-lines by 132 columns. + * It interprets the up and down sequences generated by the new + * nroff when used with tbl and by \u \d and \r. + * General overstriking doesn't work correctly. + * Underlining is split onto multiple lines, etc. + * + * Option - suppresses all underlining. + * Option -2 forces printing of all half lines. + */ + +char page[267][132]; + +int outline = 1; +int outcol; + +char suppresul; +char printall; + +char *progname; +FILE *f; + +main(argc, argv) + int argc; + char *argv[]; +{ + register c; + register char *cp, *dp; + + argc--; + progname = *argv++; + while (argc > 0 && argv[0][0] == '-') { + switch (argv[0][1]) { + case 0: + suppresul = 1; + break; + case '2': + printall = 1; + break; + default: + printf("usage: %s [ - ] [ -2 ] [ file ... ]\n", progname); + fflush(stdout); + exit(1); + } + argc--; + argv++; + } + do { + if (argc > 0) { + close(0); + if (!(f = fopen(argv[0], "r"))) { + fflush(stdout); + perror(argv[0]); + exit (1); + } + argc--; + argv++; + } + for (;;) { + c = getc(stdin); + if (c == -1) { + pflush(outline); + fflush(stdout); + break; + } + switch (c) { + case '\n': + if (outline >= 265) + pflush(62); + outline += 2; + outcol = 0; + continue; + case '\016': + case '\017': + continue; + case 033: + c = getc(stdin); + switch (c) { + case '9': + if (outline >= 266) + pflush(62); + outline++; + continue; + case '8': + if (outline >= 1) + outline--; + continue; + case '7': + outline -= 2; + if (outline < 0) + outline = 0; + continue; + default: + continue; + } + case '\b': + if (outcol) + outcol--; + continue; + case '\t': + outcol += 8; + outcol &= ~7; + outcol--; + c = ' '; + default: + if (outcol >= 132) { + outcol++; + continue; + } + cp = &page[outline][outcol]; + outcol++; + if (c == '_') { + if (suppresul) + continue; + cp += 132; + c = '-'; + } + if (*cp == 0) { + *cp = c; + dp = cp - outcol; + for (cp--; cp >= dp && *cp == 0; cp--) + *cp = ' '; + } else + if (plus(c, *cp) || plus(*cp, c)) + *cp = '+'; + else if (*cp == ' ' || *cp == 0) + *cp = c; + continue; + } + } + } while (argc > 0); + fflush(stdout); + exit(0); +} + +plus(c, d) + char c, d; +{ + + return (c == '|' && d == '-' || d == '_'); +} + +int first; + +pflush(ol) + int ol; +{ + register int i, j; + register char *cp; + char lastomit; + int l; + + l = ol; + lastomit = 0; + if (l > 266) + l = 266; + else + l |= 1; + for (i = first | 1; i < l; i++) { + move(i, i - 1); + move(i, i + 1); + } + for (i = first; i < l; i++) { + cp = page[i]; + if (printall == 0 && lastomit == 0 && *cp == 0) { + lastomit = 1; + continue; + } + lastomit = 0; + printf("%s\n", cp); + } + bcopy(page[ol], page, (267 - ol) * 132); + bzero(page[267- ol], ol * 132); + outline -= ol; + outcol = 0; + first = 1; +} + +move(l, m) + int l, m; +{ + register char *cp, *dp; + + for (cp = page[l], dp = page[m]; *cp; cp++, dp++) { + switch (*cp) { + case '|': + if (*dp != ' ' && *dp != '|' && *dp != 0) + return; + break; + case ' ': + break; + default: + return; + } + } + if (*cp == 0) { + for (cp = page[l], dp = page[m]; *cp; cp++, dp++) + if (*cp == '|') + *dp = '|'; + else if (*dp == 0) + *dp = ' '; + page[l][0] = 0; + } +} diff --git a/text-utils/colrm.1 b/text-utils/colrm.1 new file mode 100644 index 000000000..43153b955 --- /dev/null +++ b/text-utils/colrm.1 @@ -0,0 +1,63 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)colrm.1 6.6 (Berkeley) 3/14/91 +.\" +.Dd March 14, 1991 +.Dt COLRM 1 +.Os BSD 3 +.Sh NAME +.Nm colrm +.Nd remove columns from a file +.Sh SYNOPSIS +.Nm colrm +.Op Ar startcol Op Ar endcol +.Sh DESCRIPTION +.Nm Colrm +removes selected columns from a file. Input is taken from standard input. +Output is sent to standard output. +.Pp +If called with one parameter the columns +of each line will be removed starting with the specified column. +If called with two parameters the columns from the first column +to the last column will be removed. +.Pp +Column numbering starts with column 1. +.Sh SEE ALSO +.Xr awk 1 , +.Xr column 1 , +.Xr expand 1 , +.Xr paste 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/text-utils/colrm.c b/text-utils/colrm.c new file mode 100644 index 000000000..0fcf725b1 --- /dev/null +++ b/text-utils/colrm.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1980 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)colrm.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include <stdio.h> +/* +COLRM removes unwanted columns from a file + Jeff Schriebman UC Berkeley 11-74 +*/ + + +main(argc,argv) +char **argv; +{ + register c, ct, first, last; + + first = 0; + last = 0; + if (argc > 1) + first = getn(*++argv); + if (argc > 2) + last = getn(*++argv); + +start: + ct = 0; +loop1: + c = getc(stdin); + if (feof(stdin)) + goto fin; + if (c == '\t') + ct = (ct + 8) & ~7; + else if (c == '\b') + ct = ct ? ct - 1 : 0; + else + ct++; + if (c == '\n') { + putc(c, stdout); + goto start; + } + if (!first || ct < first) { + putc(c, stdout); + goto loop1; + } + +/* Loop getting rid of characters */ + while (!last || ct < last) { + c = getc(stdin); + if (feof(stdin)) + goto fin; + if (c == '\n') { + putc(c, stdout); + goto start; + } + if (c == '\t') + ct = (ct + 8) & ~7; + else if (c == '\b') + ct = ct ? ct - 1 : 0; + else + ct++; + } + +/* Output last of the line */ + for (;;) { + c = getc(stdin); + if (feof(stdin)) + break; + putc(c, stdout); + if (c == '\n') + goto start; + } +fin: + fflush(stdout); + exit(0); +} + +getn(ap) +char *ap; +{ + register int n,c; + register char *p; + + p = ap; + n = 0; + while ((c = *p++) >= '0' && c <= '9') + n = n*10 + c - '0'; + return(n); +} diff --git a/text-utils/column.1 b/text-utils/column.1 new file mode 100644 index 000000000..05d6a0fd7 --- /dev/null +++ b/text-utils/column.1 @@ -0,0 +1,99 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)column.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Os +.Dt COLUMN 1 +.Sh NAME +.Nm column +.Nd columnate lists +.Sh SYNOPSIS +.Nm column +.Op Fl tx +.Op Fl c Ar columns +.Op Fl s Ar sep +.Op Ar +.Sh DESCRIPTION +The +.Nm column +utility formats its input into multiple columns. +Rows are filled before columns. +Input is taken from +.Ar file +operands, or, by default, from the standard input. +Empty lines are ignored. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl c +Output is formatted for a display +.Ar columns +wide. +.It Fl s +Specify a set of characters to be used to delimit columns for the +.Fl t +option. +.It Fl t +Determine the number of columns the input contains and create a table. +Columns are delimited with whitespace, by default, or with the characters +supplied using the +.Fl s +option. +Useful for pretty-printing displays. +.It Fl x +Fill columns before filling rows. +.El +.Pp +.Nm Column +exits 0 on success, >0 if an error occurred. +.Sh ENVIRONMENT +.Bl -tag -width COLUMNS +.It Ev COLUMNS +The environment variable +.Ev COLUMNS +is used to determine the size of +the screen if no other information is available. +.El +.Sh EXAMPLES +.Dl (printf \&"PERM LINKS OWNER SIZE MONTH DAY HH:MM/YEAR NAME\en\&"\ \&;\ \&\e +.Dl ls -l \&| sed 1d) \&| column -t +.Sh SEE ALSO +.Xr colrm 1 , +.Xr ls 1 , +.Xr paste 1 , +.Xr sort 1 +.Sh HISTORY +The +.Nm +command appeared in +.Bx 4.3 Reno . diff --git a/text-utils/column.c b/text-utils/column.c new file mode 100644 index 000000000..7536c06d7 --- /dev/null +++ b/text-utils/column.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1989, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)column.c 8.3 (Berkeley) 4/2/94"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/ioctl.h> + +#include <ctype.h> +#include <err.h> +#include <limits.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void c_columnate __P((void)); +void *emalloc __P((int)); +void input __P((FILE *)); +void maketbl __P((void)); +void print __P((void)); +void r_columnate __P((void)); +void usage __P((void)); + +int termwidth = 80; /* default terminal width */ + +int entries; /* number of records */ +int eval; /* exit value */ +int maxlength; /* longest record */ +char **list; /* array of pointers to records */ +char *separator = "\t "; /* field separator for table option */ + +int +main(argc, argv) + int argc; + char **argv; +{ + struct winsize win; + FILE *fp; + int ch, tflag, xflag; + char *p; + +#ifdef __linux__ + extern int optind; + extern char *optarg; + extern char *__progname; + __progname = argv[0]; +#endif + + if (ioctl(1, TIOCGWINSZ, &win) == -1 || !win.ws_col) { + if (p = getenv("COLUMNS")) + termwidth = atoi(p); + } else + termwidth = win.ws_col; + + tflag = xflag = 0; + while ((ch = getopt(argc, argv, "c:s:tx")) != EOF) + switch(ch) { + case 'c': + termwidth = atoi(optarg); + break; + case 's': + separator = optarg; + break; + case 't': + tflag = 1; + break; + case 'x': + xflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (!*argv) + input(stdin); + else for (; *argv; ++argv) + if (fp = fopen(*argv, "r")) { + input(fp); + (void)fclose(fp); + } else { + warn("%s", *argv); + eval = 1; + } + + if (!entries) + exit(eval); + + if (tflag) + maketbl(); + else if (maxlength >= termwidth) + print(); + else if (xflag) + c_columnate(); + else + r_columnate(); + exit(eval); +} + +#define TAB 8 +void +c_columnate() +{ + int chcnt, col, cnt, endcol, numcols; + char **lp; + + maxlength = (maxlength + TAB) & ~(TAB - 1); + numcols = termwidth / maxlength; + endcol = maxlength; + for (chcnt = col = 0, lp = list;; ++lp) { + chcnt += printf("%s", *lp); + if (!--entries) + break; + if (++col == numcols) { + chcnt = col = 0; + endcol = maxlength; + putchar('\n'); + } else { + while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { + (void)putchar('\t'); + chcnt = cnt; + } + endcol += maxlength; + } + } + if (chcnt) + putchar('\n'); +} + +void +r_columnate() +{ + int base, chcnt, cnt, col, endcol, numcols, numrows, row; + + maxlength = (maxlength + TAB) & ~(TAB - 1); + numcols = termwidth / maxlength; + numrows = entries / numcols; + if (entries % numcols) + ++numrows; + + for (row = 0; row < numrows; ++row) { + endcol = maxlength; + for (base = row, chcnt = col = 0; col < numcols; ++col) { + chcnt += printf("%s", list[base]); + if ((base += numrows) >= entries) + break; + while ((cnt = (chcnt + TAB & ~(TAB - 1))) <= endcol) { + (void)putchar('\t'); + chcnt = cnt; + } + endcol += maxlength; + } + putchar('\n'); + } +} + +void +print() +{ + int cnt; + char **lp; + + for (cnt = entries, lp = list; cnt--; ++lp) + (void)printf("%s\n", *lp); +} + +typedef struct _tbl { + char **list; + int cols, *len; +} TBL; +#define DEFCOLS 25 + +void +maketbl() +{ + TBL *t; + int coloff, cnt; + char *p, **lp; + int *lens, maxcols; + TBL *tbl; + char **cols; + + t = tbl = emalloc(entries * sizeof(TBL)); + cols = emalloc((maxcols = DEFCOLS) * sizeof(char *)); + lens = emalloc(maxcols * sizeof(int)); + for (cnt = 0, lp = list; cnt < entries; ++cnt, ++lp, ++t) { + for (coloff = 0, p = *lp; cols[coloff] = strtok(p, separator); + p = NULL) + if (++coloff == maxcols) { + if (!(cols = realloc(cols, (u_int)maxcols + + DEFCOLS * sizeof(char *))) || + !(lens = realloc(lens, + (u_int)maxcols + DEFCOLS * sizeof(int)))) + err(1, NULL); + memset((char *)lens + maxcols * sizeof(int), + 0, DEFCOLS * sizeof(int)); + maxcols += DEFCOLS; + } + t->list = emalloc(coloff * sizeof(char *)); + t->len = emalloc(coloff * sizeof(int)); + for (t->cols = coloff; --coloff >= 0;) { + t->list[coloff] = cols[coloff]; + t->len[coloff] = strlen(cols[coloff]); + if (t->len[coloff] > lens[coloff]) + lens[coloff] = t->len[coloff]; + } + } + for (cnt = 0, t = tbl; cnt < entries; ++cnt, ++t) { + for (coloff = 0; coloff < t->cols - 1; ++coloff) + (void)printf("%s%*s", t->list[coloff], + lens[coloff] - t->len[coloff] + 2, " "); + (void)printf("%s\n", t->list[coloff]); + } +} + +#define DEFNUM 1000 +#define MAXLINELEN (LINE_MAX + 1) + +void +input(fp) + FILE *fp; +{ + static int maxentry; + int len; + char *p, buf[MAXLINELEN]; + + if (!list) + list = emalloc((maxentry = DEFNUM) * sizeof(char *)); + while (fgets(buf, MAXLINELEN, fp)) { + for (p = buf; *p && isspace(*p); ++p); + if (!*p) + continue; + if (!(p = strchr(p, '\n'))) { + warnx("line too long"); + eval = 1; + continue; + } + *p = '\0'; + len = p - buf; + if (maxlength < len) + maxlength = len; + if (entries == maxentry) { + maxentry += DEFNUM; + if (!(list = realloc(list, + (u_int)maxentry * sizeof(char *)))) + err(1, NULL); + } + list[entries++] = strdup(buf); + } +} + +void * +emalloc(size) + int size; +{ + char *p; + + if (!(p = malloc(size))) + err(1, NULL); + memset(p, 0, size); + return (p); +} + +void +usage() +{ + + (void)fprintf(stderr, + "usage: column [-tx] [-c columns] [file ...]\n"); + exit(1); +} diff --git a/text-utils/conv.c b/text-utils/conv.c new file mode 100644 index 000000000..c7a37a2b4 --- /dev/null +++ b/text-utils/conv.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)conv.c 5.4 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include <sys/types.h> +#include <ctype.h> +#include "hexdump.h" + +conv_c(pr, p) + PR *pr; + u_char *p; +{ + extern int deprecated; + char buf[10], *str; + + switch(*p) { + case '\0': + str = "\\0"; + goto strpr; + /* case '\a': */ + case '\007': + if (deprecated) /* od didn't know about \a */ + break; + str = "\\a"; + goto strpr; + case '\b': + str = "\\b"; + goto strpr; + case '\f': + str = "\\f"; + goto strpr; + case '\n': + str = "\\n"; + goto strpr; + case '\r': + str = "\\r"; + goto strpr; + case '\t': + str = "\\t"; + goto strpr; + case '\v': + if (deprecated) + break; + str = "\\v"; + goto strpr; + default: + break; + } + if (isprint(*p)) { + *pr->cchar = 'c'; + (void)printf(pr->fmt, *p); + } else { + (void)sprintf(str = buf, "%03o", (int)*p); +strpr: *pr->cchar = 's'; + (void)printf(pr->fmt, str); + } +} + +conv_u(pr, p) + PR *pr; + u_char *p; +{ + extern int deprecated; + static char *list[] = { + "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", + "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", + "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", + "can", "em", "sub", "esc", "fs", "gs", "rs", "us", + }; + + /* od used nl, not lf */ + if (*p <= 0x1f) { + *pr->cchar = 's'; + if (deprecated && *p == 0x0a) + (void)printf(pr->fmt, "nl"); + else + (void)printf(pr->fmt, list[*p]); + } else if (*p == 0x7f) { + *pr->cchar = 's'; + (void)printf(pr->fmt, "del"); + } else if (deprecated && *p == 0x20) { /* od replace space with sp */ + *pr->cchar = 's'; + (void)printf(pr->fmt, " sp"); + } else if (isprint(*p)) { + *pr->cchar = 'c'; + (void)printf(pr->fmt, *p); + } else { + *pr->cchar = 'x'; + (void)printf(pr->fmt, (int)*p); + } +} diff --git a/text-utils/display.c b/text-utils/display.c new file mode 100644 index 000000000..12732ee72 --- /dev/null +++ b/text-utils/display.c @@ -0,0 +1,364 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)display.c 5.11 (Berkeley) 3/9/91"; +#endif /* not lint */ + +#include <sys/param.h> +#include <sys/stat.h> +#include <unistd.h> +#include <errno.h> +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "hexdump.h" + +#ifdef linux +#define MIN(a,b) ((a)<(b)?(a):(b)) +#endif + +enum _vflag vflag = FIRST; + +static off_t address; /* address/offset in stream */ +static off_t eaddress; /* end address */ +static off_t savaddress; /* saved address/offset in stream */ + +#define PRINT { \ + switch(pr->flags) { \ + case F_ADDRESS: \ + (void)printf(pr->fmt, address); \ + break; \ + case F_BPAD: \ + (void)printf(pr->fmt, ""); \ + break; \ + case F_C: \ + conv_c(pr, bp); \ + break; \ + case F_CHAR: \ + (void)printf(pr->fmt, *bp); \ + break; \ + case F_DBL: { \ + double dval; \ + float fval; \ + switch(pr->bcnt) { \ + case 4: \ + bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ + (void)printf(pr->fmt, fval); \ + break; \ + case 8: \ + bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ + (void)printf(pr->fmt, dval); \ + break; \ + } \ + break; \ + } \ + case F_INT: { \ + int ival; \ + short sval; \ + switch(pr->bcnt) { \ + case 1: \ + (void)printf(pr->fmt, (int)*bp); \ + break; \ + case 2: \ + bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ + (void)printf(pr->fmt, (int)sval); \ + break; \ + case 4: \ + bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ + (void)printf(pr->fmt, ival); \ + break; \ + } \ + break; \ + } \ + case F_P: \ + (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ + break; \ + case F_STR: \ + (void)printf(pr->fmt, (char *)bp); \ + break; \ + case F_TEXT: \ + (void)printf(pr->fmt); \ + break; \ + case F_U: \ + conv_u(pr, bp); \ + break; \ + case F_UINT: { \ + u_int ival; \ + u_short sval; \ + switch(pr->bcnt) { \ + case 1: \ + (void)printf(pr->fmt, (u_int)*bp); \ + break; \ + case 2: \ + bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ + (void)printf(pr->fmt, (u_int)sval); \ + break; \ + case 4: \ + bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ + (void)printf(pr->fmt, ival); \ + break; \ + } \ + break; \ + } \ + } \ +} + +display() +{ + extern FU *endfu; + register FS *fs; + register FU *fu; + register PR *pr; + register int cnt; + register u_char *bp; + off_t saveaddress; + u_char savech, *savebp, *get(); + + while (bp = get()) + for (fs = fshead, savebp = bp, saveaddress = address; fs; + fs = fs->nextfs, bp = savebp, address = saveaddress) + for (fu = fs->nextfu; fu; fu = fu->nextfu) { + if (fu->flags&F_IGNORE) + break; + for (cnt = fu->reps; cnt; --cnt) + for (pr = fu->nextpr; pr; address += pr->bcnt, + bp += pr->bcnt, pr = pr->nextpr) { + if (eaddress && address >= eaddress && + !(pr->flags&(F_TEXT|F_BPAD))) + bpad(pr); + if (cnt == 1 && pr->nospace) { + savech = *pr->nospace; + *pr->nospace = '\0'; + } + PRINT; + if (cnt == 1 && pr->nospace) + *pr->nospace = savech; + } + } + if (endfu) { + /* + * if eaddress not set, error or file size was multiple of + * blocksize, and no partial block ever found. + */ + if (!eaddress) { + if (!address) + return; + eaddress = address; + } + for (pr = endfu->nextpr; pr; pr = pr->nextpr) + switch(pr->flags) { + case F_ADDRESS: + (void)printf(pr->fmt, eaddress); + break; + case F_TEXT: + (void)printf(pr->fmt); + break; + } + } +} + +bpad(pr) + PR *pr; +{ + static char *spec = " -0+#"; + register char *p1, *p2; + + /* + * remove all conversion flags; '-' is the only one valid + * with %s, and it's not useful here. + */ + pr->flags = F_BPAD; + *pr->cchar = 's'; + for (p1 = pr->fmt; *p1 != '%'; ++p1); + for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); + while (*p2++ = *p1++); +} + +static char **_argv; + +u_char * +get() +{ + extern enum _vflag vflag; + extern int length; + static int ateof = 1; + static u_char *curp, *savp; + register int n; + int need, nread; + u_char *tmpp; + + if (!curp) { + curp = (u_char *)emalloc(blocksize); + savp = (u_char *)emalloc(blocksize); + } else { + tmpp = curp; + curp = savp; + savp = tmpp; + address = savaddress += blocksize; + } + for (need = blocksize, nread = 0;;) { + /* + * if read the right number of bytes, or at EOF for one file, + * and no other files are available, zero-pad the rest of the + * block and set the end flag. + */ + if (!length || ateof && !next((char **)NULL)) { + if (need == blocksize) + return((u_char *)NULL); + if (vflag != ALL && !bcmp(curp, savp, nread)) { + if (vflag != DUP) + (void)printf("*\n"); + return((u_char *)NULL); + } + bzero((char *)curp + nread, need); + eaddress = address + nread; + return(curp); + } + n = fread((char *)curp + nread, sizeof(u_char), + length == -1 ? need : MIN(length, need), stdin); + if (!n) { + if (ferror(stdin)) + (void)fprintf(stderr, "hexdump: %s: %s\n", + _argv[-1], strerror(errno)); + ateof = 1; + continue; + } + ateof = 0; + if (length != -1) + length -= n; + if (!(need -= n)) { + if (vflag == ALL || vflag == FIRST || + bcmp(curp, savp, blocksize)) { + if (vflag == DUP || vflag == FIRST) + vflag = WAIT; + return(curp); + } + if (vflag == WAIT) + (void)printf("*\n"); + vflag = DUP; + address = savaddress += blocksize; + need = blocksize; + nread = 0; + } + else + nread += n; + } +} + +extern off_t skip; /* bytes to skip */ + +next(argv) + char **argv; +{ + extern int errno, exitval; + static int done; + int statok; + + if (argv) { + _argv = argv; + return(1); + } + for (;;) { + if (*_argv) { + if (!(freopen(*_argv, "r", stdin))) { + (void)fprintf(stderr, "hexdump: %s: %s\n", + *_argv, strerror(errno)); + exitval = 1; + ++_argv; + continue; + } + statok = done = 1; + } else { + if (done++) + return(0); + statok = 0; + } + if (skip) + doskip(statok ? *_argv : "stdin", statok); + if (*_argv) + ++_argv; + if (!skip) + return(1); + } + /* NOTREACHED */ +} + +doskip(fname, statok) + char *fname; + int statok; +{ + extern int errno; + struct stat sbuf; + + if (statok) { + if (fstat(fileno(stdin), &sbuf)) { + (void)fprintf(stderr, "hexdump: %s: %s.\n", + fname, strerror(errno)); + exit(1); + } + if (skip >= sbuf.st_size) { + skip -= sbuf.st_size; + address += sbuf.st_size; + return; + } + } + if (fseek(stdin, skip, SEEK_SET)) { + (void)fprintf(stderr, "hexdump: %s: %s.\n", + fname, strerror(errno)); + exit(1); + } + savaddress = address += skip; + skip = 0; +} + +char * +emalloc(size) + int size; +{ + char *p; + + if (!(p = malloc((u_int)size))) + nomem(); + bzero(p, size); + return(p); +} + +nomem() +{ + extern int errno; + + (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno)); + exit(1); +} diff --git a/text-utils/hexdump.1 b/text-utils/hexdump.1 new file mode 100644 index 000000000..7161beb45 --- /dev/null +++ b/text-utils/hexdump.1 @@ -0,0 +1,324 @@ +.\" Copyright (c) 1989, 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)hexdump.1 8.2 (Berkeley) 4/18/94 +.\" +.Dd April 18, 1994 +.Dt HEXDUMP 1 +.Os +.Sh NAME +.Nm hexdump +.Nd ascii, decimal, hexadecimal, octal dump +.Sh SYNOPSIS +.Nm hexdump +.Op Fl bcdovx +.Op Fl e Ar format_string +.Op Fl f Ar format_file +.Op Fl n Ar length +.Bk -words +.Op Fl s Ar skip +.Ek +.Ar file ... +.Sh DESCRIPTION +The hexdump utility is a filter which displays the specified files, or +the standard input, if no files are specified, in a user specified +format. +.Pp +The options are as follows: +.Bl -tag -width Fl +.It Fl b +.Em One-byte octal display . +Display the input offset in hexadecimal, followed by sixteen +space-separated, three column, zero-filled, bytes of input data, +in octal, per line. +.It Fl c +.Em One-byte character display . +Display the input offset in hexadecimal, followed by sixteen +space-separated, three column, space-filled, characters of input +data per line. +.It Fl d +.Em Two-byte decimal display. +Display the input offset in hexadecimal, followed by eight +space-separated, five column, zero-filled, two-byte units +of input data, in unsigned decimal, per line. +.It Fl e Ar format_string +Specify a format string to be used for displaying data. +.It Fl f Ar format_file +Specify a file that contains one or more newline separated format strings. +Empty lines and lines whose first non-blank character is a hash mark +.Pf ( Cm \&# ) +are ignored. +.It Fl n Ar length +Interpret only +.Ar length +bytes of input. +.It Fl o +.Em Two-byte octal display. +Display the input offset in hexadecimal, followed by eight +space-separated, six column, zero-filled, two byte quantities of +input data, in octal, per line. +.It Fl s Ar offset +Skip +.Ar offset +bytes from the beginning of the input. +By default, +.Ar offset +is interpreted as a decimal number. +With a leading +.Cm 0x +or +.Cm 0X , +.Ar offset +is interpreted as a hexadecimal number, +otherwise, with a leading +.Cm 0 , +.Ar offset +is interpreted as an octal number. +Appending the character +.Cm b , +.Cm k , +or +.Cm m +to +.Ar offset +causes it to be interpreted as a multiple of +.Li 512 , +.Li 1024 , +or +.Li 1048576 , +respectively. +.It Fl v +The +.Fl v +option causes hexdump to display all input data. +Without the +.Fl v +option, any number of groups of output lines, which would be +identical to the immediately preceding group of output lines (except +for the input offsets), are replaced with a line comprised of a +single asterisk. +.It Fl x +.Em Two-byte hexadecimal display. +Display the input offset in hexadecimal, followed by eight, space +separated, four column, zero-filled, two-byte quantities of input +data, in hexadecimal, per line. +.El +.Pp +For each input file, +.Nm hexdump +sequentially copies the input to standard output, transforming the +data according to the format strings specified by the +.Fl e +and +.Fl f +options, in the order that they were specified. +.Ss Formats +A format string contains any number of format units, separated by +whitespace. +A format unit contains up to three items: an iteration count, a byte +count, and a format. +.Pp +The iteration count is an optional positive integer, which defaults to +one. +Each format is applied iteration count times. +.Pp +The byte count is an optional positive integer. +If specified it defines the number of bytes to be interpreted by +each iteration of the format. +.Pp +If an iteration count and/or a byte count is specified, a single slash +must be placed after the iteration count and/or before the byte count +to disambiguate them. +Any whitespace before or after the slash is ignored. +.Pp +The format is required and must be surrounded by double quote +(" ") marks. +It is interpreted as a fprintf-style format string (see +.Xr fprintf 3 ) , +with the +following exceptions: +.Bl -bullet -offset indent +.It +An asterisk (*) may not be used as a field width or precision. +.It +A byte count or field precision +.Em is +required for each ``s'' conversion +character (unlike the +.Xr fprintf 3 +default which prints the entire string if the precision is unspecified). +.It +The conversion characters ``h'', ``l'', ``n'', ``p'' and ``q'' are +not supported. +.It +The single character escape sequences +described in the C standard are supported: +.Bd -ragged -offset indent -compact +.Bl -column <alert_character> +.It NUL \e0 +.It <alert character> \ea +.It <backspace> \eb +.It <form-feed> \ef +.It <newline> \en +.It <carriage return> \er +.It <tab> \et +.It <vertical tab> \ev +.El +.Ed +.El +.Pp +Hexdump also supports the the following additional conversion strings: +.Bl -tag -width Fl +.It Cm \&_a Ns Op Cm dox +Display the input offset, cumulative across input files, of the +next byte to be displayed. +The appended characters +.Cm d , +.Cm o , +and +.Cm x +specify the display base +as decimal, octal or hexadecimal respectively. +.It Cm \&_A Ns Op Cm dox +Identical to the +.Cm \&_a +conversion string except that it is only performed +once, when all of the input data has been processed. +.It Cm \&_c +Output characters in the default character set. +Nonprinting characters are displayed in three character, zero-padded +octal, except for those representable by standard escape notation +(see above), +which are displayed as two character strings. +.It Cm _p +Output characters in the default character set. +Nonprinting characters are displayed as a single +.Dq Cm \&. . +.It Cm _u +Output US ASCII characters, with the exception that control characters are +displayed using the following, lower-case, names. +Characters greater than 0xff, hexadecimal, are displayed as hexadecimal +strings. +.Bl -column \&000_nu \&001_so \&002_st \&003_et \&004_eo +.It \&000\ nul\t001\ soh\t002\ stx\t003\ etx\t004\ eot\t005\ enq +.It \&006\ ack\t007\ bel\t008\ bs\t009\ ht\t00A\ lf\t00B\ vt +.It \&00C\ ff\t00D\ cr\t00E\ so\t00F\ si\t010\ dle\t011\ dc1 +.It \&012\ dc2\t013\ dc3\t014\ dc4\t015\ nak\t016\ syn\t017\ etb +.It \&018\ can\t019\ em\t01A\ sub\t01B\ esc\t01C\ fs\t01D\ gs +.It \&01E\ rs\t01F\ us\t0FF\ del +.El +.El +.Pp +The default and supported byte counts for the conversion characters +are as follows: +.Bl -tag -width "Xc,_Xc,_Xc,_Xc,_Xc,_Xc" -offset indent +.It Li \&%_c , \&%_p , \&%_u , \&%c +One byte counts only. +.It Xo +.Li \&%d , \&%i , \&%o , +.Li \&%u , \&%X , \&%x +.Xc +Four byte default, one, two and four byte counts supported. +.It Xo +.Li \&%E , \&%e , \&%f , +.Li \&%G , \&%g +.Xc +Eight byte default, four byte counts supported. +.El +.Pp +The amount of data interpreted by each format string is the sum of the +data required by each format unit, which is the iteration count times the +byte count, or the iteration count times the number of bytes required by +the format if the byte count is not specified. +.Pp +The input is manipulated in ``blocks'', where a block is defined as the +largest amount of data specified by any format string. +Format strings interpreting less than an input block's worth of data, +whose last format unit both interprets some number of bytes and does +not have a specified iteration count, have the iteration count +incremented until the entire input block has been processed or there +is not enough data remaining in the block to satisfy the format string. +.Pp +If, either as a result of user specification or hexdump modifying +the iteration count as described above, an iteration count is +greater than one, no trailing whitespace characters are output +during the last iteration. +.Pp +It is an error to specify a byte count as well as multiple conversion +characters or strings unless all but one of the conversion characters +or strings is +.Cm \&_a +or +.Cm \&_A . +.Pp +If, as a result of the specification of the +.Fl n +option or end-of-file being reached, input data only partially +satisfies a format string, the input block is zero-padded sufficiently +to display all available data (i.e. any format units overlapping the +end of data will display some number of the zero bytes). +.Pp +Further output by such format strings is replaced by an equivalent +number of spaces. +An equivalent number of spaces is defined as the number of spaces +output by an +.Cm s +conversion character with the same field width +and precision as the original conversion character or conversion +string but with any +.Dq Li \&+ , +.Dq \&\ \& , +.Dq Li \&# +conversion flag characters +removed, and referencing a NULL string. +.Pp +If no format strings are specified, the default display is equivalent +to specifying the +.Fl x +option. +.Pp +.Nm hexdump +exits 0 on success and >0 if an error occurred. +.Sh EXAMPLES +Display the input in perusal format: +.Bd -literal -offset indent +"%06.6_ao " 12/1 "%3_u " +"\et\et" "%_p " +"\en" +.Ed +.Pp +Implement the \-x option: +.Bd -literal -offset indent +"%07.7_Ax\en" +"%07.7_ax " 8/2 "%04x " "\en" +.Ed +.Sh SEE ALSO +.Xr adb 1 diff --git a/text-utils/hexdump.c b/text-utils/hexdump.c new file mode 100644 index 000000000..4b282427a --- /dev/null +++ b/text-utils/hexdump.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)hexdump.c 5.5 (Berkeley) 6/1/90"; +#endif /* not lint */ + +#include <sys/types.h> +#include <stdio.h> +#include "hexdump.h" + +FS *fshead; /* head of format strings */ +int blocksize; /* data block size */ +int exitval; /* final exit value */ +int length = -1; /* max bytes to read */ + +main(argc, argv) + int argc; + char **argv; +{ + extern int errno; + register FS *tfs; + char *p, *rindex(); + + if (!(p = rindex(argv[0], 'o')) || strcmp(p, "od")) + newsyntax(argc, &argv); + else + oldsyntax(argc, &argv); + + /* figure out the data block size */ + for (blocksize = 0, tfs = fshead; tfs; tfs = tfs->nextfs) { + tfs->bcnt = size(tfs); + if (blocksize < tfs->bcnt) + blocksize = tfs->bcnt; + } + /* rewrite the rules, do syntax checking */ + for (tfs = fshead; tfs; tfs = tfs->nextfs) + rewrite(tfs); + + (void)next(argv); + display(); + exit(exitval); +} diff --git a/text-utils/hexdump.h b/text-utils/hexdump.h new file mode 100644 index 000000000..9def76330 --- /dev/null +++ b/text-utils/hexdump.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)hexdump.h 5.4 (Berkeley) 6/1/90 + */ + +typedef struct _pr { + struct _pr *nextpr; /* next print unit */ +#define F_ADDRESS 0x001 /* print offset */ +#define F_BPAD 0x002 /* blank pad */ +#define F_C 0x004 /* %_c */ +#define F_CHAR 0x008 /* %c */ +#define F_DBL 0x010 /* %[EefGf] */ +#define F_INT 0x020 /* %[di] */ +#define F_P 0x040 /* %_p */ +#define F_STR 0x080 /* %s */ +#define F_U 0x100 /* %_u */ +#define F_UINT 0x200 /* %[ouXx] */ +#define F_TEXT 0x400 /* no conversions */ + u_int flags; /* flag values */ + int bcnt; /* byte count */ + char *cchar; /* conversion character */ + char *fmt; /* printf format */ + char *nospace; /* no whitespace version */ +} PR; + +typedef struct _fu { + struct _fu *nextfu; /* next format unit */ + struct _pr *nextpr; /* next print unit */ +#define F_IGNORE 0x01 /* %_A */ +#define F_SETREP 0x02 /* rep count set, not default */ + u_int flags; /* flag values */ + int reps; /* repetition count */ + int bcnt; /* byte count */ + char *fmt; /* format string */ +} FU; + +typedef struct _fs { /* format strings */ + struct _fs *nextfs; /* linked list of format strings */ + struct _fu *nextfu; /* linked list of format units */ + int bcnt; +} FS; + +extern FS *fshead; /* head of format strings list */ +extern int blocksize; /* data block size */ +enum _vflag { ALL, DUP, FIRST, WAIT }; /* -v values */ +char *emalloc(); diff --git a/text-utils/hexsyntax.c b/text-utils/hexsyntax.c new file mode 100644 index 000000000..3812e979e --- /dev/null +++ b/text-utils/hexsyntax.c @@ -0,0 +1,130 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)hexsyntax.c 5.2 (Berkeley) 5/8/90"; +#endif /* not lint */ + +#include <sys/types.h> +#include <stdio.h> +#include "hexdump.h" + +off_t skip; /* bytes to skip */ + +newsyntax(argc, argvp) + int argc; + char ***argvp; +{ + extern enum _vflag vflag; + extern FS *fshead; + extern char *optarg; + extern int length, optind; + int ch; + char *p, **argv; + + argv = *argvp; + while ((ch = getopt(argc, argv, "bcde:f:n:os:vx")) != EOF) + switch (ch) { + case 'b': + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 16/1 \"%03o \" \"\\n\""); + break; + case 'c': + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 16/1 \"%3_c \" \"\\n\""); + break; + case 'd': + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 8/2 \" %05u \" \"\\n\""); + break; + case 'e': + add(optarg); + break; + case 'f': + addfile(optarg); + break; + case 'n': + if ((length = atoi(optarg)) < 0) { + (void)fprintf(stderr, + "hexdump: bad length value.\n"); + exit(1); + } + break; + case 'o': + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 8/2 \" %06o \" \"\\n\""); + break; + case 's': + if ((skip = strtol(optarg, &p, 0)) < 0) { + (void)fprintf(stderr, + "hexdump: bad skip value.\n"); + exit(1); + } + switch(*p) { + case 'b': + skip *= 512; + break; + case 'k': + skip *= 1024; + break; + case 'm': + skip *= 1048576; + break; + } + break; + case 'v': + vflag = ALL; + break; + case 'x': + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 8/2 \" %04x \" \"\\n\""); + break; + case '?': + usage(); + exit(1); + } + + if (!fshead) { + add("\"%07.7_Ax\n\""); + add("\"%07.7_ax \" 8/2 \"%04x \" \"\\n\""); + } + + *argvp += optind; +} + +usage() +{ + (void)fprintf(stderr, +"hexdump: [-bcdovx] [-e fmt] [-f fmt_file] [-n length] [-s skip] [file ...]\n"); + exit(1); +} diff --git a/text-utils/more.1 b/text-utils/more.1 new file mode 100644 index 000000000..2f08b38a1 --- /dev/null +++ b/text-utils/more.1 @@ -0,0 +1,196 @@ +.\" Copyright (c) 1988, 1990 The Regents of the University of California. +.\" Copyright (c) 1988 Mark Nudleman +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)more.1 5.15 (Berkeley) 7/29/91 +.\" +.\" Revised: Fri Dec 25 15:27:27 1992 by root +.\" 25Dec92: Extensive changes made by Rik Faith (faith@cs.unc.edu) to +.\" conform with the more 5.19 currently in use by the Linux community. +.\" +.Dd July 29, 1991 (Modified December 25, 1992) +.Dt MORE 1 +.Os "Linux 0.98" +.Sh NAME +.Nm more +.Nd file perusal filter for crt viewing +.Sh SYNOPSIS +.Nm more +.Op Fl dlfpcsu +.Op Fl num +.Op +/ pattern +.Op + linenum +.Op Ar +.Sh DESCRIPTION +.Nm More +is a filter for paging through text one screenful at a time. This version +is especially primitve. Users should realize that +.Xr less 1 +provides +.Xr more 1 +emulation and extensive enhancements. +.Sh OPTIONS +Command line options are described below. +Options are also taken from the environment variable +.Ev MORE +(make sure to precede them with a dash (``-'')) but command +line options will override them. +.Bl -tag -width flag +.It Fl num +This option specifies an integer which is the screen size (in lines). +.It Fl d +.Nm more +will prompt the user with the message "[Press space to continue, 'q' to +quit.]" and will display "[Press 'h' for instructions.]" instead of ringing +the bell when an illegal key is pressed. +.It Fl l +.Nm more +usually treats +.Ic \&^L +(form feed) as a special character, and will pause after any line that +contains a form feed. The +.Fl l +option will prevent this behavior. +.It Fl f +Causes +.Nm more +to count logical, rather than screen lines (i.e., long lines are not +folded). +.It Fl p +Do not scroll. Instead, clear the whole screen and then display the text. +.It Fl c +Do not scroll. Instead, paint each screen from the top, clearing the +remainder of each line as it is displayed. +.It Fl s +Squeeze multiple blank lines into one. +.It Fl u +Suppress underlining. +.It Ic +/ +The +.Ic +/ +option specifies a string that will be searched for before +each file is displayed. +.It Ic +num +Start at line number +.Ic num . +.Sh COMMANDS +Interactive commands for +.Nm more +are based on +.Xr vi 1 . +Some commands may be preceeded by a decimal number, called k in the +descriptions below. +In the following descriptions, ^X means control-X. +.Pp +.Bl -tag -width Ic +.It Ic h No or Ic ? +Help: display a summary of these commands. +If you forget all the other commands, remember this one. +.It Ic SPACE +Display next k lines of text. Defaults to current screen size. +.It Ic z +Display next k lines of text. Defaults to current screen size. Argument +becomes new default. +.It Ic RETURN +Display next k lines of text. Defaults to 1. Argument becomes new +default. +.It Ic d No or Ic \&^D +Scroll k lines. Default is current scroll size, initially 11. Argument +becomes new default. +.It Xo +.Ic q +.No or +.Ic Q +.No or +.Ic INTERRUPT +.Xc +Exit. +.It Ic s +Skip forward k lines of text. Defaults to 1. +.It Ic f +Skip forward k screenfuls of text. Defaults to 1. +.It Ic b No or Ic \&^B +Skip backwards k screenfuls of text. Defaults to 1. +.It Ic ' +Go to place where previous search started. +.It Ic = +Display current line number. +.It Ic \&/ Ns Ar pattern +Search for kth occurrence of regular expression. Defaults to 1. +.It Ic n +Search for kth occurrence of last r.e. Defaults to 1. +.It Ic !<cmd> No or Ic :!<cmd> +Execute <cmd> in a subshell +.It Ic v +Start up /usr/bin/vi at current line +.It Ic \&^L +Redraw screen +.It Ic :n +Go to kth next file. Defaults to 1. +.It Ic :p +Go to kth previous file. Defaults to 1. +.It Ic :f +Display current file name and line number +.It Ic \&. +Repeat previous command +.El +.Sh ENVIRONMENT +.Nm More +utilizes the following environment variables, if they exist: +.Bl -tag -width Fl +.It Ev MORE +This variable may be set with favored options to +.Nm more . +.It Ev SHELL +Current shell in use (normally set by the shell at login time). +.It Ev TERM +Specifies terminal type, used by more to get the terminal +characteristics necessary to manipulate the screen. +.El +.Sh SEE ALSO +.Xr vi 1 +.Xr less 1 +.Sh AUTHORS +Eric Shienbrood, UC Berkeley +.br +Modified by Geoff Peck, UCB to add underlining, single spacing +.br +Modified by John Foderaro, UCB to add -c and MORE environment variable +.Sh HISTORY +The +.Nm more +command appeared in +.Bx 3.0 . +This man page documents +.Nm more +version 5.19 (Berkeley 6/29/88), which is currently in use in the Linux +community. Documentation was produced using several other versions of the +man page, and extensive inspection of the source code. diff --git a/text-utils/more.c b/text-utils/more.c new file mode 100644 index 000000000..51ddc6430 --- /dev/null +++ b/text-utils/more.c @@ -0,0 +1,1832 @@ +/* + * Copyright (C) 1980 Regents Of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980 Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)more.c 5.19 (Berkeley) 6/29/88"; +#endif /* not lint */ + +/* +** more.c - General purpose tty output filter and file perusal program +** +** by Eric Shienbrood, UC Berkeley +** +** modified by Geoff Peck, UCB to add underlining, single spacing +** modified by John Foderaro, UCB to add -c and MORE environment variable +*/ + +#include <stdio.h> +#include <unistd.h> +#include <sys/param.h> +#include <ctype.h> +#include <signal.h> +#include <errno.h> +#include <termios.h> +#include <setjmp.h> +#include <sys/stat.h> +#include <sys/file.h> +#include <a.out.h> +#include <varargs.h> +#include <termcap.h> + +#define HELPFILE "/usr/lib/more.help" +#define VI "/usr/bin/vi" + +#define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m)) +#define Ftell(f) file_pos +#define Fseek(f,off) (file_pos=off,fseek(f,off,0)) +#define Getc(f) (++file_pos, getc(f)) +#define Ungetc(c,f) (--file_pos, ungetc(c,f)) + +#define stty(fd,argp) ioctl(fd,TCSETAF,argp) + +/* some function declarations */ +void initterm(); +void argscan(char *s); +void copy_file(register FILE *f); +void doclear(); +void home(); +void search(char buf[], FILE *file, register int n); +void skiplns(register int n, register FILE *f); +void screen (register FILE *f, register int num_lines); +int command (char *filename, register FILE *f); +void erase (register int col); +void cleareol(); +void clreos(); +int pr(char *s1); +void reset_tty(); +int getline(register FILE *f, int *length); +void prbuf (register char *s, register int n); + +#define TBUFSIZ 1024 +#define LINSIZ 256 +#define ctrl(letter) (letter & 077) +#define RUBOUT '\177' +#define ESC '\033' +#define QUIT '\034' + +struct termio otty, savetty; +long file_pos, file_size; +int fnum, no_intty, no_tty, slow_tty; +int dum_opt, dlines; +void onquit(), onsusp(), chgwinsz(), end_it(); +int nscroll = 11; /* Number of lines scrolled by 'd' */ +int fold_opt = 1; /* Fold long lines */ +int stop_opt = 1; /* Stop after form feeds */ +int ssp_opt = 0; /* Suppress white space */ +int ul_opt = 1; /* Underline as best we can */ +int promptlen; +int Currline; /* Line we are currently at */ +int startup = 1; +int firstf = 1; +int notell = 1; +int docrterase = 0; +int docrtkill = 0; +int bad_so; /* True if overwriting does not turn off standout */ +int inwait, Pause, errors; +int within; /* true if we are within a file, + false if we are between files */ +int hard, dumb, noscroll, hardtabs, clreol, eatnl; +int catch_susp; /* We should catch the SIGTSTP signal */ +char **fnames; /* The list of file names */ +int nfiles; /* Number of files left to process */ +char *shell; /* The name of the shell to use */ +int shellp; /* A previous shell command exists */ +char ch; +jmp_buf restore; +char Line[LINSIZ]; /* Line buffer */ +int Lpp = 24; /* lines per page */ +char *Clear; /* clear screen */ +char *eraseln; /* erase line */ +char *Senter, *Sexit;/* enter and exit standout mode */ +char *ULenter, *ULexit; /* enter and exit underline mode */ +char *chUL; /* underline character */ +char *chBS; /* backspace character */ +char *Home; /* go to home */ +char *cursorm; /* cursor movement */ +char cursorhome[40]; /* contains cursor movement to home */ +char *EodClr; /* clear rest of screen */ +char *tgetstr(); +int Mcol = 80; /* number of columns */ +int Wrap = 1; /* set if automargins */ +int soglitch; /* terminal has standout mode glitch */ +int ulglitch; /* terminal has underline mode glitch */ +int pstate = 0; /* current UL state */ +char *getenv(); +static magic(); +struct { + long chrctr, line; +} context, screen_start; +/* extern */ char PC; /* pad character */ + + +int main(int argc, char **argv) { + register FILE *f; + register char *s; + register char *p; + register char ch; + register int left; + int prnames = 0; + int initopt = 0; + int srchopt = 0; + int clearit = 0; + int initline; + char initbuf[80]; + FILE *checkf(); + + nfiles = argc; + fnames = argv; + initterm (); + nscroll = Lpp/2 - 1; + if (nscroll <= 0) + nscroll = 1; + if(s = getenv("MORE")) argscan(s); + while (--nfiles > 0) { + if ((ch = (*++fnames)[0]) == '-') { + argscan(*fnames+1); + } + else if (ch == '+') { + s = *fnames; + if (*++s == '/') { + srchopt++; + for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';) + *p++ = *s++; + *p = '\0'; + } + else { + initopt++; + for (initline = 0; *s != '\0'; s++) + if (isdigit (*s)) + initline = initline*10 + *s -'0'; + --initline; + } + } + else break; + } + /* allow clreol only if Home and eraseln and EodClr strings are + * defined, and in that case, make sure we are in noscroll mode + */ + if(clreol) + { + if((Home == NULL) || (*Home == '\0') || + (eraseln == NULL) || (*eraseln == '\0') || + (EodClr == NULL) || (*EodClr == '\0') ) + clreol = 0; + else noscroll = 1; + } + if (dlines == 0) + dlines = Lpp - (noscroll ? 1 : 2); + left = dlines; + if (nfiles > 1) + prnames++; + if (!no_intty && nfiles == 0) { + char *rindex(); + + p = rindex(argv[0], '/'); + fputs("usage: ",stderr); + fputs(p ? p + 1 : argv[0],stderr); + fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr); + exit(1); + } + else + f = stdin; + if (!no_tty) { + signal(SIGQUIT, onquit); + signal(SIGINT, end_it); +#ifdef SIGWINCH + signal(SIGWINCH, chgwinsz); +#endif + if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) { + signal(SIGTSTP, onsusp); + catch_susp++; + } + stty (fileno(stderr), &otty); + } + if (no_intty) { + if (no_tty) + copy_file (stdin); + else { + if ((ch = Getc (f)) == '\f') + doclear(); + else { + Ungetc (ch, f); + if (noscroll && (ch != EOF)) { + if (clreol) + home (); + else + doclear (); + } + } + if (srchopt) + { + search (initbuf, stdin, 1); + if (noscroll) + left--; + } + else if (initopt) + skiplns (initline, stdin); + screen (stdin, left); + } + no_intty = 0; + prnames++; + firstf = 0; + } + + while (fnum < nfiles) { + if ((f = checkf (fnames[fnum], &clearit)) != NULL) { + context.line = context.chrctr = 0; + Currline = 0; + if (firstf) setjmp (restore); + if (firstf) { + firstf = 0; + if (srchopt) + { + search (initbuf, f, 1); + if (noscroll) + left--; + } + else if (initopt) + skiplns (initline, f); + } + else if (fnum < nfiles && !no_tty) { + setjmp (restore); + left = command (fnames[fnum], f); + } + if (left != 0) { + if ((noscroll || clearit) && (file_size != LONG_MAX)) + if (clreol) + home (); + else + doclear (); + if (prnames) { + if (bad_so) + erase (0); + if (clreol) + cleareol (); + pr("::::::::::::::"); + if (promptlen > 14) + erase (14); + xprintf ("\n"); + if(clreol) cleareol(); + xprintf("%s\n", fnames[fnum]); + if(clreol) cleareol(); + xprintf("::::::::::::::\n"); + if (left > Lpp - 4) + left = Lpp - 4; + } + if (no_tty) + copy_file (f); + else { + within++; + screen(f, left); + within = 0; + } + } + setjmp (restore); + fflush(stdout); + fclose(f); + screen_start.line = screen_start.chrctr = 0L; + context.line = context.chrctr = 0L; + } + fnum++; + firstf = 0; + } + reset_tty (); + exit(0); +} + +void argscan(char *s) { + int seen_num = 0; + + while (*s != '\0') { + switch (*s) { + case '0': case '1': case '2': + case '3': case '4': case '5': + case '6': case '7': case '8': + case '9': + if (!seen_num) { + dlines = 0; + seen_num = 1; + } + dlines = dlines*10 + *s - '0'; + break; + case 'd': + dum_opt = 1; + break; + case 'l': + stop_opt = 0; + break; + case 'f': + fold_opt = 0; + break; + case 'p': + noscroll++; + break; + case 'c': + clreol++; + break; + case 's': + ssp_opt = 1; + break; + case 'u': + ul_opt = 0; + break; + } + s++; + } +} + + +/* +** Check whether the file named by fs is an ASCII file which the user may +** access. If it is, return the opened file. Otherwise return NULL. +*/ + +FILE * +checkf (fs, clearfirst) + register char *fs; + int *clearfirst; +{ + struct stat stbuf; + register FILE *f; + char c; + + if (stat (fs, &stbuf) == -1) { + (void)fflush(stdout); + if (clreol) + cleareol (); + perror(fs); + return((FILE *)NULL); + } + if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { + xprintf("\n*** %s: directory ***\n\n", fs); + return((FILE *)NULL); + } + if ((f = Fopen(fs, "r")) == NULL) { + (void)fflush(stdout); + perror(fs); + return((FILE *)NULL); + } + if (magic(f, fs)) + return((FILE *)NULL); + c = Getc(f); + *clearfirst = c == '\f'; + Ungetc (c, f); + if ((file_size = stbuf.st_size) == 0) + file_size = LONG_MAX; + return(f); +} + +/* + * magic -- + * check for file magic numbers. This code would best be shared with + * the file(1) program or, perhaps, more should not try and be so smart? + */ +static int +magic(f, fs) + FILE *f; + char *fs; +{ + struct exec ex; + + if (fread(&ex, sizeof(ex), 1, f) == 1) + switch(ex.a_info) { + case OMAGIC: + case NMAGIC: + case ZMAGIC: + case 0405: + case 0411: + case 0177545: + xprintf("\n******** %s: Not a text file ********\n\n", fs); + (void)fclose(f); + return(1); + } + (void)fseek(f, 0L, L_SET); /* rewind() not necessary */ + return(0); +} + +/* +** A real function, for the tputs routine in termlib +*/ +#ifdef __linux__ +int putch( int ch ) +#else +void +putch (ch) +char ch; +#endif +{ + putchar (ch); +#ifdef __linux__ + return 0; +#endif +} + +/* +** Print out the contents of the file f, one screenful at a time. +*/ + +#define STOP -10 + +void screen (register FILE *f, register int num_lines) +{ + register int c; + register int nchars; + int length; /* length of current line */ + static int prev_len = 1; /* length of previous line */ + + for (;;) { + while (num_lines > 0 && !Pause) { + if ((nchars = getline (f, &length)) == EOF) + { + if (clreol) + clreos(); + return; + } + if (ssp_opt && length == 0 && prev_len == 0) + continue; + prev_len = length; + if (bad_so || ((Senter && *Senter == ' ') && (promptlen > 0))) + erase (0); + /* must clear before drawing line since tabs on some terminals + * do not erase what they tab over. + */ + if (clreol) + cleareol (); + prbuf (Line, length); + if (nchars < promptlen) + erase (nchars); /* erase () sets promptlen to 0 */ + else promptlen = 0; + /* is this needed? + * if (clreol) + * cleareol(); * must clear again in case we wrapped * + */ + if (nchars < Mcol || !fold_opt) + prbuf("\n", 1); /* will turn off UL if necessary */ + if (nchars == STOP) + break; + num_lines--; + } + if (pstate) { + tputs(ULexit, 1, putch); + pstate = 0; + } + fflush(stdout); + if ((c = Getc(f)) == EOF) + { + if (clreol) + clreos (); + return; + } + + if (Pause && clreol) + clreos (); + Ungetc (c, f); + setjmp (restore); + Pause = 0; startup = 0; + if ((num_lines = command (NULL, f)) == 0) + return; + if (hard && promptlen > 0) + erase (0); + if (noscroll && num_lines >= dlines) + { + if (clreol) + home(); + else + doclear (); + } + screen_start.line = Currline; + screen_start.chrctr = Ftell (f); + } +} + +/* +** Come here if a quit signal is received +*/ + +void onquit() +{ + signal(SIGQUIT, SIG_IGN); + if (!inwait) { + putchar ('\n'); + if (!startup) { + signal(SIGQUIT, onquit); + longjmp (restore, 1); + } + else + Pause++; + } + else if (!dum_opt && notell) { + write (2, "[Use q or Q to quit]", 20); + promptlen += 20; + notell = 0; + } + signal(SIGQUIT, onquit); +} + +/* +** Come here if a signal for a window size change is received +*/ + +#ifdef SIGWINCH +void chgwinsz() +{ + struct winsize win; + + (void) signal(SIGWINCH, SIG_IGN); + if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) { + if (win.ws_row != 0) { + Lpp = win.ws_row; + nscroll = Lpp/2 - 1; + if (nscroll <= 0) + nscroll = 1; + dlines = Lpp - (noscroll ? 1 : 2); + } + if (win.ws_col != 0) + Mcol = win.ws_col; + } + (void) signal(SIGWINCH, chgwinsz); +} +#endif + +/* +** Clean up terminal state and exit. Also come here if interrupt signal received +*/ + +void end_it () +{ + + reset_tty (); + if (clreol) { + putchar ('\r'); + clreos (); + fflush (stdout); + } + else if (!clreol && (promptlen > 0)) { + kill_line (); + fflush (stdout); + } + else + write (2, "\n", 1); + _exit(0); +} + +void copy_file(register FILE *f) { + register int c; + + while ((c = getc(f)) != EOF) + putchar(c); +} + +/* Simplified printf function */ + +int xprintf (fmt, va_alist) +register char *fmt; +va_dcl +{ + va_list ap; + register char ch; + register int ccount; + + ccount = 0; + va_start(ap); + while (*fmt) { + while ((ch = *fmt++) != '%') { + if (ch == '\0') + return (ccount); + ccount++; + putchar (ch); + } + switch (*fmt++) { + case 'd': + ccount += printd (va_arg(ap, int)); + break; + case 's': + ccount += pr (va_arg(ap, char *)); + break; + case '%': + ccount++; + putchar ('%'); + break; + case '0': + return (ccount); + default: + break; + } + } + va_end(ap); + return (ccount); + +} + +/* +** Print an integer as a string of decimal digits, +** returning the length of the print representation. +*/ + +printd (n) +int n; +{ + int a, nchars; + + if (a = n/10) + nchars = 1 + printd(a); + else + nchars = 1; + putchar (n % 10 + '0'); + return (nchars); +} + +/* Put the print representation of an integer into a string */ +static char *sptr; + +scanstr (n, str) +int n; +char *str; +{ + sptr = str; + Sprintf (n); + *sptr = '\0'; +} + +Sprintf (n) +{ + int a; + + if (a = n/10) + Sprintf (a); + *sptr++ = n % 10 + '0'; +} + +static char bell = ctrl('G'); + +#ifdef undef +strlen (s) +char *s; +{ + register char *p; + + p = s; + while (*p++) + ; + return (p - s - 1); +} +#endif + +/* See whether the last component of the path name "path" is equal to the +** string "string" +*/ + +tailequ (path, string) +char *path; +register char *string; +{ + register char *tail; + + tail = path + strlen(path); + while (tail >= path) + if (*(--tail) == '/') + break; + ++tail; + while (*tail++ == *string++) + if (*tail == '\0') + return(1); + return(0); +} + +prompt (filename) +char *filename; +{ + if (clreol) + cleareol (); + else if (promptlen > 0) + kill_line (); + if (!hard) { + promptlen = 8; + if (Senter && Sexit) { + tputs (Senter, 1, putch); + promptlen += (2 * soglitch); + } + if (clreol) + cleareol (); + pr("--More--"); + if (filename != NULL) { + promptlen += xprintf ("(Next file: %s)", filename); + } + else if (!no_intty) { + promptlen += xprintf ("(%d%%)", (int)((file_pos * 100) / file_size)); + } + if (dum_opt) { + promptlen += pr("[Press space to continue, 'q' to quit.]"); + } + if (Senter && Sexit) + tputs (Sexit, 1, putch); + if (clreol) + clreos (); + fflush(stdout); + } + else + write (2, &bell, 1); + inwait++; +} + +/* +** Get a logical line +*/ + +int getline(register FILE *f, int *length) +{ + register int c; + register char *p; + register int column; + static int colflg; + + p = Line; + column = 0; + c = Getc (f); + if (colflg && c == '\n') { + Currline++; + c = Getc (f); + } + while (p < &Line[LINSIZ - 1]) { + if (c == EOF) { + if (p > Line) { + *p = '\0'; + *length = p - Line; + return (column); + } + *length = p - Line; + return (EOF); + } + if (c == '\n') { + Currline++; + break; + } + *p++ = c; + if (c == '\t') + if (!hardtabs || column < promptlen && !hard) { + if (hardtabs && eraseln && !dumb) { + column = 1 + (column | 7); + tputs (eraseln, 1, putch); + promptlen = 0; + } + else { + for (--p; p < &Line[LINSIZ - 1];) { + *p++ = ' '; + if ((++column & 7) == 0) + break; + } + if (column >= promptlen) promptlen = 0; + } + } + else + column = 1 + (column | 7); + else if (c == '\b' && column > 0) + column--; + else if (c == '\r') + column = 0; + else if (c == '\f' && stop_opt) { + p[-1] = '^'; + *p++ = 'L'; + column += 2; + Pause++; + } + else if (c == EOF) { + *length = p - Line; + return (column); + } + else if (c >= ' ' && c != RUBOUT) + column++; + if (column >= Mcol && fold_opt) break; + c = Getc (f); + } + if (column >= Mcol && Mcol > 0) { + if (!Wrap) { + *p++ = '\n'; + } + } + colflg = column == Mcol && fold_opt; + if (colflg && eatnl && Wrap) { + *p++ = '\n'; /* simulate normal wrap */ + } + *length = p - Line; + *p = 0; + return (column); +} + +/* +** Erase the rest of the prompt, assuming we are starting at column col. +*/ + +void erase (register int col) +{ + + if (promptlen == 0) + return; + if (hard) { + putchar ('\n'); + } + else { + if (col == 0) + putchar ('\r'); + if (!dumb && eraseln) + tputs (eraseln, 1, putch); + else + for (col = promptlen - col; col > 0; col--) + putchar (' '); + } + promptlen = 0; +} + +/* +** Erase the current line entirely +*/ + +kill_line () +{ + erase (0); + if (!eraseln || dumb) putchar ('\r'); +} + +/* + * force clear to end of line + */ +void cleareol() +{ + tputs(eraseln, 1, putch); +} + +void clreos() +{ + tputs(EodClr, 1, putch); +} + +/* +** Print string and return number of characters +*/ + +int pr(char *s1) +{ + register char *s; + register char c; + + for (s = s1; c = *s++; ) + putchar(c); + return (int) (s - s1 - 1); +} + + +/* Print a buffer of n characters */ + +void prbuf (register char *s, register int n) +{ + register char c; /* next output character */ + register int state; /* next output char's UL state */ +#define wouldul(s,n) ((n) >= 2 && (((s)[0] == '_' && (s)[1] == '\b') || ((s)[1] == '\b' && (s)[2] == '_'))) + + while (--n >= 0) + if (!ul_opt) + putchar (*s++); + else { + if (*s == ' ' && pstate == 0 && ulglitch && wouldul(s+1, n-1)) { + s++; + continue; + } + if (state = wouldul(s, n)) { + c = (*s == '_')? s[2] : *s ; + n -= 2; + s += 3; + } else + c = *s++; + if (state != pstate) { + if (c == ' ' && state == 0 && ulglitch && wouldul(s, n-1)) + state = 1; + else + tputs(state ? ULenter : ULexit, 1, putch); + } + if (c != ' ' || pstate == 0 || state != 0 || ulglitch == 0) + putchar(c); + if (state && *chUL) { + pr(chBS); + tputs(chUL, 1, putch); + } + pstate = state; + } +} + +/* +** Clear the screen +*/ +void +doclear() +{ + if (Clear && !hard) { + tputs(Clear, 1, putch); + + /* Put out carriage return so that system doesn't + ** get confused by escape sequences when expanding tabs + */ + putchar ('\r'); + promptlen = 0; + } +} + +/* + * Go to home position + */ +void +home() +{ + tputs(Home,1,putch); +} + +static int lastcmd, lastarg, lastp; +static int lastcolon; +char shell_line[132]; + +/* +** Read a command and do it. A command consists of an optional integer +** argument followed by the command character. Return the number of lines +** to display in the next screenful. If there is nothing more to display +** in the current file, zero is returned. +*/ + +int command (char *filename, register FILE *f) +{ + register int nlines; + register int retval; + register char c; + char colonch; + FILE *helpf; + int done; + char comchar, cmdbuf[80], *p; + +#define ret(val) retval=val;done++;break + + done = 0; + if (!errors) + prompt (filename); + else + errors = 0; + for (;;) { + nlines = number (&comchar); + lastp = colonch = 0; + if (comchar == '.') { /* Repeat last command */ + lastp++; + comchar = lastcmd; + nlines = lastarg; + if (lastcmd == ':') + colonch = lastcolon; + } + lastcmd = comchar; + lastarg = nlines; + if (comchar == otty.c_cc[VERASE]) { + kill_line (); + prompt (filename); + continue; + } + switch (comchar) { + case ':': + retval = colon (filename, colonch, nlines); + if (retval >= 0) + done++; + break; + case 'b': + case ctrl('B'): + { + register int initline; + + if (no_intty) { + write(2, &bell, 1); + return (-1); + } + + if (nlines == 0) nlines++; + + putchar ('\r'); + erase (0); + xprintf ("\n"); + if (clreol) + cleareol (); + xprintf ("...back %d page", nlines); + if (nlines > 1) + pr ("s\n"); + else + pr ("\n"); + + if (clreol) + cleareol (); + pr ("\n"); + + initline = Currline - dlines * (nlines + 1); + if (! noscroll) + --initline; + if (initline < 0) initline = 0; + Fseek(f, 0L); + Currline = 0; /* skiplns() will make Currline correct */ + skiplns(initline, f); + if (! noscroll) { + ret(dlines + 1); + } + else { + ret(dlines); + } + } + case ' ': + case 'z': + if (nlines == 0) nlines = dlines; + else if (comchar == 'z') dlines = nlines; + ret (nlines); + case 'd': + case ctrl('D'): + if (nlines != 0) nscroll = nlines; + ret (nscroll); + case 'q': + case 'Q': + end_it (); + case 's': + case 'f': + if (nlines == 0) nlines++; + if (comchar == 'f') + nlines *= dlines; + putchar ('\r'); + erase (0); + xprintf ("\n"); + if (clreol) + cleareol (); + xprintf ("...skipping %d line", nlines); + if (nlines > 1) + pr ("s\n"); + else + pr ("\n"); + + if (clreol) + cleareol (); + pr ("\n"); + + while (nlines > 0) { + while ((c = Getc (f)) != '\n') + if (c == EOF) { + retval = 0; + done++; + goto endsw; + } + Currline++; + nlines--; + } + ret (dlines); + case '\n': + if (nlines != 0) + dlines = nlines; + else + nlines = 1; + ret (nlines); + case '\f': + if (!no_intty) { + doclear (); + Fseek (f, screen_start.chrctr); + Currline = screen_start.line; + ret (dlines); + } + else { + write (2, &bell, 1); + break; + } + case '\'': + if (!no_intty) { + kill_line (); + pr ("\n***Back***\n\n"); + Fseek (f, context.chrctr); + Currline = context.line; + ret (dlines); + } + else { + write (2, &bell, 1); + break; + } + case '=': + kill_line (); + promptlen = printd (Currline); + fflush (stdout); + break; + case 'n': + lastp++; + case '/': + if (nlines == 0) nlines++; + kill_line (); + pr ("/"); + promptlen = 1; + fflush (stdout); + if (lastp) { + write (2,"\r", 1); + search (NULL, f, nlines); /* Use previous r.e. */ + } + else { + ttyin (cmdbuf, 78, '/'); + write (2, "\r", 1); + search (cmdbuf, f, nlines); + } + ret (dlines-1); + case '!': + do_shell (filename); + break; + case '?': + case 'h': + if ((helpf = fopen (HELPFILE, "r")) == NULL) + error ("Can't open help file"); + if (noscroll) doclear (); + copy_file (helpf); + fclose (helpf); + prompt (filename); + break; + case 'v': /* This case should go right before default */ + if (!no_intty) { + kill_line (); + cmdbuf[0] = '+'; + scanstr (Currline - dlines < 0 ? 0 + : Currline - (dlines + 1) / 2, &cmdbuf[1]); + pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]); + execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0); + break; + } + default: + if (dum_opt) { + kill_line (); + if (Senter && Sexit) { + tputs (Senter, 1, putch); + promptlen = pr ("[Press 'h' for instructions.]") + (2 * soglitch); + tputs (Sexit, 1, putch); + } + else + promptlen = pr ("[Press 'h' for instructions.]"); + fflush (stdout); + } + else + write (2, &bell, 1); + break; + } + if (done) break; + } + putchar ('\r'); +endsw: + inwait = 0; + notell++; + return (retval); +} + +char ch; + +/* + * Execute a colon-prefixed command. + * Returns <0 if not a command that should cause + * more of the file to be printed. + */ + +colon (filename, cmd, nlines) +char *filename; +int cmd; +int nlines; +{ + if (cmd == 0) + ch = readch (); + else + ch = cmd; + lastcolon = ch; + switch (ch) { + case 'f': + kill_line (); + if (!no_intty) + promptlen = xprintf ("\"%s\" line %d", fnames[fnum], Currline); + else + promptlen = xprintf ("[Not a file] line %d", Currline); + fflush (stdout); + return (-1); + case 'n': + if (nlines == 0) { + if (fnum >= nfiles - 1) + end_it (); + nlines++; + } + putchar ('\r'); + erase (0); + skipf (nlines); + return (0); + case 'p': + if (no_intty) { + write (2, &bell, 1); + return (-1); + } + putchar ('\r'); + erase (0); + if (nlines == 0) + nlines++; + skipf (-nlines); + return (0); + case '!': + do_shell (filename); + return (-1); + case 'q': + case 'Q': + end_it (); + default: + write (2, &bell, 1); + return (-1); + } +} + +/* +** Read a decimal number from the terminal. Set cmd to the non-digit which +** terminates the number. +*/ + +number(cmd) +char *cmd; +{ + register int i; + + i = 0; ch = otty.c_cc[VKILL]; + for (;;) { + ch = readch (); + if (ch >= '0' && ch <= '9') + i = i*10 + ch - '0'; + else if (ch == otty.c_cc[VKILL]) + i = 0; + else { + *cmd = ch; + break; + } + } + return (i); +} + +do_shell (filename) +char *filename; +{ + char cmdbuf[80]; + + kill_line (); + pr ("!"); + fflush (stdout); + promptlen = 1; + if (lastp) + pr (shell_line); + else { + ttyin (cmdbuf, 78, '!'); + if (expand (shell_line, cmdbuf)) { + kill_line (); + promptlen = xprintf ("!%s", shell_line); + } + } + fflush (stdout); + write (2, "\n", 1); + promptlen = 0; + shellp = 1; + execute (filename, shell, shell, "-c", shell_line, 0); +} + +/* +** Search for nth ocurrence of regular expression contained in buf in the file +*/ + +void search(char buf[], FILE *file, register int n) +{ + long startline = Ftell (file); + register long line1 = startline; + register long line2 = startline; + register long line3 = startline; + register int lncount; + int saveln, rv, re_exec(); + char *s, *re_comp(); + + context.line = saveln = Currline; + context.chrctr = startline; + lncount = 0; + if ((s = re_comp (buf)) != 0) + error (s); + while (!feof (file)) { + line3 = line2; + line2 = line1; + line1 = Ftell (file); + rdline (file); + lncount++; + if ((rv = re_exec (Line)) == 1) + if (--n == 0) { + if (lncount > 3 || (lncount > 1 && no_intty)) + { + pr ("\n"); + if (clreol) + cleareol (); + pr("...skipping\n"); + } + if (!no_intty) { + Currline -= (lncount >= 3 ? 3 : lncount); + Fseek (file, line3); + if (noscroll) + if (clreol) { + home (); + cleareol (); + } + else + doclear (); + } + else { + kill_line (); + if (noscroll) + if (clreol) { + home (); + cleareol (); + } + else + doclear (); + pr (Line); + putchar ('\n'); + } + break; + } + else if (rv == -1) + error ("Regular expression botch"); + } + if (feof (file)) { + if (!no_intty) { +#ifndef __linux__ + /* No longer in libc 4.5.8. . . */ + file->_flags &= ~STDIO_S_EOF_SEEN; /* why doesn't fseek do this ??!!??! */ +#endif + Currline = saveln; + Fseek (file, startline); + } + else { + pr ("\nPattern not found\n"); + end_it (); + } + error ("Pattern not found"); + } +} + +/*VARARGS2*/ +execute (filename, cmd, va_alist) +char *filename; +char *cmd; +va_dcl +{ + int id; + int n; + va_list argp; + + fflush (stdout); + reset_tty (); + for (n = 10; (id = fork ()) < 0 && n > 0; n--) + sleep (5); + if (id == 0) { + if (!isatty(0)) { + close(0); + open("/dev/tty", 0); + } + va_start(argp); + execv (cmd, argp); + write (2, "exec failed\n", 12); + exit (1); + va_end(argp); /* balance {}'s for some UNIX's */ + } + if (id > 0) { + signal (SIGINT, SIG_IGN); + signal (SIGQUIT, SIG_IGN); + if (catch_susp) + signal(SIGTSTP, SIG_DFL); + while (wait(0) > 0); + signal (SIGINT, end_it); + signal (SIGQUIT, onquit); + if (catch_susp) + signal(SIGTSTP, onsusp); + } else + write(2, "can't fork\n", 11); + set_tty (); + pr ("------------------------\n"); + prompt (filename); +} +/* +** Skip n lines in the file f +*/ + +void skiplns (register int n, register FILE *f) +{ + register char c; + + while (n > 0) { + while ((c = Getc (f)) != '\n') + if (c == EOF) + return; + n--; + Currline++; + } +} + +/* +** Skip nskip files in the file list (from the command line). Nskip may be +** negative. +*/ + +skipf (nskip) +register int nskip; +{ + if (nskip == 0) return; + if (nskip > 0) { + if (fnum + nskip > nfiles - 1) + nskip = nfiles - fnum - 1; + } + else if (within) + ++fnum; + fnum += nskip; + if (fnum < 0) + fnum = 0; + pr ("\n...Skipping "); + pr ("\n"); + if (clreol) + cleareol (); + pr ("...Skipping "); + pr (nskip > 0 ? "to file " : "back to file "); + pr (fnames[fnum]); + pr ("\n"); + if (clreol) + cleareol (); + pr ("\n"); + --fnum; +} + +/*----------------------------- Terminal I/O -------------------------------*/ + +void initterm() +{ + char buf[TBUFSIZ]; + static char clearbuf[TBUFSIZ]; + char *clearptr, *padstr; + int ldisc; + int lmode; + char *term; + int tgrp; + struct winsize win; + +retry: + no_tty = ioctl(fileno(stdout), TCGETA, &otty); + if (!no_tty) { + docrterase = (otty.c_cc[VERASE] != 255); + docrtkill = (otty.c_cc[VKILL] != 255); +#ifdef undef + /* + * Wait until we're in the foreground before we save the + * the terminal modes. + */ + if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) { + perror("TIOCGPGRP"); + exit(1); + } + if (tgrp != getpgrp(0)) { + kill(0, SIGTTOU); + goto retry; + } +#endif + if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) { + dumb++; ul_opt = 0; + } + else { +#ifdef TIOCGWINSZ + if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) { +#endif + Lpp = tgetnum("li"); + Mcol = tgetnum("co"); +#ifdef TIOCGWINSZ + } else { + if ((Lpp = win.ws_row) == 0) + Lpp = tgetnum("li"); + if ((Mcol = win.ws_col) == 0) + Mcol = tgetnum("co"); + } +#endif + if ((Lpp <= 0) || tgetflag("hc")) { + hard++; /* Hard copy terminal */ + Lpp = 24; + } + if (tgetflag("xn")) + eatnl++; /* Eat newline at last column + 1; dec, concept */ + if (Mcol <= 0) + Mcol = 80; + + if (tailequ (fnames[0], "page") || !hard && tgetflag("ns")) + noscroll++; + Wrap = tgetflag("am"); + bad_so = tgetflag ("xs"); + clearptr = clearbuf; + eraseln = tgetstr("ce",&clearptr); + Clear = tgetstr("cl", &clearptr); + Senter = tgetstr("so", &clearptr); + Sexit = tgetstr("se", &clearptr); + if ((soglitch = tgetnum("sg")) < 0) + soglitch = 0; + + /* + * Set up for underlining: some terminals don't need it; + * others have start/stop sequences, still others have an + * underline char sequence which is assumed to move the + * cursor forward one character. If underline sequence + * isn't available, settle for standout sequence. + */ + + if (tgetflag("ul") || tgetflag("os")) + ul_opt = 0; + if ((chUL = tgetstr("uc", &clearptr)) == NULL ) + chUL = ""; + if (((ULenter = tgetstr("us", &clearptr)) == NULL || + (ULexit = tgetstr("ue", &clearptr)) == NULL) && !*chUL) { + if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) { + ULenter = ""; + ULexit = ""; + } else + ulglitch = soglitch; + } else { + if ((ulglitch = tgetnum("ug")) < 0) + ulglitch = 0; + } + + if (padstr = tgetstr("pc", &clearptr)) + PC = *padstr; + Home = tgetstr("ho",&clearptr); + if (Home == 0 || *Home == '\0') + { + if ((cursorm = tgetstr("cm", &clearptr)) != NULL) { + strcpy(cursorhome, tgoto(cursorm, 0, 0)); + Home = cursorhome; + } + } + EodClr = tgetstr("cd", &clearptr); + if ((chBS = tgetstr("bc", &clearptr)) == NULL) + chBS = "\b"; + + } + if ((shell = getenv("SHELL")) == NULL) + shell = "/bin/sh"; + } + no_intty = ioctl(fileno(stdin), TCGETA, &otty); + ioctl(fileno(stderr), TCGETA, &otty); + savetty = otty; + slow_tty = (otty.c_cflag & CBAUD) < B1200; + hardtabs = (otty.c_oflag & TABDLY) != XTABS; + if (!no_tty) + otty.c_lflag &= ~(ICANON|ECHO); +} + +readch () +{ + char ch; + extern int errno; + + errno = 0; + if (read (2, &ch, 1) <= 0) + if (errno != EINTR) + end_it(); + else + ch = otty.c_cc[VKILL]; + return (ch); +} + +static char BS = '\b'; +static char *BSB = "\b \b"; +static char CARAT = '^'; +#define ERASEONECHAR \ + if (docrterase) \ + write (2, BSB, sizeof(BSB)); \ + else \ + write (2, &BS, sizeof(BS)); + +ttyin (buf, nmax, pchar) +char buf[]; +register int nmax; +char pchar; +{ + register char *sptr; + register char ch; + register int slash = 0; + int maxlen; + char cbuf; + + sptr = buf; + maxlen = 0; + while (sptr - buf < nmax) { + if (promptlen > maxlen) maxlen = promptlen; + ch = readch (); + if (ch == '\\') { + slash++; + } + else if ((ch == otty.c_cc[VERASE]) && !slash) { + if (sptr > buf) { + --promptlen; + ERASEONECHAR + --sptr; + if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) { + --promptlen; + ERASEONECHAR + } + continue; + } + else { + if (!eraseln) promptlen = maxlen; + longjmp (restore, 1); + } + } + else if ((ch == otty.c_cc[VKILL]) && !slash) { + if (hard) { + show (ch); + putchar ('\n'); + putchar (pchar); + } + else { + putchar ('\r'); + putchar (pchar); + if (eraseln) + erase (1); + else if (docrtkill) + while (promptlen-- > 1) + write (2, BSB, sizeof(BSB)); + promptlen = 1; + } + sptr = buf; + fflush (stdout); + continue; + } + if (slash && (ch == otty.c_cc[VKILL] || ch == otty.c_cc[VERASE])) { + ERASEONECHAR + --sptr; + } + if (ch != '\\') + slash = 0; + *sptr++ = ch; + if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { + ch += ch == RUBOUT ? -0100 : 0100; + write (2, &CARAT, 1); + promptlen++; + } + cbuf = ch; + if (ch != '\n' && ch != ESC) { + write (2, &cbuf, 1); + promptlen++; + } + else + break; + } + *--sptr = '\0'; + if (!eraseln) promptlen = maxlen; + if (sptr - buf >= nmax - 1) + error ("Line too long"); +} + +expand (outbuf, inbuf) +char *outbuf; +char *inbuf; +{ + register char *instr; + register char *outstr; + register char ch; + char temp[200]; + int changed = 0; + + instr = inbuf; + outstr = temp; + while ((ch = *instr++) != '\0') + switch (ch) { + case '%': + if (!no_intty) { + strcpy (outstr, fnames[fnum]); + outstr += strlen (fnames[fnum]); + changed++; + } + else + *outstr++ = ch; + break; + case '!': + if (!shellp) + error ("No previous command to substitute for"); + strcpy (outstr, shell_line); + outstr += strlen (shell_line); + changed++; + break; + case '\\': + if (*instr == '%' || *instr == '!') { + *outstr++ = *instr++; + break; + } + default: + *outstr++ = ch; + } + *outstr++ = '\0'; + strcpy (outbuf, temp); + return (changed); +} + +show (ch) +register char ch; +{ + char cbuf; + + if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { + ch += ch == RUBOUT ? -0100 : 0100; + write (2, &CARAT, 1); + promptlen++; + } + cbuf = ch; + write (2, &cbuf, 1); + promptlen++; +} + +error (mess) +char *mess; +{ + if (clreol) + cleareol (); + else + kill_line (); + promptlen += strlen (mess); + if (Senter && Sexit) { + tputs (Senter, 1, putch); + pr(mess); + tputs (Sexit, 1, putch); + } + else + pr (mess); + fflush(stdout); + errors++; + longjmp (restore, 1); +} + + +set_tty () +{ + otty.c_lflag &= ~(ICANON|ECHO); + stty(fileno(stderr), &otty); +} + +void reset_tty () +{ + if (no_tty) + return; + if (pstate) { + tputs(ULexit, 1, putch); + fflush(stdout); + pstate = 0; + } + otty.c_lflag |= ICANON|ECHO; + stty(fileno(stderr), &savetty); +} + +rdline (f) +register FILE *f; +{ + register char c; + register char *p; + + p = Line; + while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) + *p++ = c; + if (c == '\n') + Currline++; + *p = '\0'; +} + +/* Come here when we get a suspend signal from the terminal */ + +void onsusp () +{ + /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ + signal(SIGTTOU, SIG_IGN); + reset_tty (); + fflush (stdout); + signal(SIGTTOU, SIG_DFL); + /* Send the TSTP signal to suspend our process group */ + signal(SIGTSTP, SIG_DFL); +/* sigsetmask(0);*/ + kill (0, SIGTSTP); + /* Pause for station break */ + + /* We're back */ + signal (SIGTSTP, onsusp); + set_tty (); + if (inwait) + longjmp (restore, 1); +} diff --git a/text-utils/more.help b/text-utils/more.help new file mode 100644 index 000000000..bd415cfb1 --- /dev/null +++ b/text-utils/more.help @@ -0,0 +1,24 @@ + +Most commands optionally preceded by integer argument k. Defaults in brackets. +Star (*) indicates argument becomes new default. +------------------------------------------------------------------------------- +<space> Display next k lines of text [current screen size] +z Display next k lines of text [current screen size]* +<return> Display next k lines of text [1]* +d or ctrl-D Scroll k lines [current scroll size, initially 11]* +q or Q or <interrupt> Exit from more +s Skip forward k lines of text [1] +f Skip forward k screenfuls of text [1] +b or ctrl-B Skip backwards k screenfuls of text [1] +' Go to place where previous search started += Display current line number +/<regular expression> Search for kth occurrence of regular expression [1] +n Search for kth occurrence of last r.e [1] +!<cmd> or :!<cmd> Execute <cmd> in a subshell +v Start up /usr/bin/vi at current line +ctrl-L Redraw screen +:n Go to kth next file [1] +:p Go to kth previous file [1] +:f Display current file name and line number +. Repeat previous command +------------------------------------------------------------------------------- diff --git a/text-utils/od.1 b/text-utils/od.1 new file mode 100644 index 000000000..dab6da732 --- /dev/null +++ b/text-utils/od.1 @@ -0,0 +1,76 @@ +.\" Copyright (c) 1990, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)od.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd %Q +.Os +.Dt OD 1 +.Sh NAME +.Nm od +.Nd octal, decimal, hex, ascii dump +.Sh SYNOPSIS +.Nm od +.Op Fl aBbcDdeFfHhIiLlOovXx +.Sm off +.Oo +.Op Cm \&+ +.Li offset +.Op Cm \&. +.Op Cm Bb +.Oc +.Ar file +.Sh DESCRIPTION +.Nm Od +has been deprecated in favor of +.Xr hexdump 1 . +.Pp +.Xr Hexdump , +if called as +.Nm od , +provides compatibility for the options listed above. +.Pp +It does not provide compatibility for the +.Fl s +option (see +.Xr strings 1 ) +or the +.Fl P , +.Fl p , +or +.Fl w +options, nor is compatibility provided for the ``label'' component +of the offset syntax. +.Sh SEE ALSO +.Xr hexdump 1 , +.Xr strings 1 +.Sh BUGS +Quite a few. diff --git a/text-utils/odsyntax.c b/text-utils/odsyntax.c new file mode 100644 index 000000000..2dd5a2a26 --- /dev/null +++ b/text-utils/odsyntax.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)odsyntax.c 5.4 (Berkeley) 3/8/91"; +#endif /* not lint */ + +#include <sys/types.h> +#include <stdlib.h> +#include <stdio.h> +#include "hexdump.h" + +int deprecated; + +oldsyntax(argc, argvp) + int argc; + char ***argvp; +{ + extern enum _vflag vflag; + extern FS *fshead; + extern char *optarg; + extern int length, optind; + int ch; + char **argv; + static void odprecede(); + + deprecated = 1; + argv = *argvp; + while ((ch = getopt(argc, argv, "aBbcDdeFfHhIiLlOoPpswvXx")) != EOF) + switch (ch) { + case 'a': + odprecede(); + add("16/1 \"%3_u \" \"\\n\""); + break; + case 'B': + case 'o': + odprecede(); + add("8/2 \" %06o \" \"\\n\""); + break; + case 'b': + odprecede(); + add("16/1 \"%03o \" \"\\n\""); + break; + case 'c': + odprecede(); + add("16/1 \"%3_c \" \"\\n\""); + break; + case 'd': + odprecede(); + add("8/2 \" %05u \" \"\\n\""); + break; + case 'D': + odprecede(); + add("4/4 \" %010u \" \"\\n\""); + break; + case 'e': /* undocumented in od */ + case 'F': + odprecede(); + add("2/8 \" %21.14e \" \"\\n\""); + break; + + case 'f': + odprecede(); + add("4/4 \" %14.7e \" \"\\n\""); + break; + case 'H': + case 'X': + odprecede(); + add("4/4 \" %08x \" \"\\n\""); + break; + case 'h': + case 'x': + odprecede(); + add("8/2 \" %04x \" \"\\n\""); + break; + case 'I': + case 'L': + case 'l': + odprecede(); + add("4/4 \" %11d \" \"\\n\""); + break; + case 'i': + odprecede(); + add("8/2 \" %6d \" \"\\n\""); + break; + case 'O': + odprecede(); + add("4/4 \" %011o \" \"\\n\""); + break; + case 'v': + vflag = ALL; + break; + case 'P': + case 'p': + case 's': + case 'w': + case '?': + default: + (void)fprintf(stderr, + "od: od(1) has been deprecated for hexdump(1).\n"); + if (ch != '?') + (void)fprintf(stderr, +"od: hexdump(1) compatibility doesn't support the -%c option%s\n", + ch, ch == 's' ? "; see strings(1)." : "."); + usage(); + } + + if (!fshead) { + add("\"%07.7_Ao\n\""); + add("\"%07.7_ao \" 8/2 \"%06o \" \"\\n\""); + } + + argc -= optind; + *argvp += optind; + + odoffset(argc, argvp); +} + +#define ishexdigit(c) \ + (c >= '0' && c <= '9' || c >= 'a' && c <= 'f' || c >= 'A' && c <= 'F') + +odoffset(argc, argvp) + int argc; + char ***argvp; +{ + extern off_t skip; + register char *num, *p; + int base; + char *end; + + /* + * The offset syntax of od(1) was genuinely bizarre. First, if + * it started with a plus it had to be an offset. Otherwise, if + * there were at least two arguments, a number or lower-case 'x' + * followed by a number makes it an offset. By default it was + * octal; if it started with 'x' or '0x' it was hex. If it ended + * in a '.', it was decimal. If a 'b' or 'B' was appended, it + * multiplied the number by 512 or 1024 byte units. There was + * no way to assign a block count to a hex offset. + * + * We assumes it's a file if the offset is bad. + */ + p = **argvp; + if (*p != '+' && (argc < 2 || + (!isdigit(p[0]) && (p[0] != 'x' || !ishexdigit(p[1]))))) + return; + + base = 0; + /* + * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and + * set base. + */ + if (p[0] == '+') + ++p; + if (p[0] == 'x' && ishexdigit(p[1])) { + ++p; + base = 16; + } else if (p[0] == '0' && p[1] == 'x') { + p += 2; + base = 16; + } + + /* skip over the number */ + if (base == 16) + for (num = p; ishexdigit(*p); ++p); + else + for (num = p; isdigit(*p); ++p); + + /* check for no number */ + if (num == p) + return; + + /* if terminates with a '.', base is decimal */ + if (*p == '.') { + if (base) + return; + base = 10; + } + + skip = strtol(num, &end, base ? base : 8); + + /* if end isn't the same as p, we got a non-octal digit */ + if (end != p) + skip = 0; + else { + if (*p) { + if (*p == 'b') + skip *= 512; + else if (*p == 'B') + skip *= 1024; + ++p; + } + if (*p) + skip = 0; + else { + ++*argvp; + /* + * If the offset uses a non-octal base, the base of + * the offset is changed as well. This isn't pretty, + * but it's easy. + */ +#define TYPE_OFFSET 7 + if (base == 16) { + fshead->nextfu->fmt[TYPE_OFFSET] = 'x'; + fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x'; + } else if (base == 10) { + fshead->nextfu->fmt[TYPE_OFFSET] = 'd'; + fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd'; + } + } + } +} + +static void +odprecede() +{ + static int first = 1; + + if (first) { + first = 0; + add("\"%07.7_Ao\n\""); + add("\"%07.7_ao \""); + } else + add("\" \""); +} diff --git a/text-utils/parse.c b/text-utils/parse.c new file mode 100644 index 000000000..e0d982e1a --- /dev/null +++ b/text-utils/parse.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char sccsid[] = "@(#)parse.c 5.6 (Berkeley) 3/9/91"; +#endif /* not lint */ + +#include <sys/types.h> +#include <sys/file.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include "hexdump.h" + +FU *endfu; /* format at end-of-data */ + +addfile(name) + char *name; +{ + register char *p; + FILE *fp; + int ch; + char buf[2048 + 1]; + + if (!(fp = fopen(name, "r"))) { + (void)fprintf(stderr, "hexdump: can't read %s.\n", name); + exit(1); + } + while (fgets(buf, sizeof(buf), fp)) { + if (!(p = index(buf, '\n'))) { + (void)fprintf(stderr, "hexdump: line too long.\n"); + while ((ch = getchar()) != '\n' && ch != EOF); + continue; + } + *p = '\0'; + for (p = buf; *p && isspace(*p); ++p); + if (!*p || *p == '#') + continue; + add(p); + } + (void)fclose(fp); +} + +add(fmt) + char *fmt; +{ + register char *p; + static FS **nextfs; + FS *tfs; + FU *tfu, **nextfu; + char *savep, *emalloc(); + + /* start new linked list of format units */ + /* NOSTRICT */ + tfs = (FS *)emalloc(sizeof(FS)); + if (!fshead) + fshead = tfs; + else + *nextfs = tfs; + nextfs = &tfs->nextfs; + nextfu = &tfs->nextfu; + + /* take the format string and break it up into format units */ + for (p = fmt;;) { + /* skip leading white space */ + for (; isspace(*p); ++p); + if (!*p) + break; + + /* allocate a new format unit and link it in */ + /* NOSTRICT */ + tfu = (FU *)emalloc(sizeof(FU)); + *nextfu = tfu; + nextfu = &tfu->nextfu; + tfu->reps = 1; + + /* if leading digit, repetition count */ + if (isdigit(*p)) { + for (savep = p; isdigit(*p); ++p); + if (!isspace(*p) && *p != '/') + badfmt(fmt); + /* may overwrite either white space or slash */ + tfu->reps = atoi(savep); + tfu->flags = F_SETREP; + /* skip trailing white space */ + for (++p; isspace(*p); ++p); + } + + /* skip slash and trailing white space */ + if (*p == '/') + while (isspace(*++p)); + + /* byte count */ + if (isdigit(*p)) { + for (savep = p; isdigit(*p); ++p); + if (!isspace(*p)) + badfmt(fmt); + tfu->bcnt = atoi(savep); + /* skip trailing white space */ + for (++p; isspace(*p); ++p); + } + + /* format */ + if (*p != '"') + badfmt(fmt); + for (savep = ++p; *p != '"';) + if (*p++ == 0) + badfmt(fmt); + if (!(tfu->fmt = malloc(p - savep + 1))) + nomem(); + (void) strncpy(tfu->fmt, savep, p - savep); + tfu->fmt[p - savep] = '\0'; + escape(tfu->fmt); + p++; + } +} + +static char *spec = ".#-+ 0123456789"; +size(fs) + FS *fs; +{ + register FU *fu; + register int bcnt, cursize; + register char *fmt; + int prec; + + /* figure out the data block size needed for each format unit */ + for (cursize = 0, fu = fs->nextfu; fu; fu = fu->nextfu) { + if (fu->bcnt) { + cursize += fu->bcnt * fu->reps; + continue; + } + for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) { + if (*fmt != '%') + continue; + /* + * skip any special chars -- save precision in + * case it's a %s format. + */ + while (index(spec + 1, *++fmt)); + if (*fmt == '.' && isdigit(*++fmt)) { + prec = atoi(fmt); + while (isdigit(*++fmt)); + } + switch(*fmt) { + case 'c': + bcnt += 1; + break; + case 'd': case 'i': case 'o': case 'u': + case 'x': case 'X': + bcnt += 4; + break; + case 'e': case 'E': case 'f': case 'g': case 'G': + bcnt += 8; + break; + case 's': + bcnt += prec; + break; + case '_': + switch(*++fmt) { + case 'c': case 'p': case 'u': + bcnt += 1; + break; + } + } + } + cursize += bcnt * fu->reps; + } + return(cursize); +} + +rewrite(fs) + FS *fs; +{ + enum { NOTOKAY, USEBCNT, USEPREC } sokay; + register PR *pr, **nextpr; + register FU *fu; + register char *p1, *p2; + char savech, *fmtp; + int nconv, prec; + + for (fu = fs->nextfu; fu; fu = fu->nextfu) { + /* + * break each format unit into print units; each + * conversion character gets its own. + */ + for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) { + /* NOSTRICT */ + pr = (PR *)emalloc(sizeof(PR)); + if (!fu->nextpr) + fu->nextpr = pr; + else + *nextpr = pr; + + /* skip preceding text and up to the next % sign */ + for (p1 = fmtp; *p1 && *p1 != '%'; ++p1); + + /* only text in the string */ + if (!*p1) { + pr->fmt = fmtp; + pr->flags = F_TEXT; + break; + } + + /* + * get precision for %s -- if have a byte count, don't + * need it. + */ + if (fu->bcnt) { + sokay = USEBCNT; + /* skip to conversion character */ + for (++p1; index(spec, *p1); ++p1); + } else { + /* skip any special chars, field width */ + while (index(spec + 1, *++p1)); + if (*p1 == '.' && isdigit(*++p1)) { + sokay = USEPREC; + prec = atoi(p1); + while (isdigit(*++p1)); + } + else + sokay = NOTOKAY; + } + + p2 = p1 + 1; /* set end pointer */ + + /* + * figure out the byte count for each conversion; + * rewrite the format as necessary, set up blank- + * padding for end of data. + */ + switch(*p1) { + case 'c': + pr->flags = F_CHAR; + switch(fu->bcnt) { + case 0: case 1: + pr->bcnt = 1; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + break; + case 'd': case 'i': + pr->flags = F_INT; + goto sw1; + case 'l': + ++p2; + switch(p1[1]) { + case 'd': case 'i': + ++p1; + pr->flags = F_INT; + goto sw1; + case 'o': case 'u': case 'x': case 'X': + ++p1; + pr->flags = F_UINT; + goto sw1; + default: + p1[2] = '\0'; + badconv(p1); + } + /* NOTREACHED */ + case 'o': case 'u': case 'x': case 'X': + pr->flags = F_UINT; +sw1: switch(fu->bcnt) { + case 0: case 4: + pr->bcnt = 4; + break; + case 1: + pr->bcnt = 1; + break; + case 2: + pr->bcnt = 2; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + break; + case 'e': case 'E': case 'f': case 'g': case 'G': + pr->flags = F_DBL; + switch(fu->bcnt) { + case 0: case 8: + pr->bcnt = 8; + break; + case 4: + pr->bcnt = 4; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + break; + case 's': + pr->flags = F_STR; + switch(sokay) { + case NOTOKAY: + badsfmt(); + case USEBCNT: + pr->bcnt = fu->bcnt; + break; + case USEPREC: + pr->bcnt = prec; + break; + } + break; + case '_': + ++p2; + switch(p1[1]) { + case 'A': + endfu = fu; + fu->flags |= F_IGNORE; + /* FALLTHROUGH */ + case 'a': + pr->flags = F_ADDRESS; + ++p2; + switch(p1[2]) { + case 'd': case 'o': case'x': + *p1 = p1[2]; + break; + default: + p1[3] = '\0'; + badconv(p1); + } + break; + case 'c': + pr->flags = F_C; + /* *p1 = 'c'; set in conv_c */ + goto sw2; + case 'p': + pr->flags = F_P; + *p1 = 'c'; + goto sw2; + case 'u': + pr->flags = F_U; + /* *p1 = 'c'; set in conv_u */ +sw2: switch(fu->bcnt) { + case 0: case 1: + pr->bcnt = 1; + break; + default: + p1[2] = '\0'; + badcnt(p1); + } + break; + default: + p1[2] = '\0'; + badconv(p1); + } + break; + default: + p1[1] = '\0'; + badconv(p1); + } + + /* + * copy to PR format string, set conversion character + * pointer, update original. + */ + savech = *p2; + p1[1] = '\0'; + if (!(pr->fmt = strdup(fmtp))) + nomem(); + *p2 = savech; + pr->cchar = pr->fmt + (p1 - fmtp); + fmtp = p2; + + /* only one conversion character if byte count */ + if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) { + (void)fprintf(stderr, + "hexdump: byte count with multiple conversion characters.\n"); + exit(1); + } + } + /* + * if format unit byte count not specified, figure it out + * so can adjust rep count later. + */ + if (!fu->bcnt) + for (pr = fu->nextpr; pr; pr = pr->nextpr) + fu->bcnt += pr->bcnt; + } + /* + * if the format string interprets any data at all, and it's + * not the same as the blocksize, and its last format unit + * interprets any data at all, and has no iteration count, + * repeat it as necessary. + * + * if, rep count is greater than 1, no trailing whitespace + * gets output from the last iteration of the format unit. + */ + for (fu = fs->nextfu;; fu = fu->nextfu) { + if (!fu->nextfu && fs->bcnt < blocksize && + !(fu->flags&F_SETREP) && fu->bcnt) + fu->reps += (blocksize - fs->bcnt) / fu->bcnt; + if (fu->reps > 1) { + for (pr = fu->nextpr;; pr = pr->nextpr) + if (!pr->nextpr) + break; + for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) + p2 = isspace(*p1) ? p1 : NULL; + if (p2) + pr->nospace = p2; + } + if (!fu->nextfu) + break; + } +} + + +escape(p1) + register char *p1; +{ + register char *p2; + + /* alphabetic escape sequences have to be done in place */ + for (p2 = p1;; ++p1, ++p2) { + if (!*p1) { + *p2 = *p1; + break; + } + if (*p1 == '\\') + switch(*++p1) { + case 'a': + /* *p2 = '\a'; */ + *p2 = '\007'; + break; + case 'b': + *p2 = '\b'; + break; + case 'f': + *p2 = '\f'; + break; + case 'n': + *p2 = '\n'; + break; + case 'r': + *p2 = '\r'; + break; + case 't': + *p2 = '\t'; + break; + case 'v': + *p2 = '\v'; + break; + default: + *p2 = *p1; + break; + } + } +} + +badcnt(s) + char *s; +{ + (void)fprintf(stderr, + "hexdump: bad byte count for conversion character %s.\n", s); + exit(1); +} + +badsfmt() +{ + (void)fprintf(stderr, + "hexdump: %%s requires a precision or a byte count.\n"); + exit(1); +} + +badfmt(fmt) + char *fmt; +{ + (void)fprintf(stderr, "hexdump: bad format {%s}\n", fmt); + exit(1); +} + +badconv(ch) + char *ch; +{ + (void)fprintf(stderr, "hexdump: bad conversion character %%%s.\n", ch); + exit(1); +} diff --git a/text-utils/rev.1 b/text-utils/rev.1 new file mode 100644 index 000000000..5503a94a8 --- /dev/null +++ b/text-utils/rev.1 @@ -0,0 +1,51 @@ +.\" Copyright (c) 1985, 1992 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)rev.1 6.3 (Berkeley) 3/21/92 +.\" Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu) +.\" and Brian Koehmstedt (bpk@gnu.ai.mit.edu) +.\" rev.1,v 1.1.1.1 1995/02/22 19:09:19 faith Exp +.\" +.Dd March 21, 1992 +.Dt REV 1 +.Os +.Sh NAME +.Nm rev +.Nd reverse lines of a file +.Sh SYNOPSIS +.Nm rev +.Op Ar file +.Sh DESCRIPTION +The +.Nm rev +utility copies the specified files to the standard output, reversing the +order of characters in every line. +If no files are specified, the standard input is read. diff --git a/text-utils/rev.c b/text-utils/rev.c new file mode 100644 index 000000000..9fd22e0f3 --- /dev/null +++ b/text-utils/rev.c @@ -0,0 +1,159 @@ +/*- + * Copyright (c) 1987, 1992 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Modified for Linux by Charles Hannum (mycroft@gnu.ai.mit.edu) + * and Brian Koehmstedt (bpk@gnu.ai.mit.edu) + * + * Wed Sep 14 22:26:00 1994: Patch from bjdouma <bjdouma@xs4all.nl> to handle + * last line that has no newline correctly. + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1987, 1992 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +/*static char sccsid[] = "from: @(#)rev.c 5.2 (Berkeley) 3/21/92";*/ +static char rcsid[] = "rev.c,v 1.1.1.1 1995/02/22 19:09:19 faith Exp"; +#endif /* not lint */ + +#include <sys/types.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifdef linux +#include <unistd.h> +#endif /* linux */ + +void usage __P((void)); +void warn __P((const char *, ...)); + +int +main(argc, argv) + int argc; + char *argv[]; +{ + register char *filename, *t; +#ifdef linux + char p[512]; +#else /* linux */ + char *p; +#endif /* linux */ + FILE *fp; + size_t len; + int ch, rval; + + while ((ch = getopt(argc, argv, "")) != EOF) + switch(ch) { + case '?': + default: + usage(); + } + + argc -= optind; + argv += optind; + + fp = stdin; + filename = "stdin"; + rval = 0; + do { + if (*argv) { + if ((fp = fopen(*argv, "r")) == NULL) { + warn("%s: %s", *argv, strerror(errno)); + rval = 1; + ++argv; + continue; + } + filename = *argv++; + } +#ifndef linux + while (p = fgetline(fp, &len)) { + t = p + len - 1; + for (t = p + len - 1; t >= p; --t) + putchar(*t); + } +#else /* linux */ + while (fgets(p, 511, fp)) { + len = strlen(p); + t = p + len - 1 - (*(p+len-1)=='\r' + || *(p+len-1)=='\n'); + for ( ; t >= p; --t) + if(strcmp(t, '\0') != 0) + putchar(*t); +#endif /* linux */ + putchar('\n'); + } + if (ferror(fp)) { + warn("%s: %s", filename, strerror(errno)); + rval = 1; + } + (void)fclose(fp); + } while(*argv); + exit(rval); +} + +#if __STDC__ +#include <stdarg.h> +#else +#include <varargs.h> +#endif + +void +#if __STDC__ +warn(const char *fmt, ...) +#else +warn(fmt, va_alist) + char *fmt; + va_dcl +#endif +{ + va_list ap; +#if __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)fprintf(stderr, "rev: "); + (void)vfprintf(stderr, fmt, ap); + va_end(ap); + (void)fprintf(stderr, "\n"); +} + +void +usage() +{ + (void)fprintf(stderr, "usage: rev [file ...]\n"); + exit(1); +} diff --git a/text-utils/strings.1 b/text-utils/strings.1 new file mode 100644 index 000000000..08dda5bfd --- /dev/null +++ b/text-utils/strings.1 @@ -0,0 +1,96 @@ +.\" Copyright (c) 1980, 1990 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)strings.1 6.11 (Berkeley) 5/9/91 +.\" +.Dd May 9, 1991 +.Dt STRINGS 1 +.Os BSD 3 +.Sh NAME +.Nm strings +.Nd find printable strings in a file +.Sh SYNOPSIS +.Nm strings +.Op Fl afo +.Op Fl n Ar number +.Op Ar file ... +.Sh DESCRIPTION +.Nm Strings +displays the sequences of printable characters in each of the specified +files, or in the standard input, by default. +By default, a sequence must be at least four characters in length +before being displayed. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a +By default, +.Nm strings +only searches the text and data segments of object files. +The +.Fl a +option causes +.Nm strings +to search the entire object file. +.It Fl f +Each string is preceded by the name of the file +in which it was found. +.It Fl n +Specifies the minimum number of characters in a sequence to be +.Ar number , +instead of four. +.It Fl o +Each string is preceded by its decimal offset in the +file. +.El +.Pp +.Nm Strings +is useful for identifying random binaries, among other things. +.Sh SEE ALSO +.Xr hexdump 1 +.Sh BUGS +The algorithm for identifying strings is extremely primitive. +In particular, machine code instructions on certain architectures +can resemble sequences of ASCII bytes, which +will fool the algorithm. +.Sh COMPATIBILITY +Historic implementations of +.Nm +only search the initialized data portion of the object file. +This was reasonable as strings were normally stored there. +Given new compiler technology which installs strings in the +text portion of the object file, the default behavior was +changed. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/text-utils/strings.c b/text-utils/strings.c new file mode 100644 index 000000000..cbcda818a --- /dev/null +++ b/text-utils/strings.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 1980, 1987 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Wed Jun 22 22:22:37 1994, faith@cs.unc.edu: + * Added internationalization patches from Vitor Duarte <vad@fct.unl.pt> + */ + +#ifndef lint +char copyright[] = +"@(#) Copyright (c) 1980, 1987 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)strings.c 5.10 (Berkeley) 5/23/91"; +#endif /* not lint */ + +#include <sys/types.h> +#include <fcntl.h> +#include <errno.h> +#include <a.out.h> +#include <unistd.h> +#include <stdio.h> +#include <ctype.h> +#include <stdlib.h> +#include <string.h> +#include <locale.h> + +#define DEF_LEN 4 /* default minimum string length */ +#if 0 +#define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t')) +#else +#define ISSTR(ch) (isprint(ch) || ch == '\t') +#endif + +typedef struct exec EXEC; /* struct exec cast */ + +static long foff; /* offset in the file */ +static int hcnt, /* head count */ + head_len, /* length of header */ + read_len; /* length to read */ +static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */ + +static void usage(); + +main(argc, argv) + int argc; + char **argv; +{ + extern char *optarg; + extern int optind; + register int ch, cnt; + register u_char *C; + EXEC *head; + int exitcode, minlen; + short asdata, oflg, fflg; + u_char *bfr; + char *file, *p; + + setlocale(LC_CTYPE, ""); + + + /* + * for backward compatibility, allow '-' to specify 'a' flag; no + * longer documented in the man page or usage string. + */ + asdata = exitcode = fflg = oflg = 0; + minlen = -1; + while ((ch = getopt(argc, argv, "-0123456789an:of")) != EOF) + switch((char)ch) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + /* + * kludge: strings was originally designed to take + * a number after a dash. + */ + if (minlen == -1) { + p = argv[optind - 1]; + if (p[0] == '-' && p[1] == ch && !p[2]) + minlen = atoi(++p); + else + minlen = atoi(argv[optind] + 1); + } + break; + case '-': + case 'a': + asdata = 1; + break; + case 'f': + fflg = 1; + break; + case 'n': + minlen = atoi(optarg); + break; + case 'o': + oflg = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + if (minlen == -1) + minlen = DEF_LEN; + + if (!(bfr = malloc((u_int)minlen))) { + (void)fprintf(stderr, "strings: %s\n", strerror(errno)); + exit(1); + } + bfr[minlen] = '\0'; + file = "stdin"; + do { + if (*argv) { + file = *argv++; + if (!freopen(file, "r", stdin)) { + (void)fprintf(stderr, + "strings; %s: %s\n", file, strerror(errno)); + exitcode = 1; + goto nextfile; + } + } + foff = 0; +#define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;} + read_len = -1; + if (asdata) + DO_EVERYTHING() + else { + head = (EXEC *)hbfr; + if ((head_len = + read(fileno(stdin), head, sizeof(EXEC))) == -1) + DO_EVERYTHING() + if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) { + foff = N_TXTOFF(*head); + if (fseek(stdin, foff, SEEK_SET) == -1) + DO_EVERYTHING() + read_len = head->a_text + head->a_data; + head_len = 0; + } + else + hcnt = 0; + } +start: + for (cnt = 0; (ch = getch()) != EOF;) { + if (ISSTR(ch)) { + if (!cnt) + C = bfr; + *C++ = ch; + if (++cnt < minlen) + continue; + if (fflg) + printf("%s:", file); + if (oflg) + printf("%07ld %s", + foff - minlen, (char *)bfr); + else + printf("%s", bfr); + while ((ch = getch()) != EOF && ISSTR(ch)) + putchar((char)ch); + putchar('\n'); + } + cnt = 0; + } +nextfile: ; + } while (*argv); + exit(exitcode); +} + +/* + * getch -- + * get next character from wherever + */ +getch() +{ + ++foff; + if (head_len) { + if (hcnt < head_len) + return((int)hbfr[hcnt++]); + head_len = 0; + } + if (read_len == -1 || read_len-- > 0) + return(getchar()); + return(EOF); +} + +static void +usage() +{ + (void)fprintf(stderr, + "usage: strings [-afo] [-n length] [file ... ]\n"); + exit(1); +} diff --git a/text-utils/ul.1 b/text-utils/ul.1 new file mode 100644 index 000000000..701797ae4 --- /dev/null +++ b/text-utils/ul.1 @@ -0,0 +1,107 @@ +.\" Copyright (c) 1980, 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)ul.1 8.1 (Berkeley) 6/6/93 +.\" +.Dd June 6, 1993 +.Dt UL 1 +.Os BSD 4 +.Sh NAME +.Nm ul +.Nd do underlining +.Sh SYNOPSIS +.Nm ul +.Op Fl i +.Op Fl t Ar terminal +.Op Ar name Ar ... +.Sh DESCRIPTION +.Nm Ul +reads the named files (or standard input if none are given) +and translates occurrences of underscores to the sequence +which indicates underlining for the terminal in use, as specified +by the environment variable +.Ev TERM . +The file +.Pa /etc/termcap +is read to determine the appropriate sequences for underlining. +If the terminal is incapable of underlining, but is capable of +a standout mode then that is used instead. +If the terminal can overstrike, +or handles underlining automatically, +.Nm ul +degenerates to +.Xr cat 1 . +If the terminal cannot underline, underlining is ignored. +.Pp +The following options are available: +.Bl -tag -width Ds +.It Fl i +Underlining is indicated by a separate line containing appropriate +dashes `\-'; this is useful when you want to look at the underlining +which is present in an +.Xr nroff +output stream on a crt-terminal. +.It Fl t Ar terminal +Overrides the terminal type specified in the environment with +.Ar terminal . +.El +.Sh ENVIRONMENT +The following environment variable is used: +.Bl -tag -width TERM +.It Ev TERM +The +.Ev TERM +variable is used to relate a tty device +with its device capability description (see +.Xr termcap 5 ) . +.Ev TERM +is set at login time, either by the default terminal type +specified in +.Pa /etc/ttys +or as set during the login process by the user in their +.Pa login +file (see +.Xr setenv 1 ) . +.El +.Sh SEE ALSO +.Xr man 1 , +.Xr nroff 1 , +.Xr colcrt 1 +.Sh BUGS +.Xr Nroff +usually outputs a series of backspaces and underlines intermixed +with the text to indicate underlining. No attempt is made to optimize +the backward motion. +.Sh HISTORY +The +.Nm +command appeared in +.Bx 3.0 . diff --git a/text-utils/ul.c b/text-utils/ul.c new file mode 100644 index 000000000..75e6f95cb --- /dev/null +++ b/text-utils/ul.c @@ -0,0 +1,508 @@ +/* + * Copyright (c) 1980, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static char copyright[] = +"@(#) Copyright (c) 1980, 1993\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)ul.c 8.1 (Berkeley) 6/6/93"; +#endif /* not lint */ + +#include <stdio.h> + +#define IESC '\033' +#define SO '\016' +#define SI '\017' +#define HFWD '9' +#define HREV '8' +#define FREV '7' +#define MAXBUF 512 + +#define NORMAL 000 +#define ALTSET 001 /* Reverse */ +#define SUPERSC 002 /* Dim */ +#define SUBSC 004 /* Dim | Ul */ +#define UNDERL 010 /* Ul */ +#define BOLD 020 /* Bold */ + +int must_use_uc, must_overstrike; +char *CURS_UP, *CURS_RIGHT, *CURS_LEFT, + *ENTER_STANDOUT, *EXIT_STANDOUT, *ENTER_UNDERLINE, *EXIT_UNDERLINE, + *ENTER_DIM, *ENTER_BOLD, *ENTER_REVERSE, *UNDER_CHAR, *EXIT_ATTRIBUTES; + +struct CHAR { + char c_mode; + char c_char; +} ; + +struct CHAR obuf[MAXBUF]; +int col, maxcol; +int mode; +int halfpos; +int upln; +int iflag; + +int outchar(); +#define PRINT(s) if (s == NULL) /* void */; else tputs(s, 1, outchar) + +main(argc, argv) + int argc; + char **argv; +{ + extern int optind; + extern char *optarg; + int c; + char *termtype; + FILE *f; + char termcap[1024]; + char *getenv(), *strcpy(); + + termtype = getenv("TERM"); + if (termtype == NULL || (argv[0][0] == 'c' && !isatty(1))) + termtype = "lpr"; + while ((c=getopt(argc, argv, "it:T:")) != EOF) + switch(c) { + + case 't': + case 'T': /* for nroff compatibility */ + termtype = optarg; + break; + case 'i': + iflag = 1; + break; + + default: + fprintf(stderr, + "usage: %s [ -i ] [ -tTerm ] file...\n", + argv[0]); + exit(1); + } + + switch(tgetent(termcap, termtype)) { + + case 1: + break; + + default: + fprintf(stderr,"trouble reading termcap"); + /* fall through to ... */ + + case 0: + /* No such terminal type - assume dumb */ + (void)strcpy(termcap, "dumb:os:col#80:cr=^M:sf=^J:am:"); + break; + } + initcap(); + if ( (tgetflag("os") && ENTER_BOLD==NULL ) || + (tgetflag("ul") && ENTER_UNDERLINE==NULL && UNDER_CHAR==NULL)) + must_overstrike = 1; + initbuf(); + if (optind == argc) + filter(stdin); + else for (; optind<argc; optind++) { + f = fopen(argv[optind],"r"); + if (f == NULL) { + perror(argv[optind]); + exit(1); + } else + filter(f); + } + exit(0); +} + +filter(f) + FILE *f; +{ + register c; + + while ((c = getc(f)) != EOF) switch(c) { + + case '\b': + if (col > 0) + col--; + continue; + + case '\t': + col = (col+8) & ~07; + if (col > maxcol) + maxcol = col; + continue; + + case '\r': + col = 0; + continue; + + case SO: + mode |= ALTSET; + continue; + + case SI: + mode &= ~ALTSET; + continue; + + case IESC: + switch (c = getc(f)) { + + case HREV: + if (halfpos == 0) { + mode |= SUPERSC; + halfpos--; + } else if (halfpos > 0) { + mode &= ~SUBSC; + halfpos--; + } else { + halfpos = 0; + reverse(); + } + continue; + + case HFWD: + if (halfpos == 0) { + mode |= SUBSC; + halfpos++; + } else if (halfpos < 0) { + mode &= ~SUPERSC; + halfpos++; + } else { + halfpos = 0; + fwd(); + } + continue; + + case FREV: + reverse(); + continue; + + default: + fprintf(stderr, + "Unknown escape sequence in input: %o, %o\n", + IESC, c); + exit(1); + } + continue; + + case '_': + if (obuf[col].c_char) + obuf[col].c_mode |= UNDERL | mode; + else + obuf[col].c_char = '_'; + case ' ': + col++; + if (col > maxcol) + maxcol = col; + continue; + + case '\n': + flushln(); + continue; + + case '\f': + flushln(); + putchar('\f'); + continue; + + default: + if (c < ' ') /* non printing */ + continue; + if (obuf[col].c_char == '\0') { + obuf[col].c_char = c; + obuf[col].c_mode = mode; + } else if (obuf[col].c_char == '_') { + obuf[col].c_char = c; + obuf[col].c_mode |= UNDERL|mode; + } else if (obuf[col].c_char == c) + obuf[col].c_mode |= BOLD|mode; + else + obuf[col].c_mode = mode; + col++; + if (col > maxcol) + maxcol = col; + continue; + } + if (maxcol) + flushln(); +} + +flushln() +{ + register lastmode; + register i; + int hadmodes = 0; + + lastmode = NORMAL; + for (i=0; i<maxcol; i++) { + if (obuf[i].c_mode != lastmode) { + hadmodes++; + setmode(obuf[i].c_mode); + lastmode = obuf[i].c_mode; + } + if (obuf[i].c_char == '\0') { + if (upln) + PRINT(CURS_RIGHT); + else + outc(' '); + } else + outc(obuf[i].c_char); + } + if (lastmode != NORMAL) { + setmode(0); + } + if (must_overstrike && hadmodes) + overstrike(); + putchar('\n'); + if (iflag && hadmodes) + iattr(); + (void)fflush(stdout); + if (upln) + upln--; + initbuf(); +} + +/* + * For terminals that can overstrike, overstrike underlines and bolds. + * We don't do anything with halfline ups and downs, or Greek. + */ +overstrike() +{ + register int i; + char lbuf[256]; + register char *cp = lbuf; + int hadbold=0; + + /* Set up overstrike buffer */ + for (i=0; i<maxcol; i++) + switch (obuf[i].c_mode) { + case NORMAL: + default: + *cp++ = ' '; + break; + case UNDERL: + *cp++ = '_'; + break; + case BOLD: + *cp++ = obuf[i].c_char; + hadbold=1; + break; + } + putchar('\r'); + for (*cp=' '; *cp==' '; cp--) + *cp = 0; + for (cp=lbuf; *cp; cp++) + putchar(*cp); + if (hadbold) { + putchar('\r'); + for (cp=lbuf; *cp; cp++) + putchar(*cp=='_' ? ' ' : *cp); + putchar('\r'); + for (cp=lbuf; *cp; cp++) + putchar(*cp=='_' ? ' ' : *cp); + } +} + +iattr() +{ + register int i; + char lbuf[256]; + register char *cp = lbuf; + + for (i=0; i<maxcol; i++) + switch (obuf[i].c_mode) { + case NORMAL: *cp++ = ' '; break; + case ALTSET: *cp++ = 'g'; break; + case SUPERSC: *cp++ = '^'; break; + case SUBSC: *cp++ = 'v'; break; + case UNDERL: *cp++ = '_'; break; + case BOLD: *cp++ = '!'; break; + default: *cp++ = 'X'; break; + } + for (*cp=' '; *cp==' '; cp--) + *cp = 0; + for (cp=lbuf; *cp; cp++) + putchar(*cp); + putchar('\n'); +} + +initbuf() +{ + + bzero((char *)obuf, sizeof (obuf)); /* depends on NORMAL == 0 */ + col = 0; + maxcol = 0; + mode &= ALTSET; +} + +fwd() +{ + register oldcol, oldmax; + + oldcol = col; + oldmax = maxcol; + flushln(); + col = oldcol; + maxcol = oldmax; +} + +reverse() +{ + upln++; + fwd(); + PRINT(CURS_UP); + PRINT(CURS_UP); + upln++; +} + +initcap() +{ + static char tcapbuf[512]; + char *bp = tcapbuf; + char *getenv(), *tgetstr(); + + /* This nonsense attempts to work with both old and new termcap */ + CURS_UP = tgetstr("up", &bp); + CURS_RIGHT = tgetstr("ri", &bp); + if (CURS_RIGHT == NULL) + CURS_RIGHT = tgetstr("nd", &bp); + CURS_LEFT = tgetstr("le", &bp); + if (CURS_LEFT == NULL) + CURS_LEFT = tgetstr("bc", &bp); + if (CURS_LEFT == NULL && tgetflag("bs")) + CURS_LEFT = "\b"; + + ENTER_STANDOUT = tgetstr("so", &bp); + EXIT_STANDOUT = tgetstr("se", &bp); + ENTER_UNDERLINE = tgetstr("us", &bp); + EXIT_UNDERLINE = tgetstr("ue", &bp); + ENTER_DIM = tgetstr("mh", &bp); + ENTER_BOLD = tgetstr("md", &bp); + ENTER_REVERSE = tgetstr("mr", &bp); + EXIT_ATTRIBUTES = tgetstr("me", &bp); + + if (!ENTER_BOLD && ENTER_REVERSE) + ENTER_BOLD = ENTER_REVERSE; + if (!ENTER_BOLD && ENTER_STANDOUT) + ENTER_BOLD = ENTER_STANDOUT; + if (!ENTER_UNDERLINE && ENTER_STANDOUT) { + ENTER_UNDERLINE = ENTER_STANDOUT; + EXIT_UNDERLINE = EXIT_STANDOUT; + } + if (!ENTER_DIM && ENTER_STANDOUT) + ENTER_DIM = ENTER_STANDOUT; + if (!ENTER_REVERSE && ENTER_STANDOUT) + ENTER_REVERSE = ENTER_STANDOUT; + if (!EXIT_ATTRIBUTES && EXIT_STANDOUT) + EXIT_ATTRIBUTES = EXIT_STANDOUT; + + /* + * Note that we use REVERSE for the alternate character set, + * not the as/ae capabilities. This is because we are modelling + * the model 37 teletype (since that's what nroff outputs) and + * the typical as/ae is more of a graphics set, not the greek + * letters the 37 has. + */ + + UNDER_CHAR = tgetstr("uc", &bp); + must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE); +} + +outchar(c) + int c; +{ + putchar(c & 0177); +} + +static int curmode = 0; + +outc(c) + int c; +{ + putchar(c); + if (must_use_uc && (curmode&UNDERL)) { + PRINT(CURS_LEFT); + PRINT(UNDER_CHAR); + } +} + +setmode(newmode) + int newmode; +{ + if (!iflag) { + if (curmode != NORMAL && newmode != NORMAL) + setmode(NORMAL); + switch (newmode) { + case NORMAL: + switch(curmode) { + case NORMAL: + break; + case UNDERL: + PRINT(EXIT_UNDERLINE); + break; + default: + /* This includes standout */ + PRINT(EXIT_ATTRIBUTES); + break; + } + break; + case ALTSET: + PRINT(ENTER_REVERSE); + break; + case SUPERSC: + /* + * This only works on a few terminals. + * It should be fixed. + */ + PRINT(ENTER_UNDERLINE); + PRINT(ENTER_DIM); + break; + case SUBSC: + PRINT(ENTER_DIM); + break; + case UNDERL: + PRINT(ENTER_UNDERLINE); + break; + case BOLD: + PRINT(ENTER_BOLD); + break; + default: + /* + * We should have some provision here for multiple modes + * on at once. This will have to come later. + */ + PRINT(ENTER_STANDOUT); + break; + } + } + curmode = newmode; +} |