⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 commands.c

📁 操作系统源代码
💻 C
字号:
/* Copyright (c) 1985 Ceriel J.H. Jacobs */# ifndef lintstatic char rcsid[] = "$Header: commands.c,v 1.1 91/12/17 13:05:45 philip Exp $";# endif# define _COMMANDS_# include "in_all.h"# include "commands.h"# include "output.h"# include "process.h"# include "help.h"# include "term.h"# include "prompt.h"# include "getline.h"# include "getcomm.h"# include "pattern.h"# include "display.h"# include "options.h"# include "machine.h"# include "keys.h"# include "main.h"# include "assert.h"# if USG_OPEN# include <fcntl.h># include <errno.h>extern int errno;# endif# if BSD4_2_OPEN# include <sys/file.h># include <errno.h>extern int errno;# endif# if POSIX_OPEN# include <sys/types.h># include <fcntl.h># include <errno.h># endifchar	*strcpy(), *strcat();static long lastcount;		/* Save last count for '.' command */static int lastcomm;		/* Save last command for '.' command *//*ARGSUSED*/STATIC intdo_nocomm(cnt) long cnt; {	/* Do nothing */}/*ARGSUSED*/intdo_chkm(cnt) long cnt; {	/* Change key map */	register struct keymap *p;	if (!(p = othermap)) {		error("No other keymap");		return;	}	othermap = currmap;	currmap = p;}static int searchdir;		/* Direction of last search *//* * Perform searches */STATIC VOIDdo_search(str,cnt,dir) char *str; long cnt; int dir; {	register char *p;	register long lineno;	if (str) {		/*		 * We have to get a pattern, which we have to prompt for		 * with the string "str".		 */		if ((p = readline(str)) == 0) {			/*			 * User cancelled command			 */			return;		}		if ((p = re_comp(p))) {			/*			 * There was an error in the pattern			 */			error(p);			return;		}		searchdir = dir;	}	if (dir < 0) lineno = scr_info.firstline;	else lineno = scr_info.lastline;	for (;;) {		p = 0;		if ((lineno += dir) > 0) p = getline(lineno, 0);		if (interrupt) return;		if (!p) {	/* End of file reached */			error("pattern not found");			return;		}		if (re_exec(p) && --cnt <= 0) {			/*			 * We found the pattern, and we found it often enough.			 * Pity that we still don't know where the match is.			 * We only know the linenumber. So, we just hope the			 * following will at least bring it on the screen ...			 */			(VOID) display(lineno,0,pagesize,0);			(VOID) scrollb(2,0);			redraw(0);			return;		}	}	/* NOTREACHED */}STATIC intdo_fsearch(cnt) long cnt; {	/* Forward search */	do_search("/", cnt, 1);}STATIC intdo_bsearch(cnt) long cnt; {	/* Backward search */	do_search("?", cnt, -1);}/* * Repeat last search in direction "dir" */STATIC intn_or_rn_search(cnt,dir) long cnt; int dir; {	register char *p;	if (dir == 1) {		p = "/\r";	}	else if (dir == -1) {		p = "?\r";	}	else {		error("No previous pattern");		return;	}	if (!stupid) clrbline();	putline(p);	flush();	do_search((char *) 0, cnt, dir);}STATIC intdo_nsearch(cnt) long cnt; {	/* Repeat search in same direction */		n_or_rn_search(cnt,searchdir);}STATIC intdo_rnsearch(cnt) long cnt; {	/* Repeat search in opposite direction */	n_or_rn_search(cnt, -searchdir);}STATIC int shell(esc_ch, cnt) long cnt;{	register char *p;	static char buf[2];	buf[0] = esc_ch;	if (p = readline(buf)) {		shellescape(p, esc_ch);		if (cnt >= 0 && !hardcopy) {			p = startcomm;			startcomm = 0;			ret_to_continue();			putline(TI);			if (!p) {				/*				 * Avoid double redraw.				 * After a "startcomm", a redraw will				 * take place anyway.				 */				redraw(1);			}		}	}}STATIC intdo_shell(cnt) long cnt; {	/* Execute a shell escape */	shell('!', cnt);}STATIC intdo_pipe(cnt) long cnt; {	/* Execute a shell escape */	shell('|', cnt);}/*ARGSUSED*/STATIC intdo_writefile(cnt) long cnt; {	/* Write input to a file */	register char *p;	int fd;	if ((p = readline("Filename: ")) == 0 || !*p) {		/*		 * No file name given		 */		return;	}# if USG_OPEN || BSD4_2_OPEN || POSIX_OPEN	if ((fd = open(p,O_CREAT|O_EXCL|O_WRONLY,0644)) < 0) {		if (errno == EEXIST) {			error("File exists");			return;		}		error("Could not open file");		return;	}# else	if (!access(p,0)) {		error("File exists");		return;	}	if ((fd = creat(p,0644)) < 0) {		error("Could not open file");		return;	}# endif	wrt_fd(fd);	(VOID) close(fd);}VOIDwrt_fd(fd){	register long l = 1;	register char *p = getline(l,0), *pbuf;	char buf[1024];	while (p) {		pbuf = buf;		while (p && pbuf < &buf[1024]) {			if (!*p) {				*pbuf++ = '\n';				p = getline(++l,0);			}			else *pbuf++ = *p++ & 0177;		}		if (write(fd, buf, pbuf - buf) < 0) {			error("Write failed");			break;		}	}}STATIC intdo_absolute(cnt) long cnt; {	/* Go to linenumber "cnt" */	if (!getline(cnt,0)) {	/* Not there or interrupt */		if (!interrupt) {			/*			 * User did'nt give an interrupt, so the line number			 * was too high. Go to the last line.			 */			do_lline(cnt);		}		return;	}	(VOID) display(cnt,0,pagesize,1);}/*ARGSUSED*/STATIC intdo_visit(cnt) long cnt; {	/* Visit a file */	register char *p;	static char fn[128];	/* Keep file name */	if ((p = readline("Filename: ")) == 0) {		return;	}	if (*p) {		(VOID) strcpy(fn,p);		visitfile(fn);	}	else {		/*		 * User typed a return. Visit the current file		 */		if (!(p = filenames[filecount])) {			error("No current file");			return;		}		visitfile(p);	}	(VOID) display(1L, 0, pagesize, 1);}/*ARGSUSED*/STATIC intdo_error(cnt) long cnt; {	/* Called when user types wrong key sequence */	error(currmap->k_help);}/* * Interface routine for displaying previous screen, * depending on cflag. */STATIC intprev_screen(sz,really) int sz, really; {	register int retval;	retval = scrollb(sz - 1, really && cflag);	if (really && !cflag) {		/*		 * The previous call did not display anything, but at least we		 * know where to start		 */		return display(scr_info.firstline, scr_info.nf, sz, 1);	}	return retval;}/* * Interface routine for displaying the next screen, * dependent on cflag. */STATIC intnext_screen(sz,really) int sz, really; {	register int t;	register struct scr_info *p = &scr_info;	if (cflag) {		return scrollf(sz-1,really);	}	t = p->tail->cnt - 1;	if (p->lastline == p->firstline) {		t += p->nf;	}	return display(p->lastline, t, sz, really);}/*ARGSUSED*/STATIC intdo_redraw(cnt) long cnt; {	redraw(1);}STATIC intpage_size(cnt) unsigned cnt; {	if (cnt) {		if (cnt > maxpagesize) return maxpagesize;		if (cnt < MINPAGESIZE) return MINPAGESIZE;		return (int) cnt;	}	return pagesize;}STATIC intdo_forward(cnt) long cnt; {	/* Display next page */	register int i;	i = page_size((unsigned) cnt);	if (status & EOFILE) {		/*		 * May seem strange, but actually a visit to the next file		 * has already been done here		 */		(VOID) display(1L,0,i,1);		return;	}	(VOID) next_screen(i,1);}STATIC intdo_backward(cnt) long cnt; {	register int i, temp;	i = page_size((unsigned) cnt);	if (!(status & START)) {		(VOID) prev_screen(i,1);		return;	}	if (stdf < 0) {		(VOID) display(1L,0,i,1);		return;	}	/*	 * The next part is a bit clumsy.	 * We want to display the last page of the previous file (for which	 * a visit has already been done), but the pagesize may temporarily	 * be different because the command had a count	 */	temp = pagesize;	pagesize = i;	do_lline(cnt);	pagesize = temp;}/*ARGSUSED*/STATIC intdo_firstline(cnt) long cnt; {	/* Go to start of input */	do_absolute(1L);}STATIC intdo_lline(cnt) long cnt; {	/* Go to end of input */	register int i = 0;	register int j = pagesize - 1;	if ((cnt = to_lastline()) < 0) {		/*		 * Interrupted by the user		 */		return;	}	/*	 * Display the page such that only the last line of the page is	 * a "~", independant of the pagesize	 */	while (!(display(cnt,i,j,0) & EOFILE)) {		/*		 * The last line could of course be very long ...		 */		i+= j;	}	(VOID) scrollb(j - scr_info.tail->cnt, 0);	redraw(0);}STATIC intdo_lf(cnt) long cnt; {		/* Display next line, or go to line */	if (cnt) {		/* Go to line */		do_absolute(cnt);		return;	}	(VOID) scrollf(1,1);}STATIC intdo_upline(cnt) long cnt; {	/* Display previous line, or go to line */	if (cnt) {		/* Go to line */		do_absolute(cnt);		return;	}	(VOID) scrollb(1,1);}STATIC intdo_skiplines(cnt) long cnt; {	/* Skip lines forwards */	/* Should be interruptable ... */	(VOID) scrollf((int) (cnt + maxpagesize - 1), 0);	redraw(0);}STATIC intdo_bskiplines(cnt) long cnt; {	/* Skip lines backwards */	/* Should be interruptable ... */	(VOID) scrollb((int) (cnt + pagesize - 1), 0);	redraw(0);}STATIC intdo_fscreens(cnt) long cnt; {	/* Skip screens forwards */	do {		if ((next_screen(pagesize,0) & EOFILE) || interrupt) break;	} while (--cnt >= 0);	redraw(0);}STATIC intdo_bscreens(cnt) long cnt; {	/* Skip screens backwards */	do {		if ((prev_screen(pagesize,0) & START) || interrupt) break;	} while (--cnt >= 0);	redraw(0);}STATIC intscro_size(cnt) unsigned cnt; {	if (cnt >= maxpagesize) return maxpagesize;	if (cnt) return (int) cnt;	return scrollsize;}STATIC intdo_f_scroll(cnt) long cnt; {	/* Scroll forwards */	(VOID) scrollf(scro_size((unsigned) cnt),1);}STATIC intdo_b_scroll(cnt) long cnt; {	/* Scroll backwards */	(VOID) scrollb(scro_size((unsigned) cnt),1);}STATIC intdo_previousfile(cnt) long cnt; {/* Visit previous file */	if (nextfile(- (int) cnt)) {		error("No (Nth) previous file");		return;	}	redraw(0);}STATIC intdo_nextfile(cnt) long cnt; {	/* Visit next file */	if (nextfile((int) cnt)) {		error("No (Nth) next file");		return;	}	redraw(0);}STATIC int do_lcomm();/* * The next array is initialized, sorted on the first element of the structs, * so that we can perform binary search */struct commands commands[] = {{"",	    0,	    do_error,	    ""},{"",	    0,	    do_nocomm,	    ""},{"bf",	    STICKY|NEEDS_COUNT,		    do_previousfile,"Visit previous file"},{"bl",	    NEEDS_SCREEN|STICKY,		    do_upline,	    "Scroll one line up, or go to line"},{"bot",	    STICKY,		    do_lline,	    "Go to last line of the input"},{"bp",	    BACK|NEEDS_SCREEN|TOPREVFILE|STICKY,		    do_backward,    "display previous page"},{"bps",	    SCREENSIZE_ADAPT|BACK|NEEDS_SCREEN|TOPREVFILE|STICKY,		    do_backward,    "Display previous page, set pagesize"},{"bs",	    BACK|NEEDS_SCREEN|STICKY,		    do_b_scroll,    "Scroll backwards"},{"bse",	    0,	    do_bsearch,	    "Search backwards for pattern"},{"bsl",	    BACK|NEEDS_SCREEN|STICKY|NEEDS_COUNT,		    do_bskiplines,  "Skip lines backwards"},{"bsp",	    BACK|NEEDS_SCREEN|STICKY|NEEDS_COUNT,		    do_bscreens,    "Skip screens backwards"},{"bss",	    SCROLLSIZE_ADAPT|BACK|NEEDS_SCREEN|STICKY,		    do_b_scroll,    "Scroll backwards, set scrollsize"},{"chm",	    0,	    do_chkm,	    "Switch to other keymap"},{"exg",	    STICKY, exgmark,	    "Exchange current page with mark"},{"ff",	    STICKY|NEEDS_COUNT,		    do_nextfile,    "Visit next file"},{"fl",	    NEEDS_SCREEN|STICKY,		    do_lf,	    "Scroll one line down, or go to line"},{"fp",	    TONEXTFILE|AHEAD|STICKY,		    do_forward,	    "Display next page"},{"fps",	    SCREENSIZE_ADAPT|TONEXTFILE|AHEAD|STICKY,		    do_forward,	    "Display next page, set pagesize"},{"fs",	    AHEAD|NEEDS_SCREEN|STICKY,		    do_f_scroll,    "Scroll forwards"},{"fse",	    0,	    do_fsearch,	    "Search forwards for pattern"},{"fsl",	    AHEAD|NEEDS_SCREEN|STICKY|NEEDS_COUNT,		    do_skiplines,   "Skip lines forwards"},{"fsp",	    AHEAD|NEEDS_SCREEN|STICKY|NEEDS_COUNT,		    do_fscreens,    "Skip screens forwards"},{"fss",	    SCROLLSIZE_ADAPT|AHEAD|NEEDS_SCREEN|STICKY,		    do_f_scroll,    "Scroll forwards, set scrollsize"},{"hlp",	    0,	    do_help,	    "Give description of all commands"},{"mar",	    0,	    setmark,	    "Set a mark on the current page"},{"nse",	    STICKY, do_nsearch,	    "Repeat the last search"},{"nsr",	    STICKY, do_rnsearch, "Repeat last search in other direction"},{"pip",     ESC,    do_pipe,	    "pipe input into shell command"},{"qui",	    0,	    quit,	    "Exit from yap"},{"red",	    0,	    do_redraw,	    "Redraw screen"},{"rep",	    0,	    do_lcomm,	    "Repeat last command"},{"shl",	    ESC,    do_shell,	    "Execute a shell escape"},{"tom",	    0,	    tomark,	    "Go to mark"},{"top",	    STICKY, do_firstline,   "Go to the first line of the input"},{"vis",	    0,	    do_visit,	    "Visit a file"},{"wrf",	    0,	    do_writefile,   "Write input to a file"},};/* * Lookup string "s" in the commands array, and return index. * return 0 if not found. */intlookup(s) char *s; {	register struct commands *l, *u, *m;	l = &commands[2];	u = &commands[sizeof(commands) / sizeof(*u) - 1];	do {		/*		 * Perform binary search		 */		m = l + (u - l) / 2;		if (strcmp(s, m->c_cmd) > 0) l = m + 1;		else u = m;	} while (l < u);	if (!strcmp(s, u->c_cmd)) return u - commands;	return 0;}/*ARGSUSED*/STATIC intdo_lcomm(cnt) long cnt; {	/* Repeat last command */	if (!lastcomm) {		error("No previous command");		return;	}	do_comm(lastcomm, lastcount);}/* * Execute a command, with optional count "count". */VOIDdo_comm(comm, count) register int comm; register long count; {	register struct commands *pcomm;	register int temp;	register int flags;	pcomm = &commands[comm];	flags = pcomm->c_flags;	/*	 * Check the command.	 * If the last line of the file is displayed and the command goes	 * forwards and does'nt have the ability to go to the next file, it	 * is an error.	 * If the first line of the file is displayed and the command goes	 * backwards and does'nt have the ability to go to the previous file,	 * it is an error.	 * Also check wether we need the next or previous file. If so, get it.	 */	if ((status & EOFILE) && (flags & AHEAD)) {		if (qflag || !(flags & TONEXTFILE)) return;		if (nextfile(1)) quit();	}	if ((status & START) && (flags & BACK)) {		if (qflag || !(flags & TOPREVFILE)) return;		if (nextfile(-1)) quit();	}	/*	 * Does the command stick around for LASTCOMM?	 */	if (flags & STICKY) {		lastcomm = comm;		lastcount = count;	}	if (!count) {		if (flags & NEEDS_COUNT) count = 1;	}	else {		/*		 * Does the command adapt the screensize?		 */		if (flags & SCREENSIZE_ADAPT) {			temp = maxpagesize;			if ((unsigned) count < temp) {				temp = count;			}			if (temp < MINPAGESIZE) {				temp = MINPAGESIZE;			}			count = 0;			pagesize = temp;		}		/*		 * Does the command adapt the scrollsize?		 */		if (flags & SCROLLSIZE_ADAPT) {			temp = maxpagesize - 1;			if ((unsigned) count < temp) {				temp = (int) count;			}			scrollsize = temp;			count = 0;		}	}	/*	 * Now execute the command.	 */	(*(pcomm->c_func))(count);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -