# To unbundle, sh this file echo LICENSE 1>&2 sed 's/.//' >LICENSE <<'//GO.SYSIN DD LICENSE' -This software is provided `as-is,' without any express or implied -warranty. In no event will the author be held liable for any damages -arising from the use of this software. - -Permission is granted to anyone to use this software for any purpose, -including commercial applications, and to alter it and redistribute it -freely, subject to the following restrictions: - -1. The origin of this software must not be misrepresented; you must -not claim that you wrote the original software. If you use this -software in a product, an acknowledgment in the product documentation -would be appreciated but is not required. - -2. Altered source versions must be plainly marked as such, and must -not be misrepresented as being the original software. - -3. This notice may not be removed or altered from any source -distribution. //GO.SYSIN DD LICENSE echo Makefile 1>&2 sed 's/.//' >Makefile <<'//GO.SYSIN DD Makefile' -PFILES=p.o pad.o -CFLAGS=-O - -ALL=p mc seq vis -all: $(ALL) - -p: $(PFILES) - $(CC) -o p $(PFILES) - -p.o pad.o: pad.h - -clean: - rm -f $(ALL) $(PFILES) //GO.SYSIN DD Makefile echo README 1>&2 sed 's/.//' >README <<'//GO.SYSIN DD README' -Pure reimplementations of p mc seq vis; untainted by -Research UNIX licenses; meant for use on other systems. -In fact mc in its present state won't compile on Research -UNIX because has been abolished. - -Some day these should probably replace the official Research -versions after various compatibility checks and fixes. - -ANSI C is required (, prototypes). //GO.SYSIN DD README echo mc.c 1>&2 sed 's/.//' >mc.c <<'//GO.SYSIN DD mc.c' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -#include -#include -#include -#include /* for open */ - -static int linesize; -static int bflag; -static int tflag; -static int iflag; - -#define TABSTOP 8 - -static void docol(int); -static void getwords(int, char **, char **); -static int countwords(char *, char *, int *); -static void prwords(char *, char *, int, int, int); -static int deflinesize(void); - -int -main(argc, argv) -int argc; -char **argv; -{ - int fd; - int sts; - - while (argc > 1 && argv[1][0] == '-') { - argc--; - argv++; - switch (argv[0][1]) { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - linesize = atoi(&argv[0][1]); - continue; - - case 0: /* - */ - case 'b': - bflag = 1; - continue; - - case 'i': - iflag = 1; - continue; - - case 't': - tflag = 1; - continue; - - default: - fprintf(stderr, "usage: mc [-linesize] [-b] [files]\n"); - return (1); - } - } - if (linesize == 0) - linesize = deflinesize(); - sts = 0; - if (argc <= 1) - docol(0); - else - while (--argc > 0) { - if ((fd = open(*++argv, 0)) < 0) { - fprintf(stderr, "mc: %s: cannot open\n", *argv); - sts = 1; - } else { - docol(fd); - close(fd); - } - } - return (sts); -} - -/* - * the general idea: - * 1. read all the words to be printed into buf, - * separated by newlines - * 2. count the words, remember the longest - * 3. print - */ - -#define EDGE 1 /* some CRTs scroll if last character is used */ -#define GUTTER 2 /* min distance between words */ - -static void -docol(fd) -int fd; -{ - char *buf; - char *ebuf; - int nwords, maxlen; - int ncol, nrow; - - getwords(fd, &buf, &ebuf); - nwords = countwords(buf, ebuf, &maxlen); - ncol = (linesize - EDGE) / (maxlen + GUTTER); - if (ncol <= 0) - ncol = 1; - nrow = (nwords + ncol - 1) / ncol; - prwords(buf, ebuf, nrow, ncol, maxlen + GUTTER); - free(buf); -} - -#define INITBUF 4096 -#define ADDBUF 4096 - -static void -getwords(fd, bufp, ebufp) -int fd; -char **bufp; -char **ebufp; -{ - int n, rlen; - char *p; - - if ((*bufp = malloc(INITBUF + 1)) == NULL) { - fprintf(stderr, "mc: out of memory\n"); - exit(1); - } - p = *bufp; - rlen = INITBUF; - while ((n = read(fd, p, rlen)) > 0) { - p += n; - if ((rlen -= n) <= 0) { /* need more buffer */ - n = *bufp - p; - if ((*bufp = realloc(*bufp, n + ADDBUF + 1)) == NULL) { - fprintf(stderr, "mc: out of memory\n"); - exit(1); - } - rlen = ADDBUF; - p = *bufp + n; - } - } - *ebufp = p; - *p = '\n'; /* sentinel */ -} - -static int -countwords(buf, ebuf, maxp) -char *buf, *ebuf; -int *maxp; -{ - char *p; - int n, max, nwords; - - nwords = max = n = 0; - for (p = buf; p < ebuf; p++) { - if (*p == '\t' && iflag == 0) { - n += TABSTOP; - n /= TABSTOP; - n *= TABSTOP; - } else if (*p != '\n') - n++; - else { - nwords++; - if (n > max) - max = n; - n = 0; - } - } - *maxp = max; - return (nwords); -} - -/* - * print newline-separated words from buf to ebuf, - * in nrow rows of ncol columns, - * each column wordspace wide - * the hard part is tabs, - * especially if there are tabs inside the data - */ - -static void -prwords(buf, ebuf, nrow, ncol, wordspace) -char *buf, *ebuf; -int nrow, ncol, wordspace; -{ - char **colp; - int i, j; - char *p; - int outpos, wantpos, ioutpos; - - if ((colp = malloc(ncol * sizeof(char *))) == NULL) { - fprintf(stderr, "mc: out of memory\n"); - exit(1); - } - for (p = buf, i = 0; i < ncol; i++) { - colp[i] = p; - for (j = 0; j < nrow && p < ebuf; j++) - while (*p++ != '\n') - ; - } - for (i = 0; i < nrow; i++) { - outpos = wantpos = 0; - for (j = 0; j < ncol && (p = colp[j]) < ebuf; j++) { - while (outpos < wantpos) { - if (tflag == 0 - && outpos < (wantpos/TABSTOP)*TABSTOP) { - putchar('\t'); - outpos += TABSTOP; - outpos /= TABSTOP; - outpos *= TABSTOP; - } else { - putchar(' '); - outpos++; - } - } - ioutpos = outpos; - while (*p != '\n') { - if (iflag == 0 && *p == '\t') { - p++; - while ((outpos-ioutpos)%TABSTOP) { - putchar(' '); - outpos++; - } - } else { - putchar(*p++); - outpos++; - } - } - p++; /* past newline */ - colp[j] = p; - wantpos += wordspace; - } - putchar('\n'); - } - free(colp); -} - -#if NOTDEF -#include -#endif - -static int -deflinesize() -{ -#ifdef TIOCGWINSZ - { - struct winsize ws; - - if (ioctl(1, TIOCGWINSZ, &ws) >= 0 - && ws.ws_col > 0) - return (ws.ws_col); - if (ioctl(2, TIOCGWINSZ, &ws) >= 0 /* in case stdout is a pipe */ - && ws.ws_col > 0) - return (ws.ws_col); - } -#endif - return (80); -} //GO.SYSIN DD mc.c echo p.c 1>&2 sed 's/.//' >p.c <<'//GO.SYSIN DD p.c' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "pad.h" - -static int pagelen = 22; /* 22 evenly divides 66 */ -static int curpos = 0; -static FILE *tty; - -static void pag(FILE *); -static void docomm(FILE *, PFILE *); -static void psystem(char *); -static void backup(PFILE *, int); - -int -main(argc, argv) -int argc; -char **argv; -{ - FILE *fp; - int sts; - char buf[BUFSIZ]; - - if (argc > 1 && argv[1][0] == '-' && isdigit(argv[1][1])) { - pagelen = atoi(&argv[1][1]); - argc--; - argv++; - } - if ((tty = fopen("/dev/tty", "r")) == NULL) { - if (argc <= 1) { /* if we need stdin */ - fprintf(stderr, "p: cannot open /dev/tty: %s\n", strerror(errno)); - return (1); - } - tty = stdin; - } - setbuf(stdout, buf); - sts = 0; - if (argc <= 1) - pag(stdin); - else { - while (--argc > 0) { - if ((fp = fopen(*++argv, "r")) == NULL) { - fprintf(stderr, "p: %s: %s\n", *argv, strerror(errno)); - sts = 1; - } - else { - pag(fp); - fclose(fp); - } - } - } - return (sts); -} - -static void -pag(fp) -FILE *fp; -{ - PFILE *pp; - int c; - - if ((pp = Pfopen(fp, 0)) == NULL) { - fprintf(stderr, "p: no mem for buffers\n"); - return; - } - while ((c = Pgetc(pp)) != EOF) { - if (c != '\n' || ++curpos < pagelen) { - putchar(c); - continue; - } - curpos = 0; - fflush(stdout); - docomm(tty, pp); - } -} - -static void -docomm(tfp, pp) -FILE *tfp; -PFILE *pp; -{ - char comm[200]; - int i; - int c; - - while ((c = getc(tfp)) != '\n') { - switch (c) { - default: - continue; - - case EOF: - case 'q': - exit(0); - - case '-': - backup(pp, pagelen); - continue; - - case '!': - for (i = 0; (c = getc(tfp)) != '\n' && c != EOF; i++) - if (i < sizeof(comm)-1) - comm[i] = c; - comm[i] = 0; - psystem(comm); - printf("!\n"); - fflush(stdout); - continue; - } - } -} - -/* - * special form of system: - * force tty into stdin - * in case stdin is the data we are p-ing - */ - -static void -psystem(comm) -char *comm; -{ - char *sh; - int pid; - void (*isig)(), (*qsig)(); - - if ((pid = fork()) < 0) { - fprintf(stderr, "p: fork: %s\n", strerror(errno)); - return; - } - if (pid == 0) { /* child */ - if (fileno(tty) != 0) - dup2(fileno(tty), 0); - if ((sh = getenv("SHELL")) == NULL) - sh = "/bin/sh"; - execl(sh, sh, "-c", comm, (char *)NULL); - fprintf(stderr, "p: exec %s: %s\n", sh, strerror(errno)); - _exit(1); - } - isig = signal(SIGINT, SIG_IGN); - qsig = signal(SIGQUIT, SIG_IGN); - while (wait(NULL) != pid) - ; - signal(SIGINT, isig); - signal(SIGQUIT, qsig); -} - -/* - * skip backward nlines lines - * -- == back nlines+1 newlines, then forward one to beginning of line - */ -static void -backup(pp, nlines) -PFILE *pp; -int nlines; -{ - int c; - - nlines++; - while (--nlines >= 0) { - while ((c = Pbackc(pp)) != '\n' && c != EOF) - ; - if (c == EOF) - break; - } - if (c == '\n') - (void)Pgetc(pp); /* skip to beginning of line */ -} //GO.SYSIN DD p.c echo pad.c 1>&2 sed 's/.//' >pad.c <<'//GO.SYSIN DD pad.c' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -/* - * front-end to stdio - * to stick a circular buffer - * in front of read side, - * and allow backup - * - * pp->base points to the buffer; - * pp->lim points past its end. - * pp->first is the first (oldest) character; - * pp->last points past the last (youngest). - * pp->cur is the current character. - */ - -#include -#include -#include "pad.h" - -#define CMASK 0xff - -/* - * make a PFILE to go with a stdio FILE - * fp must already be open for reading - */ -PFILE * -Pfopen(fp, buflen) -FILE *fp; -int buflen; -{ - PFILE *pp; - - if (buflen == 0) - buflen = PADBSIZE; - if ((pp = malloc(sizeof(PFILE))) == NULL) - return (NULL); - if ((pp->base = malloc(buflen)) == NULL) { - free(pp); - return (NULL); - } - pp->lim = pp->base + buflen; - pp->first = pp->last = pp->cur = pp->base; - pp->fp = fp; - return (pp); -} - -void -Pfclose(pp) -PFILE *pp; -{ - FILE *fp; - - fp = pp->fp; - free(pp->base); - free(pp); -} - -/* - * read a character from the file, - * advancing the circular buffer - */ -int -Pgetc(pp) -PFILE *pp; -{ - int c; - - if (pp->cur != pp->last) { /* read from buffer */ - c = *pp->cur++ & CMASK; - if (pp->cur >= pp->lim) - pp->cur = pp->base; - return (c); - } - if ((c = getc(pp->fp)) == EOF) - return (c); - *pp->last++ = c; - if (pp->last >= pp->lim) - pp->last = pp->base; - pp->cur = pp->last; - if (pp->last == pp->first) { /* overflow, advance first */ - pp->first++; - if (pp->first >= pp->lim) - pp->first = pp->base; - } - return (c); -} - -/* - * back up one character; - * return the character backed over - * (that to be returned if Pgetc is called next), - * EOF if at beginning of buffer - */ -int -Pbackc(pp) -PFILE *pp; -{ - if (pp->cur == pp->first) - return (EOF); - if (pp->cur <= pp->base) - pp->cur = pp->lim; - return (*--pp->cur & CMASK); -} //GO.SYSIN DD pad.c echo pad.h 1>&2 sed 's/.//' >pad.h <<'//GO.SYSIN DD pad.h' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -/* - * assumed included - */ -typedef struct { - FILE *fp; - char *base; - char *lim; - char *first; - char *last; - char *cur; -} PFILE; - -#define PADBSIZE (8*BUFSIZ) - -PFILE *Pfopen(FILE *, int); -void Pfclose(PFILE *); -int Pgetc(PFILE *); -int Pbackc(PFILE *); //GO.SYSIN DD pad.h echo seq.c 1>&2 sed 's/.//' >seq.c <<'//GO.SYSIN DD seq.c' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -/* - * print a sequence of numbers - * from description of V10 seq(1) - * seq [ -w ] [ -ffmt ] [ first [ incr ] ] last - */ - -#include -#include -#include - -static double first = 1; -static double incr = 1; -static double last = 0; - -static int eqwid = 0; -static char *fmt = "%g"; -static int newfmt = 0; - -static void usage(void); -static void compwid(void); - -int -main(argc, argv) -int argc; -char **argv; -{ - double f; - - while (--argc > 0) { - if (**++argv != '-') - break; - if (argv[0][1] == 'w') - eqwid++; - else if (argv[0][1] == 'f' && argv[0][2] == '%') { - fmt = &argv[0][2]; - newfmt = 1; - } else - usage(); - } - if (newfmt) - eqwid = 0; - switch (argc) { /* n.b. argc already decr, argv incr */ - case 1: - last = atof(argv[0]); - break; - - case 2: - first = atof(argv[0]); - last = atof(argv[1]); - break; - - case 3: - first = atof(argv[0]); - incr = atof(argv[1]); - last = atof(argv[2]); - break; - - default: - usage(); - } - last += incr / 2; /* fuzz for imprecise floating point */ - if (eqwid) - compwid(); - for (f = first; f < last; f += incr) { - printf(fmt, f); - putchar('\n'); - } - return (0); -} - -static void -usage() -{ - fprintf(stderr, "usage: seq [-w] [-ffmt] [first [incr]] last\n"); - exit(1); -} - -/* - * there is probably a cleaner way to do this - */ - -static void -compwid() -{ - char buf[200]; /* arbitrarily large */ - static char fmtbuf[20]; - int maxlen; - int len; - double f; - - maxlen = 0; - for (f = first; f < last; f += incr) { - sprintf(buf, fmt, f); - len = strlen(buf); - if (maxlen < len) - maxlen = len; - } - sprintf(fmtbuf, "%%0%dg", maxlen); - fmt = fmtbuf; -} //GO.SYSIN DD seq.c echo vis.c 1>&2 sed 's/.//' >vis.c <<'//GO.SYSIN DD vis.c' -/* - * Copyright 2004 Norman Wilson - * See accompanying file LICENSE for conditions - */ - -/* - * simple filter for invisible characters - */ - -#include -#include -#include -#include -#include - -static int tabsok, strip; -static int bsdisp; - -static void usage(void); -static void vis(FILE *); - -int -main(argc, argv) -int argc; -char **argv; -{ - FILE *fp; - - for (; argc > 1 && argv[1][0] == '-'; --argc, ++argv) { - if (strcmp(argv[1], "-t") == 0) - tabsok++; - else if (strcmp(argv[1], "-s") == 0) - strip++; - else if (strcmp(argv[1], "-b") == 0) - bsdisp++; - else - usage(); - } - if (argc <= 1) - vis(stdin); - else { - for (; argc > 1; --argc, ++argv) { - if ((fp = fopen(argv[1], "r")) == NULL) - fprintf(stderr, "vis: %s: %s\n", argv[1], strerror(errno)); - else { - vis(fp); - fclose(fp); - } - } - } - return (0); -} - -static void -usage() -{ - fprintf(stderr, "usage: vis [-s] [-t] file ...\n"); - exit(1); -} - -static void -vis(fp) -FILE *fp; -{ - int c; - - while ((c = getc(fp)) != EOF) { - if (isprint(c) || c == '\n') { - putchar(c); - continue; - } - if (tabsok && c == '\t') { - putchar(c); - continue; - } - if (bsdisp && c == '\b') { - printf("\\b"); - continue; - } - if (strip) - continue; - switch (c) { - case '\t': - printf("\\t"); - continue; - - case '\b': - printf("\\b"); - continue; - } - /* default: */ - printf("\\%03o", c&0377); - } -} //GO.SYSIN DD vis.c