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 + -
显示快捷键?