|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 12000 (0x2ee0) Types: TextFile Names: »mysystem.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« └─⟦dcb95597f⟧ └─⟦this⟧ »mysystem.c«
#ifndef lint static char rcsid[] = "$Header: mysystem.c,v 2.12 88/01/13 19:10:51 deboor Exp $"; static char notice[] = "This program is in the public domain and is available for unlimited \ distribution as long as this notice is enclosed."; #endif /* * new system routines for vmh. old ones weren't sufficient. * * $Source: /c/support/deboor/usr/src/old/vmh/RCS/mysystem.c,v $ * $Revision: 2.12 $ * $Author: deboor $ * * FUNCTIONS: * Pcmd execute a command with a shell and page output in * bottom window. * call_prepare prepare for executing an external command with messages * and the resetting of the tty state * call_recover recover from an external command. * do_refresh interrupt routine to worry about refreshing the screen * after vmh has been suspended * flushinput nuke any typeahead * my_system system() with terminal reset, etc. * my_tstp ^Z catcher * my_vfork vfork with terminal reset, etc. * newtty initialize/set tty modes to those desired by vmh * oldtty reset tty to initial state * system vmh version of the system() library call (probably un- * nec'y) */ #include "vmh.h" /* Mine */ #include <sys/wait.h> #include <sys/resource.h> /* #include <sys/param.h> /* For NOFILES parameter (given by ff) */ extern struct tchars chars; /* Filled initially by init.c */ extern struct ltchars lchars; /* ditto */ extern char *KS, *KE; my_system(cmd, pause) char *cmd; int pause; { register int rc; if( !*cmd ) return -1; call_prepare(); /* Prepare for system call */ rc = system(cmd); /* Go do the cmd */ call_recover(pause, 0); /* Recover from system call */ return( rc ); } my_vfork(argv, pause) char *argv[]; int pause; /* non zero if need to wait 1 more char */ { int pid; register int (*istat)(), (*qstat)(); call_prepare(); pid = vfork(); if (pid == 0) { int i, j; j = getdtablesize(); for (i=3; i < j ; i++) /* Close all the extra fd's */ (void) close(i); execvp(argv[0], argv); printf(" *** Unable to exec %s\n", argv[0]); (void) fflush(stdout); _exit(1); /*NOTREACHED*/ } else { /* Parent */ int cpid; union wait CStat; /* Copied from system(3) */ istat = signal(SIGINT, SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); do { while ((cpid = wait3 (&CStat, WUNTRACED, (struct rusage *)0)) == 0) ; if ((cpid == pid) && WIFSTOPPED (CStat)) { (void) kill (pid, SIGCONT); cpid = 0; } } while (cpid != -1 && cpid != pid); (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); /* If non-zero rc (i.e. error) */ if (WIFSIGNALED (CStat) || WIFEXITED (CStat)) sleep(2); /* then sleep 2 to show err msg */ call_recover(pause, 0); /* Recover from call & do pause logic */ return( CStat.w_retcode ); } } /* * fflush on an input stream is undefined; and in 4.1bsd, fflush on * an input stream is a nop. */ flushinput() { stdin->_cnt = 0; /* Discard any in the stdin buffer */ (void) Ioctl(fileno(stdin), TIOCFLUSH, 0); /* Discard any in kernal */ } /* * Run cmd via popen() managing any output in the bottom window. * * (note: popen invokes a shell, which closes off excess fd's) */ Pcmd( cmd ) register char *cmd; { FILE *fp, *popen(), *pclose(); char line[150]; if( !*cmd ) return; syncfolders(); /* Refresh .infos to disk */ (void) sprintf( line, " Command: %s ", cmd ); dotitle( botHdr, line ); wclear( botWin ); wrefresh( botWin ); wmove( botWin, 1, 0 ); /* * Execute it */ /*** Bug! distributed popen leaves stderr going to the screen. Modified version of it joins it with stdout to the pipe, but that's not that great either. -- guyton ***/ fp = popen( cmd, "r" ); if( fp == NULL ) { (void) sprintf( line, "Can't open pipe to execute %s", cmd); errormsg( line, 1 ); startwatch(); return; } init_pager ((FILE *) NULL, botWin); while( fgets( line, sizeof(line), fp )) { if (putstr (line)) break; } end_pager(); wrefresh( botWin ); pclose( fp ); /* startwatch(); was broken, seems ok again */ /** recheck the folders?? **/ #ifdef notdef window.ws_row = rows; window.ws_col = cols; (void) Ioctl (0, TIOCSWINSZ, &window); #endif return; } # ifdef SIGTSTP static struct itimerval bg_timer = { /* clock for continuous refreshes */ {0, 0}, /* interval */ {0, 0}, /* value */ }; int no_tty = 0; /* if this is one, then we don't have a tty */ /* used by updatetop() */ /* ** do_refresh() ** called by my_tstp and used for SIGVTALRM catching. If the ** tty attached to descriptor 1's process group is our ** process group, we are in the foreground. If ** so, then refreshes the screen, disables the timer and ** returns. Otherwise, if the timer isn't going, then starts ** it to expire in one half second and reset to one half second after ** each expiration. */ static struct sigvec oldvt; static struct itimerval oldvtt; static int initial_mask; do_refresh (not_init) int not_init; /* called w/non-0 sig when catching */ { int _putchar(); int pgrp; if ( ! not_init) { bg_timer.it_value.tv_sec = bg_timer.it_interval.tv_sec = 0; /* * set interval to 1/2 second */ bg_timer.it_value.tv_usec = bg_timer.it_interval.tv_usec = 500000; (void) Setitimer (ITIMER_VIRTUAL, &bg_timer, &oldvtt); initial_mask = sigblock(0); (void) sigsetmask(0); } (void) Ioctl (0, TIOCGPGRP, &pgrp); /* get process group */ if ( pgrp == getpgrp(0)) { /* == => we're back */ (void) sigsetmask (initial_mask); (void) sigvec (SIGVTALRM, &oldvt, (struct sigvec *) 0); (void) Setitimer(ITIMER_VIRTUAL, &oldvtt, (struct itimerval *) 0); do_autoclear(); wrefresh(curscr); /* Repaint the entire screen */ newtty(); /* Set my tty parms and signals */ no_tty = 0; /* Put cursor back */ tputs(tgoto(CM, curscr->_curx, curscr->_cury), 1, _putchar); (void) fflush(stdout); } else no_tty = 1; } /* * handle stop and start signals * modified from curses sources for vmh. */ my_tstp(signo) int signo; { int oldx, oldy; /* Old cursor position */ int do_refresh(); struct sigvec refr; int mask; oldx = curscr->_curx; /* Save for after continue */ oldy = curscr->_cury; syncfolders(); /* Refresh .infos to disk */ mvcur(0, COLS - 1, LINES - 1, 0); /* Move to bottom of scr */ oldtty(); /* Reset tty/signals to init state */ /* also resets start/stop signal */ refr.sv_handler = do_refresh; refr.sv_mask = refr.sv_onstack = 0; (void) sigvec (SIGVTALRM, &refr, &oldvt); mask = sigblock (0); (void) sigsetmask(mask & ~sigmask(signo)); (void) kill(0, signo); /* Stop me */ (void) sigsetmask (mask); /* Have returned from stop */ do_refresh (0); /* set up refresh loop */ curscr->_curx = oldx; curscr->_cury = oldy; /*** infomsg("Welcome back!"); sleep(2); ***/ recheckfldrs(); /* See if .infos changed on me! */ } # endif SIGTSTP int (*oldtstp)(); /* Old value of tstp handler (fix types!) */ call_prepare() { infomsg("Wait ...\n", 1); mvcur (0,COLS-1, LINES-1,0); (void) fflush (stdout); endwatch(); /* Turn off mailcheck daemon */ holdclock(); syncfolders(); /* Refresh .infos to disk */ oldtty(); /* Fixup tty & signals to initial state */ } call_recover(pause, check) int pause; /* Non-zero if want to pause */ int check; /* Non-zero if want to check folders */ { register i; char jc; newtty(); /* Set my tty parms and signals */ wclear(cmdWin); mvcur (0, COLS-1, LINES-1, 0); if (pause) { /* If want to discard next char */ /* echo turned off by newtty() */ (void) write(1, ":", 1); (void) read (0, &jc, 1); } do_autoclear(); wrefresh(curscr); /* Redisplay the entire screen */ startwatch(); /* Restart the new-mail daemon */ startclock(); if (check) /* Should do this all the time someday */ recheckfldrs(); /* See if .infos changed on me! */ dotitle (botHdr, HELPMSG); } /* * Set up tty parms the way vmh want's 'em * assumes a couple of Ioctl's in init.c */ extern char start, stop; /*XXX: should be in vmh.h */ newtty() { chars.t_intrc = -1; /* Disable the del key */ chars.t_stopc = -1; chars.t_startc = -1; lchars.t_lnextc = -1; /* and the literal-next */ lchars.t_dsuspc = -1; /* and the delayed-suspend key */ (void) Ioctl(_tty_ch, TIOCSETC, &chars); (void) Ioctl(_tty_ch, TIOCSLTC, &lchars); (void) Fchmod(_tty_ch, new_tty_mode); /* set biff properly */ crmode(); /* Set cbreak mode */ noecho(); /* Turn off echo */ nonl(); /* don't want newline mapping */ _puts (KS); /* switch to application keypad */ flushinput(); /* Throw away typeahead */ #ifdef SIGTSTP (void) signal(SIGTSTP, my_tstp); /* Install my start/stop routine */ #endif } /* * Restore tty parms to what they were on entry */ oldtty() { extern SGTTY ttyb; chars.t_intrc = quit; /* Restore original DEL key */ chars.t_startc = start; chars.t_stopc = stop; lchars.t_lnextc = litnext; /* and original litnext char */ lchars.t_dsuspc = dsuspc; /* and original ^Y char */ (void) Ioctl(_tty_ch, TIOCSETC, &chars); (void) Ioctl(_tty_ch, TIOCSLTC, &lchars); (void) Ioctl(_tty_ch, TIOCSETP, &ttyb); /* and original modes */ (void) Fchmod(_tty_ch, init_tty_mode); /* reset biff */ _puts (KE); /* back to normal keypad */ endwin(); /* Turn off cbreak, turn on echo */ #ifdef COMMENT Turns out the fflush is not what is wanted here. The ambassador termcap entry TE (sent by the endwin routine) is enough to clear the bottom line and get rid of the "Waiting ..." msg that was so carefully put up. So, for now lets just leave out the fflush and it will get sent later. #endif COMMENT (void) fflush(stdout); /* Wonder if this line is required? */ #ifdef SIGTSTP (void) signal(SIGTSTP, SIG_DFL); /* Install default start/stop */ #endif } /* This is just system(3) except with csh instead of sh. Not just that I like csh (I do), but "sh" doesn't close excess open fd's across exec's and vmh was running out of fd's. -- Guyton 2/83 */ system(s) char *s; { union wait status; int pid, w; register int (*istat)(), (*qstat)(); if ((pid = vfork()) == 0) { execl("/bin/csh", "csh", "-c", s, 0); _exit(127); } istat = signal(SIGINT ,SIG_IGN); qstat = signal(SIGQUIT, SIG_IGN); /* do WUNTRACED here ? */ while ((w = wait(&status)) != pid && w != -1) ; if (w == -1) status.w_retcode = -1; (void) signal(SIGINT, istat); (void) signal(SIGQUIT, qstat); return(status.w_retcode); } /* * do_autoclear() * this function is used to speed things up <= 1200 baud. if the auto_clear * flag is set, then don't want to redisplay the contents of the bottom * window. But if just do a wclear() wrefresh() sequence, curses prints * a row of spaces. This is designed to alleviate that since the screen * has already been cleared by a clear-screen terminal sequence. Whether * it will work is up to curses, though. */ do_autoclear() { register int i; register int j; int endx = botWin->_begx + botWin->_maxx; int endy = botWin->_begy + botWin->_maxy; if (! auto_clear) return; werase (botWin);/* do it now */ /* * THIS IS A HACK!!! It should work only for this * specific implementation of curses...if then. */ for (i = botWin->_begy; i < endy; i++) { for (j = botWin->_begx; j < endx; j++) { curscr->_y[i][j] = ' '; } } for (i=0; i < botWin->_maxy; i++) botWin->_lastch[i] = botWin->_firstch[i] = curscr->_lastch[curscr->_begy+i] = curscr->_firstch[curscr->_begy+i] = _NOCHANGE; }