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

📄 main.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
			goto err;	}	/* Set up the argument pointer. */	sp->a_frp = sp->frp;	/*	 * If there's an initial command, push it on the command stack.	 * Historically, it was always an ex command, not vi in vi mode	 * or ex in ex mode.  So, make it look like an ex command to vi.	 */	if (excmdarg != NULL)		if (IN_EX_MODE(sp)) {			if (term_push(sp, excmdarg, strlen(excmdarg), 0, 0))				goto err;		} else if (IN_VI_MODE(sp)) {			if (term_push(sp, "\n", 1, 0, 0))				goto err;			if (term_push(sp, excmdarg, strlen(excmdarg), 0, 0))				goto err;			if (term_push(sp, ":", 1, 0, 0))				goto err;		}	/*	 * Initialize the signals.  Use sigaction(2), not signal(3), because	 * we don't want to always restart system calls on 4BSD systems.  It	 * would be nice in some cases to restart system calls, but SA_RESTART	 * is a 4BSD extension so we can't use it.	 *	 * SIGALRM:	 *	Walk structures and call handling routines.	 * SIGHUP, SIGTERM, SIGWINCH:	 *	Catch and set a global bit.	 * SIGQUIT:	 *	Always ignore.	 */	act.sa_handler = h_alrm;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	if (sigaction(SIGALRM, &act, NULL)) {		msgq(sp, M_SYSERR, "timer: sigaction");		goto err;	}	act.sa_handler = h_hup;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	(void)sigaction(SIGHUP, &act, NULL);	act.sa_handler = h_term;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	(void)sigaction(SIGTERM, &act, NULL);	act.sa_handler = h_winch;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	(void)sigaction(SIGWINCH, &act, NULL);	act.sa_handler = SIG_IGN;	sigemptyset(&act.sa_mask);	act.sa_flags = 0;	(void)sigaction(SIGQUIT, &act, NULL);	for (;;) {		if (sp->s_edit(sp, sp->ep))			goto err;		/*		 * Edit the next screen on the display queue, or, move		 * a screen from the hidden queue to the display queue.		 */		if ((sp = __global_list->dq.cqh_first) ==		    (void *)&__global_list->dq)			if ((sp = __global_list->hq.cqh_first) !=			    (void *)&__global_list->hq) {				CIRCLEQ_REMOVE(&sp->gp->hq, sp, q);				CIRCLEQ_INSERT_TAIL(&sp->gp->dq, sp, q);			} else				break;		/*		 * The screen type may have changed -- reinitialize the		 * functions in case it has.		 */		switch (F_ISSET(sp, S_SCREENS)) {		case S_EX:			if (sex_screen_init(sp))				goto err;			break;		case S_VI_CURSES:			if (svi_screen_init(sp))				goto err;			break;		case S_VI_XAW:			if (xaw_screen_init(sp))				goto err;			break;		default:			abort();		}	}	eval = 0;	if (0)err:		eval = 1;	/*	 * NOTE: sp may be GONE when the screen returns, so only	 * the gp can be trusted.	 */	gs_end(gp);	exit(eval);}/* * gs_init -- *	Build and initialize the GS structure. */static GS *gs_init(){	GS *gp;	int fd;	CALLOC_NOMSG(NULL, gp, GS *, 1, sizeof(GS));	if (gp == NULL)		err(1, NULL);	CIRCLEQ_INIT(&gp->dq);	CIRCLEQ_INIT(&gp->hq);	LIST_INIT(&gp->msgq);	/* Structures shared by screens so stored in the GS structure. */	CALLOC_NOMSG(NULL, gp->tty, IBUF *, 1, sizeof(IBUF));	if (gp->tty == NULL)		err(1, NULL);	LIST_INIT(&gp->cutq);	LIST_INIT(&gp->seqq);	/* Set a flag if we're reading from the tty. */	if (isatty(STDIN_FILENO))		F_SET(gp, G_STDIN_TTY);	/*	 * Set the G_STDIN_TTY flag.  It's purpose is to avoid setting and	 * resetting the tty if the input isn't from there.	 *	 * Set the G_TERMIOS_SET flag.  It's purpose is to avoid using the	 * original_termios information (mostly special character values)	 * if it's not valid.  We expect that if we've lost our controlling	 * terminal that the open() (but not the tcgetattr()) will fail.	 */	if (F_ISSET(gp, G_STDIN_TTY)) {		if (tcgetattr(STDIN_FILENO, &gp->original_termios) == -1)			err(1, "tcgetattr");		F_SET(gp, G_TERMIOS_SET);	} else if ((fd = open(_PATH_TTY, O_RDONLY, 0)) != -1) {		if (tcgetattr(fd, &gp->original_termios) == -1)			err(1, "tcgetattr");		F_SET(gp, G_TERMIOS_SET);		(void)close(fd);	}	return (gp);}/* * gs_end -- *	End the GS structure. */static voidgs_end(gp)	GS *gp;{	MSG *mp;	SCR *sp;	char *tty;	/* Reset anything that needs resetting. */	if (gp->flags & G_SETMODE)			/* O_MESG */		if ((tty = ttyname(STDERR_FILENO)) == NULL)			warn("ttyname");		else if (chmod(tty, gp->origmode) < 0)			warn("%s", tty);	/* Ring the bell if scheduled. */	if (F_ISSET(gp, G_BELLSCHED))		(void)fprintf(stderr, "\07");		/* \a */	/* If there are any remaining screens, flush their messages. */	for (sp = __global_list->dq.cqh_first;	    sp != (void *)&__global_list->dq; sp = sp->q.cqe_next)		for (mp = sp->msgq.lh_first;		    mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)			(void)fprintf(stderr, "%.*s\n", (int)mp->len, mp->mbuf);	for (sp = __global_list->hq.cqh_first;	    sp != (void *)&__global_list->hq; sp = sp->q.cqe_next)		for (mp = sp->msgq.lh_first;		    mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)			(void)fprintf(stderr, "%.*s\n", (int)mp->len, mp->mbuf);	/* Flush messages on the global queue. */	for (mp = gp->msgq.lh_first;	    mp != NULL && !(F_ISSET(mp, M_EMPTY)); mp = mp->q.le_next)		(void)fprintf(stderr, "%.*s\n", (int)mp->len, mp->mbuf);	if (gp->special_key != NULL)		FREE(gp->special_key, MAX_FAST_KEY);	/*	 * DON'T FREE THE GLOBAL STRUCTURE -- WE DIDN'T TURN	 * OFF SIGNALS/TIMERS, SO IT MAY STILL BE REFERENCED.	 */}/* * h_hup -- *	Handle SIGHUP. */static voidh_hup(signo)	int signo;{	F_SET(__global_list, G_SIGHUP);	/*	 * If we're asleep, just die.	 *	 * XXX	 * This isn't right if the windows are independent.	 */	if (F_ISSET(__global_list, G_SLEEPING))		rcv_hup();}/* * h_term -- *	Handle SIGTERM. */static voidh_term(signo)	int signo;{	F_SET(__global_list, G_SIGTERM);	/*	 * If we're asleep, just die.	 *	 * XXX	 * This isn't right if the windows are independent.	 */	if (F_ISSET(__global_list, G_SLEEPING))		rcv_term();}/* * h_winch -- *	Handle SIGWINCH. */static voidh_winch(signo)	int signo;{	F_SET(__global_list, G_SIGWINCH);}/* * exrc_isok -- *	Check a .exrc file for source-ability. * * !!! * Historically, vi read both $HOME and local .exrc file if they were owned * by the user's real ID, or the "sourceany" option was set, regardless of * any other considerations.  We no longer support the sourceany option as * it's a security problem of mammoth proportions.  We require that the file * be owned by root (for the system .exrc files) or the user's effective ID * (for any of the .exrc files), and require that it not be writeable by * anyone other than the owner. *  * In O'Reilly ("Learning the VI Editor", Fifth Ed., May 1992, page 106), * it notes that System V release 3.2 and later has an option "[no]exrc". * The behavior is that local .exrc files are read only if the exrc option * is set.  The default for the exrc option was off, so, by default, local * .exrc files were not read.  The problem this was intended to solve was * that System V permitted users to give away files, so there's no possible * ownership/writeability test that the file is safe. *  * POSIX 1003.2-1992 standardized exrc as an option.  It required the exrc * option to be off by default, thus local .exrc files are not to be read * by default.  The Rationale noted (incorrectly) that this was a change * to historic practice, but correctly noted that a default of off improves * system security.  POSIX also required that vi check the effective user * ID instead of the real user ID, which is why we've switched from historic * practice. *  * We initialize the exrc variable to off.  If it's turned on by the system * or $HOME .exrc files, and the local .exrc file passes the ownership and * writeability tests, then we read it.  This breaks historic 4BSD practice, * but it gives us a measure of security on systems where users can give away * files. */static enum rcexrc_isok(sp, sbp, path, rootok)	SCR *sp;	struct stat *sbp;	char *path;	int rootok;{	uid_t uid;	char *emsg, buf[MAXPATHLEN];	/* Check for the file's existence. */	if (stat(path, sbp))		return (NOEXIST);	/* Owned by the user or root. */	uid = geteuid();	if (rootok) {		if (sbp->st_uid != uid && sbp->st_uid != 0) {			emsg = "not owned by you or root";			goto denied;		}	} else		if (sbp->st_uid != uid) {			emsg = "not owned by you";			goto denied;		}	/* Not writeable by anyone but the owner. */	if (sbp->st_mode & (S_IWGRP | S_IWOTH)) {		emsg = "writeable by a user other than the owner";denied:		if (strchr(path, '/') == NULL &&		    getcwd(buf, sizeof(buf)) != NULL)			msgq(sp, M_ERR,			    "%s/%s: not sourced: %s.", buf, path, emsg);		else			msgq(sp, M_ERR,			    "%s: not sourced: %s.", path, emsg);		return (NOPERM);	}	return (OK);}static voidobsolete(argv)	char *argv[];{	size_t len;	char *p;	/*	 * Translate old style arguments into something getopt will like.	 * Make sure it's not text space memory, because ex changes the	 * strings.	 *	Change "+" into "-c$".	 *	Change "+<anything else>" into "-c<anything else>".	 *	Change "-" into "-s"	 *	Change "-r" into "-l"	 */	while (*++argv)		if (argv[0][0] == '+') {			if (argv[0][1] == '\0') {				MALLOC_NOMSG(NULL, argv[0], char *, 4);				if (argv[0] == NULL)					err(1, NULL);				(void)strcpy(argv[0], "-c$");			} else  {				p = argv[0];				len = strlen(argv[0]);				MALLOC_NOMSG(NULL, argv[0], char *, len + 2);				if (argv[0] == NULL)					err(1, NULL);				argv[0][0] = '-';				argv[0][1] = 'c';				(void)strcpy(argv[0] + 2, p + 1);			}		} else if (argv[0][0] == '-') {			if (argv[0][1] == 'r') {				if (argv[0][2] == '\0' && argv[1] == NULL)					argv[0][1] = 'l';			} else if (argv[0][1] == '\0') {				MALLOC_NOMSG(NULL, argv[0], char *, 3);				if (argv[0] == NULL)					err(1, NULL);				(void)strcpy(argv[0], "-s");			}		}}static voidusage(is_ex)	int is_ex;{#define	EX_USAGE \	"usage: ex [-eFlRsv] [-c command] [-r file] [-t tag] [-w size] [-x aw]"#define	VI_USAGE \	"usage: vi [-eFlRv] [-c command] [-r file] [-t tag] [-w size] [-x aw]"	(void)fprintf(stderr, "%s\n", is_ex ? EX_USAGE : VI_USAGE);	exit(1);}

⌨️ 快捷键说明

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