vmh.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,519 行 · 第 1/2 页
C
1,519 行
/* vmh.c - visual front-end to mh */#ifndef lintstatic char ident[] = "@(#)$Id: vmh.c,v 1.2 90/11/25 19:06:10 sharpe Exp $";#endif lint#ifdef SYS5/* * Define TERMINFO if you have it. * You get it automatically if you're running SYS5, and you don't get * it if you're not. (If you're not SYS5, you probably have termcap.) * We distinguish TERMINFO from SYS5 because in this file SYS5 really * means "AT&T line discipline" (termio, not sgttyb), whereas terminfo * is quite a separate issue. */#define TERMINFO 1#endif SYS5/* TODO: Pass signals to client during execution Figure out a way for the user to say how big the Scan/Display windows should be. If curses ever gets fixed, then XYZ code can be removed */#include <curses.h>#undef OK /* tricky */#ifdef TERMINFO#include <term.h> /* variables describing terminal capabilities */#endif TERMINFO#include "../h/mh.h"#include "../h/vmhsbr.h"#include <ctype.h>#include <errno.h>#include <setjmp.h>#include <signal.h>#ifndef sigmask#define sigmask(s) (1 << ((s) - 1))#endif not sigmask#ifdef ridge#undef SIGTSTP#endif ridge#ifndef BSD42struct iovec { char *iov_base; int iov_len;};#else BSD42#include <sys/types.h>#include <sys/uio.h>#endif BSD42#define ALARM ((unsigned int) 10)#define PAUSE ((unsigned int) 2)#define abs(a) ((a) > 0 ? (a) : -(a))#define SMALLMOVE 1#define LARGEMOVE 10#define XYZ /* XXX *//* */static struct swit switches[] = {#define PRMPTSW 0 "prompt string", 6,#define PROGSW 1 "vmhproc program", 7,#define NPROGSW 2 "novmhproc", 9,#define HELPSW 3 "help", 4, NULL, NULL};/* */ /* PEERS */static int PEERpid = NOTOK;static jmp_buf PEERctx; /* WINDOWS */static char *myprompt = "(%s) ";static WINDOW *Scan;static WINDOW *Status;static WINDOW *Display;static WINDOW *Command;#define NWIN 3static int numwins;WINDOW *windows[NWIN + 1]; /* LINES */struct line { int l_no; char *l_buf; struct line *l_prev; struct line *l_next;};static struct line *lhead = NULL;static struct line *ltop = NULL;static struct line *ltail = NULL;static int did_less = 0;static int smallmove = SMALLMOVE;static int largemove = LARGEMOVE; /* TTYS */static int tty_ready = NOTOK;static int intrc;#ifndef SYS5#define ERASE sg.sg_erase#define KILL sg.sg_killstatic struct sgttyb sg;#define EOFC tc.t_eofc#define INTR tc.t_intrcstatic struct tchars tc;#else SYS5#define ERASE sg.c_cc[VERASE]#define KILL sg.c_cc[VKILL]#define EOFC sg.c_cc[VEOF]#define INTR sg.c_cc[VINTR]static struct termio sg;#endif SYS5#ifndef TIOCGLTC#define WERASC ('W' & 037)#else TIOCGLTC#define WERASC ltc.t_werascstatic struct ltchars ltc;#endif TIOCGLTC#ifndef SYS5int _putchar ();#endif not SYS5#ifdef SIGTSTPchar *tgoto ();#endif SIGTSTP /* SIGNALS */static int ALRMser (), PIPEser (), SIGser ();#ifdef SIGTSTPstatic int TSTPser ();#endif SIGTSTP /* MISCELLANY */extern int errno;extern int sys_nerr;extern char *sys_errlist[];static void adorn ();static vmh(), lreset(), linsert(), ladvance(), lretreat(), lgo();static TTYon(), TTYoff(), foreground();static int PEERinit(), pINI(), pLOOP(), pTTY(), pWIN(), WINinit();static int WINgetstr(), WINless(), WINputc(), TTYinit(), pWINaux();/* *//* ARGSUSED */main (argc, argv)int argc;char *argv[];{ int vecp = 1, nprog = 0; char *cp, buffer[BUFSIZ], **ap, **argp, *arguments[MAXARGS], *vec[MAXARGS]; invo_name = r1bindex (argv[0], '/'); if ((cp = m_find (invo_name)) != NULL) { ap = brkstring (cp = getcpy (cp), " ", "\n"); ap = copyip (ap, arguments); } else ap = arguments; (void) copyip (argv + 1, ap); argp = arguments;/* */ while (cp = *argp++) if (*cp == '-') switch (smatch (++cp, switches)) { case AMBIGSW: ambigsw (cp, switches); done (1); case UNKWNSW: vec[vecp++] = --cp; continue; case HELPSW: (void) sprintf (buffer, "%s [switches for vmhproc]", invo_name); help (buffer, switches); done (1); case PRMPTSW: if (!(myprompt = *argp++) || *myprompt == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case PROGSW: if (!(vmhproc = *argp++) || *vmhproc == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case NPROGSW: nprog++; continue; } else vec[vecp++] = cp;/* */ if (TTYinit (nprog) == NOTOK || WINinit (nprog) == NOTOK) { vec[vecp] = NULL; vec[0] = r1bindex (vmhproc, '/'); execvp (vmhproc, vec); adios (vmhproc, "unable to exec"); } TTYoff (); (void) PEERinit (vecp, vec); TTYon (); vmh (); done (0);}/* */static vmh () { char buffer[BUFSIZ]; for (;;) { (void) pLOOP (RC_QRY, NULLCP); wmove (Command, 0, 0); wprintw (Command, myprompt, invo_name); wclrtoeol (Command); wrefresh (Command); switch (WINgetstr (Command, buffer)) { case NOTOK: break; case OK: done (0); /* NOTREACHED */ default: if (*buffer) (void) pLOOP (RC_CMD, buffer); break; } }}/* PEERS */static int PEERinit (vecp, vec)int vecp;char *vec[];{ int pfd0[2], pfd1[2]; char buf1[BUFSIZ], buf2[BUFSIZ]; if (pipe (pfd0) == NOTOK || pipe (pfd1) == NOTOK) adios ("pipe", "unable to");#ifdef hpux switch (PEERpid = fork ()) { /* * Calling vfork() and then another routine [like close()] before * an exec() messes up the stack frame, causing crib death. * Use fork() instead. */#else not hpux switch (PEERpid = vfork ()) {#endif not hpux case NOTOK: adios ("vfork", "unable to");/* NOTREACHED */ case OK: (void) close (pfd0[0]); (void) close (pfd1[1]); vec[vecp++] = "-vmhread"; (void) sprintf (buf1, "%d", pfd1[0]); vec[vecp++] = buf1; vec[vecp++] = "-vmhwrite"; (void) sprintf (buf2, "%d", pfd0[1]); vec[vecp++] = buf2; vec[vecp] = NULL; (void) signal (SIGINT, SIG_DFL); (void) signal (SIGQUIT, SIG_DFL); vec[0] = r1bindex (vmhproc, '/'); execvp (vmhproc, vec); perror (vmhproc); _exit (-1); /* NOTREACHED */ default: (void) close (pfd0[1]); (void) close (pfd1[0]); (void) rcinit (pfd0[0], pfd1[1]); return pINI (); }}/* */static int pINI () { register char *bp; char buffer[BUFSIZ]; struct record rcs; register struct record *rc = &rcs; register WINDOW **w; initrc (rc); bp = buffer; (void) sprintf (bp, "%d %d", RC_VRSN, numwins); bp += strlen (bp); for (w = windows; *w; w++) { (void) sprintf (bp, " %d", (*w) -> _maxy); bp += strlen (bp); } switch (str2rc (RC_INI, buffer, rc)) { case RC_ACK: return OK; case RC_ERR: if (rc -> rc_len) adios (NULLCP, "%s", rc -> rc_data); else adios (NULLCP, "pINI peer error"); case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pINI protocol screw-up"); }/* NOTREACHED */}/* */static int pLOOP (code, str)char code, *str;{ int i; struct record rcs; register struct record *rc = &rcs; initrc (rc); (void) str2peer (code, str); for (;;) switch (peer2rc (rc)) { case RC_TTY: if (pTTY (rc) == NOTOK) return NOTOK; break; case RC_WIN: if (sscanf (rc -> rc_data, "%d", &i) != 1 || i <= 0 || i > numwins) { (void) fmt2peer (RC_ERR, "no such window \"%s\"", rc -> rc_data); return NOTOK; } if (pWIN (windows[i - 1]) == NOTOK) return NOTOK; break; case RC_EOF: return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pLOOP(%s) peer error", code == RC_QRY ? "QRY" : "CMD"); return NOTOK; case RC_FIN: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); (void) rcdone (); i = pidwait (PEERpid, OK); PEERpid = NOTOK; done (i); case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pLOOP(%s) protocol screw-up", code == RC_QRY ? "QRY" : "CMD"); }}/* */static int pTTY (r)register struct record *r;{ TYPESIG (*hstat) (), (*istat) (), (*qstat) (), (*tstat) (); struct record rcs; register struct record *rc = &rcs; initrc (rc); TTYoff (); hstat = signal (SIGHUP, SIG_IGN); istat = signal (SIGINT, SIG_IGN); qstat = signal (SIGQUIT, SIG_IGN); tstat = signal (SIGTERM, SIG_IGN); (void) rc2rc (RC_ACK, 0, NULLCP, rc); (void) signal (SIGHUP, hstat); (void) signal (SIGINT, istat); (void) signal (SIGQUIT, qstat); (void) signal (SIGTERM, tstat); TTYon (); if (r -> rc_len && strcmp (r -> rc_data, "FAST") == 0) goto no_refresh;#ifdef SIGTSTP (void) signal (SIGTSTP, SIG_IGN);#endif SIGTSTP#ifndef TERMINFO if (SO) tputs (SO, 0, _putchar);#else TERMINFO putp(enter_standout_mode);#endif TERMINFO fprintf (stdout, "Type any key to continue... "); (void) fflush (stdout);#ifndef TERMINFO if (SE) tputs (SE, 0, _putchar);#else TERMINFO putp(exit_standout_mode);#endif TERMINFO (void) getc (stdin);#ifdef SIGTSTP (void) signal (SIGTSTP, TSTPser);#endif SIGTSTP wrefresh (curscr);no_refresh: ; switch (rc -> rc_type) { case RC_EOF: (void) rc2peer (RC_ACK, 0, NULLCP); return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pTTY peer error"); return NOTOK; case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pTTY protocol screw-up"); }/* NOTREACHED */}/* */static int pWIN (w)register WINDOW *w;{ int i; did_less = 0; if ((i = pWINaux (w)) == OK && did_less) (void) WINless (w, 1); lreset (); return i;}/* */static int pWINaux (w)register WINDOW *w;{ register int n; int eol; register char c, *bp; struct record rcs; register struct record *rc = &rcs; initrc (rc); werase (w); wmove (w, 0, 0);#ifdef XYZ if (w == Status) wstandout (w);#endif XYZ for (eol = 0;;) switch (rc2rc (RC_ACK, 0, NULLCP, rc)) { case RC_DATA: if (eol && WINputc (w, '\n') == ERR && WINless (w, 0)) goto flush; for (bp = rc -> rc_data, n = rc -> rc_len; n-- > 0; ) { if ((c = *bp++) == '\n') linsert (w); if (WINputc (w, c) == ERR) if (n == 0 && c == '\n') eol++; else if (WINless (w, 0)) {flush: ; (void) fmt2peer (RC_ERR, "flush window");#ifdef XYZ /* should NEVER happen... */ if (w == Status) wstandend (w);#endif XYZ wrefresh (w); return NOTOK; } } break; case RC_EOF: (void) rc2peer (RC_ACK, 0, NULLCP);#ifdef XYZ if (w == Status) wstandend (w);#endif XYZ wrefresh (w); return OK; case RC_ERR: if (rc -> rc_len) adorn (NULLCP, "%s", rc -> rc_data); else adorn (NULLCP, "pWIN peer error"); return NOTOK; case RC_XXX: adios (NULLCP, "%s", rc -> rc_data); default: adios (NULLCP, "pWIN protocol screw-up"); }/* NOTREACHED */}/* */static int pFIN () { int status; if (PEERpid <= OK) return OK; (void) rc2peer (RC_FIN, 0, NULLCP); (void) rcdone (); switch (setjmp (PEERctx)) { case OK: (void) signal (SIGALRM, ALRMser); (void) alarm (ALARM); status = pidwait (PEERpid, OK); (void) alarm (0); break; default: (void) kill (PEERpid, SIGKILL); status = NOTOK; break; } PEERpid = NOTOK; return status;}/* WINDOWS */static int WINinit (nprog) { register int nlines, /* not "lines" because terminfo uses that */ top, bottom; foreground (); if (initscr () == (WINDOW *) ERR) if (nprog) return NOTOK; else adios (NULLCP, "could not initialize terminal");#ifdef SIGTSTP (void) signal (SIGTSTP, SIG_DFL);#endif SIGTSTP sideground ();#ifndef TERMINFO if (CM == NULL)#else TERMINFO if (cursor_address == NULL) /* assume mtr wanted "cm", not "CM" */#endif TERMINFO if (nprog) return NOTOK; else adios (NULLCP, "sorry, your terminal isn't powerful enough to run %s", invo_name);#ifndef TERMINFO if (tgetflag ("xt") || tgetnum ("sg") > 0) SO = SE = US = UE = NULL;#else TERMINFO/* * If termcap mapped directly to terminfo, we'd use the following: * if (teleray_glitch || magic_cookie_glitch > 0) * enter_standout_mode = exit_standout_mode = * enter_underline_mode = exit_underline_mode = NULL; * But terminfo does the right thing so we don't have to resort to that. */#endif TERMINFO if ((nlines = LINES - 1) < 11) adios (NULLCP, "screen too small"); if ((top = nlines / 3 + 1) > LINES / 4 + 2) top--; bottom = nlines - top - 2; numwins = 0; Scan = windows[numwins++] = newwin (top, COLS, 0, 0); Status = windows[numwins++] = newwin (1, COLS, top, 0);#ifndef XYZ wstandout (Status);#endif XYZ Display = windows[numwins++] = newwin (bottom, COLS, top + 1, 0); Command = newwin (1, COLS - 1, top + 1 + bottom, 0); windows[numwins] = NULL; largemove = Display -> _maxy / 2 + 2; return OK;}/* */static int WINgetstr (w, buffer)register WINDOW *w;char *buffer;{ register int c; register char *bp; bp = buffer; *bp = NULL; for (;;) { switch (c = toascii (wgetch (w))) { case ERR: adios (NULLCP, "wgetch lost"); case '\f': wrefresh (curscr); break; case '\r': case '\n': *bp = NULL; if (bp > buffer) { leaveok (curscr, FALSE); wmove (w, 0, w -> _curx - (bp - buffer)); wrefresh (w); leaveok (curscr, TRUE); } return DONE; default: if (c == intrc) { wprintw (w, " "); wstandout (w); wprintw (w, "Interrupt"); wstandend (w); wrefresh (w); *buffer = NULL; return NOTOK; } if (c == EOFC) { if (bp <= buffer) return OK; break; } if (c == ERASE) { if (bp <= buffer) continue; bp--, w -> _curx--; wclrtoeol (w); break; } if (c == KILL) { if (bp <= buffer) continue; w -> _curx -= bp - buffer; bp = buffer; wclrtoeol (w); break; } if (c == WERASC) { if (bp <= buffer) continue; do { bp--, w -> _curx--; } while (isspace (*bp) && bp > buffer); if (bp > buffer) { do { bp--, w -> _curx--;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?