summaryrefslogtreecommitdiff
path: root/usr/src/cmd/ul
diff options
context:
space:
mode:
authorstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
committerstevel@tonic-gate <none@none>2005-06-14 00:00:00 -0700
commit7c478bd95313f5f23a4c958a745db2134aa03244 (patch)
treec871e58545497667cbb4b0a4f2daf204743e1fe7 /usr/src/cmd/ul
downloadillumos-joyent-7c478bd95313f5f23a4c958a745db2134aa03244.tar.gz
OpenSolaris Launch
Diffstat (limited to 'usr/src/cmd/ul')
-rw-r--r--usr/src/cmd/ul/Makefile44
-rw-r--r--usr/src/cmd/ul/ul.c635
2 files changed, 679 insertions, 0 deletions
diff --git a/usr/src/cmd/ul/Makefile b/usr/src/cmd/ul/Makefile
new file mode 100644
index 0000000000..dfc14b2124
--- /dev/null
+++ b/usr/src/cmd/ul/Makefile
@@ -0,0 +1,44 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+# Copyright (c) 1989 by Sun Microsystems, Inc.
+#
+
+PROG= ul
+
+include ../Makefile.cmd
+
+LDLIBS += -lcurses
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+install: all $(ROOTPROG)
+
+clean:
+
+lint: lint_PROG
+
+include ../Makefile.targ
diff --git a/usr/src/cmd/ul/ul.c b/usr/src/cmd/ul/ul.c
new file mode 100644
index 0000000000..39006c03c9
--- /dev/null
+++ b/usr/src/cmd/ul/ul.c
@@ -0,0 +1,635 @@
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+/*
+ * Copyright (c) 1983, 1984 1985, 1986, 1987, 1988, 2000 Sun Microsystems, Inc.
+ * All Rights Reserved.
+ */
+
+#ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+
+#include <stdio.h>
+#include <locale.h>
+#include <wctype.h>
+#include <widec.h>
+#include <euc.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define IESC L'\033'
+#define SO L'\016'
+#define SI L'\017'
+#define HFWD L'9'
+#define HREV L'8'
+#define FREV L'7'
+#define CDUMMY -1
+
+#define NORMAL 000
+#define ALTSET 001 /* Reverse */
+#define SUPERSC 002 /* Dim */
+#define SUBSC 004 /* Dim | Ul */
+#define UNDERL 010 /* Ul */
+#define BOLD 020 /* Bold */
+
+#define MEMFCT 16
+/*
+ * MEMFCT is a number that is likely to be large enough as a factor for
+ * allocating more memory and to be small enough so as not wasting memory
+ */
+
+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;
+ wchar_t c_char;
+};
+
+struct CHAR obuf[LINE_MAX];
+int col, maxcol;
+int mode;
+int halfpos;
+int upln;
+int iflag;
+
+eucwidth_t wp;
+int scrw[4];
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ char *cp, *termtype;
+ FILE *f;
+ char termcap[1024];
+ char *getenv();
+ extern int optind;
+ extern char *optarg;
+
+ (void) setlocale(LC_ALL, "");
+#if !defined(TEXT_DOMAIN)
+#define TEXT_DOMAIN "SYS_TEST"
+#endif
+ (void) textdomain(TEXT_DOMAIN);
+
+ getwidth(&wp);
+ scrw[0] = 1;
+ scrw[1] = wp._scrw1;
+ scrw[2] = wp._scrw2;
+ scrw[3] = wp._scrw3;
+
+ 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,
+ gettext("\
+Usage: %s [ -i ] [ -t terminal ] [ filename...]\n"),
+ argv[0]);
+ exit(1);
+ }
+
+ switch (tgetent(termcap, termtype)) {
+
+ case 1:
+ break;
+
+ default:
+ fprintf(stderr, gettext("trouble reading termcap"));
+ /* fall through to ... */
+
+ case 0:
+ /* No such terminal type - assume dumb */
+ 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 wchar_t c;
+ register i;
+
+ while ((c = getwc(f)) != EOF) {
+ if (maxcol >= LINE_MAX)
+ {
+ fprintf(stderr,
+ gettext("Input line longer than %d characters\n"), LINE_MAX);
+ exit(1);
+ }
+ switch (c) {
+
+ case L'\b':
+ if (col > 0)
+ col--;
+ continue;
+
+ case L'\t':
+ col = (col+8) & ~07;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+
+ case L'\r':
+ col = 0;
+ continue;
+
+ case SO:
+ mode |= ALTSET;
+ continue;
+
+ case SI:
+ mode &= ~ALTSET;
+ continue;
+
+ case IESC:
+ switch (c = getwc(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,
+ gettext("Unknown escape sequence in input: %o, %o\n"),
+ IESC, c);
+ exit(1);
+ }
+ continue;
+
+ case L'_':
+ if (obuf[col].c_char)
+ obuf[col].c_mode |= UNDERL | mode;
+ else
+ obuf[col].c_char = '_';
+ case L' ':
+ col++;
+ if (col > maxcol)
+ maxcol = col;
+ continue;
+
+ case L'\n':
+ flushln();
+ continue;
+
+ default:
+ if (c < L' ') /* non printing */
+ continue;
+ if (obuf[col].c_char == L'\0') {
+ obuf[col].c_char = c;
+ obuf[col].c_mode = mode;
+ i = scrw[wcsetno(c)];
+ while (--i > 0)
+ obuf[++col].c_char = CDUMMY;
+ } else if (obuf[col].c_char == L'_') {
+ obuf[col].c_char = c;
+ obuf[col].c_mode |= UNDERL|mode;
+ i = scrw[wcsetno(c)];
+ while (--i > 0)
+ obuf[++col].c_char = CDUMMY;
+ } else if (obuf[col].c_char == c)
+ obuf[col].c_mode |= BOLD|mode;
+ else {
+ obuf[col].c_char = c;
+ 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 == L'\0') {
+ if (upln) {
+ puts(CURS_RIGHT);
+ } else
+ outc(L' ');
+ } else
+ outc(obuf[i].c_char);
+ }
+ if (lastmode != NORMAL) {
+ setmode(0);
+ }
+ if (must_overstrike && hadmodes)
+ overstrike();
+ putwchar(L'\n');
+ if (iflag && hadmodes)
+ iattr();
+ 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, n;
+ wchar_t *cp, *scp;
+ size_t szbf = 256, tszbf;
+ int hadbold=0;
+
+ scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf);
+ if (!scp) {
+ /* this kind of message need not to be gettext'ed */
+ (void) fprintf(stderr, "malloc failed\n");
+ exit(1);
+ }
+ cp = scp;
+ tszbf = szbf;
+#ifdef DEBUG
+ /*
+ * to allocate a memory after the chunk of the current scp
+ * and to make sure the following realloc() allocates
+ * memory from different chunks.
+ */
+ (void) malloc(1024 * 1024);
+#endif
+
+ /* Set up overstrike buffer */
+ for (i=0; i<maxcol; i++) {
+ n = scrw[wcsetno(obuf[i].c_char)];
+ if (tszbf <= n) {
+ /* may not enough buffer for this char */
+ size_t pos;
+
+ /* obtain the offset of cp */
+ pos = cp - scp;
+ /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
+ scp = (wchar_t *)realloc(scp,
+ sizeof (wchar_t) * (szbf + (n * MEMFCT)));
+ if (!scp) {
+ (void) fprintf(stderr, "malloc failed\n");
+ exit(1);
+ }
+ /* get the new address of cp */
+ cp = scp + pos;
+ szbf += n * MEMFCT;
+ tszbf += n * MEMFCT;
+ }
+ switch (obuf[i].c_mode) {
+ case NORMAL:
+ default:
+ tszbf -= n;
+ *cp++ = L' ';
+ while (--n > 0) {
+ *cp++ = L' ';
+ i++;
+ }
+ break;
+ case UNDERL:
+ tszbf -= n;
+ *cp++ = L'_';
+ while (--n > 0) {
+ *cp++ = L'_';
+ i++;
+ }
+ break;
+ case BOLD:
+ tszbf--;
+ *cp++ = obuf[i].c_char;
+ hadbold=1;
+ break;
+ }
+ }
+ putwchar(L'\r');
+ for (*cp=L' '; *cp==L' '; cp--)
+ *cp = L'\0';
+ for (cp=scp; *cp; cp++)
+ putwchar(*cp);
+ if (hadbold) {
+ putwchar(L'\r');
+ for (cp=scp; *cp; cp++)
+ putwchar(*cp==L'_' ? L' ' : *cp);
+ putwchar(L'\r');
+ for (cp=scp; *cp; cp++)
+ putwchar(*cp==L'_' ? L' ' : *cp);
+ }
+ free(scp);
+}
+
+iattr()
+{
+ register int i, n;
+ wchar_t *cp, *scp;
+ register wchar_t cx;
+ size_t szbf = 256, tszbf;
+
+ scp = (wchar_t *)malloc(sizeof (wchar_t) * szbf);
+ if (!scp) {
+ /* this kind of message need not to be gettext'ed */
+ (void) fprintf(stderr, "malloc failed\n");
+ exit(1);
+ }
+ cp = scp;
+ tszbf = szbf;
+#ifdef DEBUG
+ /*
+ * to allocate a memory after the chunk of the current scp
+ * and to make sure the following realloc() allocates
+ * memory from different chunks.
+ */
+ (void) malloc(1024 * 1024);
+#endif
+ for (i=0; i<maxcol; i++) {
+ switch (obuf[i].c_mode) {
+ case NORMAL: cx = ' '; break;
+ case ALTSET: cx = 'g'; break;
+ case SUPERSC: cx = '^'; break;
+ case SUBSC: cx = 'v'; break;
+ case UNDERL: cx = '_'; break;
+ case BOLD: cx = '!'; break;
+ default: cx = 'X'; break;
+ }
+ n = scrw[wcsetno(obuf[i].c_char)];
+ if (tszbf <= n) {
+ /* may not enough buffer for this char */
+ size_t pos;
+
+ /* obtain the offset of cp */
+ pos = cp - scp;
+ /* reallocate another (n * MEMFCT) * sizeof (wchar_t) */
+ scp = (wchar_t *)realloc(scp,
+ sizeof (wchar_t) * (szbf + (n * MEMFCT)));
+ if (!scp) {
+ (void) fprintf(stderr, "malloc failed\n");
+ exit(1);
+ }
+ /* get the new address of cp */
+ cp = scp + pos;
+ szbf += n * MEMFCT;
+ tszbf += n * MEMFCT;
+ }
+ tszbf -= n;
+ *cp++ = cx;
+ while (--n > 0) {
+ *cp++ = cx;
+ i++;
+ }
+ }
+ for (*cp=L' '; *cp==L' '; cp--)
+ *cp = L'\0';
+ for (cp=scp; *cp; cp++)
+ putwchar(*cp);
+ putwchar(L'\n');
+ free(scp);
+}
+
+initbuf()
+{
+ register i;
+
+ /* following depends on NORMAL == 000 */
+ for (i = 0; i < LINE_MAX; i++)
+ obuf[i].c_char = obuf[i].c_mode = 0;
+
+ col = 0;
+ maxcol = 0;
+ mode &= ALTSET;
+}
+
+fwd()
+{
+ register oldcol, oldmax;
+
+ oldcol = col;
+ oldmax = maxcol;
+ flushln();
+ col = oldcol;
+ maxcol = oldmax;
+}
+
+reverse()
+{
+ upln++;
+ fwd();
+ puts(CURS_UP);
+ puts(CURS_UP);
+ upln++;
+}
+
+initcap()
+{
+ static char tcapbuf[512];
+ char *termtype;
+ 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.
+ */
+
+#ifdef notdef
+printf("so %s se %s us %s ue %s me %s\n",
+ ENTER_STANDOUT, EXIT_STANDOUT, ENTER_UNDERLINE,
+ EXIT_UNDERLINE, EXIT_ATTRIBUTES);
+#endif
+ UNDER_CHAR = tgetstr("uc", &bp);
+ must_use_uc = (UNDER_CHAR && !ENTER_UNDERLINE);
+}
+
+outchar(c)
+char c;
+{
+ putchar(c&0177);
+}
+
+puts(str)
+const char *str;
+{
+ if (str)
+ tputs(str, 1, outchar);
+}
+
+static curmode = 0;
+outc(c)
+wchar_t c;
+{
+ register int m, n;
+
+ if (c == CDUMMY)
+ return;
+ putwchar(c);
+ if (must_use_uc && (curmode & UNDERL)) {
+ m = n = scrw[wcsetno(c)];
+ puts(CURS_LEFT);
+ while (--m > 0)
+ puts(CURS_LEFT);
+ puts(UNDER_CHAR);
+ while (--n > 0)
+ puts(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:
+ puts(EXIT_UNDERLINE);
+ break;
+ default:
+ /* This includes standout */
+ puts(EXIT_ATTRIBUTES);
+ break;
+ }
+ break;
+ case ALTSET:
+ puts(ENTER_REVERSE);
+ break;
+ case SUPERSC:
+ /*
+ * This only works on a few terminals.
+ * It should be fixed.
+ */
+ puts(ENTER_UNDERLINE);
+ puts(ENTER_DIM);
+ break;
+ case SUBSC:
+ puts(ENTER_DIM);
+ break;
+ case UNDERL:
+ puts(ENTER_UNDERLINE);
+ break;
+ case BOLD:
+ puts(ENTER_BOLD);
+ break;
+ default:
+ /*
+ * We should have some provision here for multiple modes
+ * on at once. This will have to come later.
+ */
+ puts(ENTER_STANDOUT);
+ break;
+ }
+ }
+ curmode = newmode;
+}