📄 main.c
字号:
/*- * Copyright (c) 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1992, 1993\n\ The Regents of the University of California. All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)main.c 8.80 (Berkeley) 4/15/94";#endif /* not lint */#include <sys/param.h>#include <sys/queue.h>#include <sys/stat.h>#include <sys/time.h>#include <bitstring.h>#include <ctype.h>#include <err.h>#include <errno.h>#include <fcntl.h>#include <limits.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <termios.h>#include <unistd.h>#ifdef __STDC__#include <stdarg.h>#else#include <varargs.h>#endif#include "compat.h"#include <db.h>#include <regex.h>#include <pathnames.h>#include "vi.h"#include "excmd.h"#include "tag.h"enum rc { NOEXIST, NOPERM, OK };static enum rc exrc_isok __P((SCR *, struct stat *, char *, int));static void gs_end __P((GS *));static GS *gs_init __P((void));static void h_hup __P((int));static void h_term __P((int));static void h_winch __P((int));static void obsolete __P((char *[]));static void usage __P((int));GS *__global_list; /* GLOBAL: List of screens. */intmain(argc, argv) int argc; char *argv[];{ extern int optind; extern char *optarg; static int reenter; /* STATIC: Re-entrancy check. */ struct sigaction act; struct stat hsb, lsb; GS *gp; FREF *frp; SCR *sp; u_int flags, saved_vi_mode; int ch, eval, flagchk, readonly, silent, snapshot; char *excmdarg, *myname, *p, *rec_f, *tag_f, *trace_f, *wsizearg; char path[MAXPATHLEN]; /* Stop if indirecting through a NULL pointer. */ if (reenter++) abort(); /* Set screen type and mode based on the program name. */ readonly = 0; if ((myname = strrchr(*argv, '/')) == NULL) myname = *argv; else ++myname; if (!strcmp(myname, "ex") || !strcmp(myname, "nex")) LF_INIT(S_EX); else { /* View is readonly. */ if (!strcmp(myname, "view")) readonly = 1; LF_INIT(S_VI_CURSES); } saved_vi_mode = S_VI_CURSES; /* Convert old-style arguments into new-style ones. */ obsolete(argv); /* Parse the arguments. */ flagchk = '\0'; excmdarg = rec_f = tag_f = trace_f = wsizearg = NULL; silent = 0; snapshot = 1; while ((ch = getopt(argc, argv, "c:eFlRr:sT:t:vw:x:")) != EOF) switch (ch) { case 'c': /* Run the command. */ excmdarg = optarg; break; case 'e': /* Ex mode. */ LF_CLR(S_SCREENS); LF_SET(S_EX); break; case 'F': /* No snapshot. */ snapshot = 0; break; case 'l': if (flagchk != '\0' && flagchk != 'l') errx(1, "only one of -%c and -l may be specified.", flagchk); flagchk = 'l'; break; case 'R': /* Readonly. */ readonly = 1; break; case 'r': /* Recover. */ if (flagchk == 'r') errx(1, "only one recovery file may be specified."); if (flagchk != '\0') errx(1, "only one of -%c and -r may be specified.", flagchk); flagchk = 'r'; rec_f = optarg; break; case 's': silent = 1; break; case 'T': /* Trace. */ trace_f = optarg; break; case 't': /* Tag. */ if (flagchk == 't') errx(1, "only one tag file may be specified."); if (flagchk != '\0') errx(1, "only one of -%c and -t may be specified.", flagchk); flagchk = 't'; tag_f = optarg; break; case 'v': /* Vi mode. */ LF_CLR(S_SCREENS); LF_SET(S_VI_CURSES); break; case 'w': wsizearg = optarg; break; case 'x': if (!strcmp(optarg, "aw")) { LF_CLR(S_SCREENS); LF_SET(S_VI_XAW); saved_vi_mode = S_VI_XAW; break; } /* FALLTHROUGH */ case '?': default: usage(LF_ISSET(S_EX)); } argc -= optind; argv += optind; /* Silent is only applicable to ex. */ if (silent && !LF_ISSET(S_EX)) errx(1, "-s only applicable to ex."); /* Build and initialize the GS structure. */ __global_list = gp = gs_init(); /* * If not reading from a terminal, it's like -s was specified. * Vi always reads from the terminal, so fail if it's not a * terminal. */ if (!F_ISSET(gp, G_STDIN_TTY)) { silent = 1; if (!LF_ISSET(S_EX)) { msgq(NULL, M_ERR, "Vi's standard input must be a terminal."); goto err; } } /* * Build and initialize the first/current screen. This is a bit * tricky. If an error is returned, we may or may not have a * screen structure. If we have a screen structure, put it on a * display queue so that the error messages get displayed. */ if (screen_init(NULL, &sp, flags)) { if (sp != NULL) CIRCLEQ_INSERT_HEAD(&__global_list->dq, sp, q); goto err; } sp->saved_vi_mode = saved_vi_mode; CIRCLEQ_INSERT_HEAD(&__global_list->dq, sp, q); if (trace_f != NULL) {#ifdef DEBUG if ((gp->tracefp = fopen(optarg, "w")) == NULL) err(1, "%s", optarg); (void)fprintf(gp->tracefp, "\n===\ntrace: open %s\n", optarg);#else msgq(sp, M_ERR, "-T support not compiled into this version.");#endif } if (set_window_size(sp, 0, 0)) /* Set the window size. */ goto err; if (opts_init(sp)) /* Options initialization. */ goto err; if (readonly) /* Global read-only bit. */ O_SET(sp, O_READONLY); if (silent) { /* Ex batch mode. */ O_CLR(sp, O_AUTOPRINT); O_CLR(sp, O_PROMPT); O_CLR(sp, O_VERBOSE); O_CLR(sp, O_WARN); F_SET(sp, S_EXSILENT); } if (wsizearg != NULL) { ARGS *av[2], a, b; errno = 0; if (strtol(optarg, &p, 10) < 0 || errno || *p) errx(1, "illegal window size -- %s", optarg); (void)snprintf(path, sizeof(path), "window=%s", optarg); a.bp = (CHAR_T *)path; a.len = strlen(path); b.bp = NULL; b.len = 0; av[0] = &a; av[1] = &b; if (opts_set(sp, av)) msgq(sp, M_ERR, "Unable to set command line window size option."); } /* Keymaps, special keys, must follow option initializations. */ if (term_init(sp)) goto err;#ifdef DIGRAPHS if (digraph_init(sp)) /* Digraph initialization. */ goto err;#endif /* * Source the system, environment, $HOME and local .exrc values. * Vi historically didn't check $HOME/.exrc if the environment * variable EXINIT was set. This is all done before the file is * read in, because things in the .exrc information can set, for * example, the recovery directory. * * !!! * While nvi can handle any of the options settings of historic vi, * the converse is not true. Since users are going to have to have * files and environmental variables that work with both, we use nvi * versions of both the $HOME and local startup files if they exist, * otherwise the historic ones. * * !!! * For a discussion of permissions and when what .exrc files are * read, see the the comment above the exrc_isok() function below. * * !!! * If the user started the historic of vi in $HOME, vi read the user's * .exrc file twice, as $HOME/.exrc and as ./.exrc. We avoid this, as * it's going to make some commands behave oddly, and I can't imagine * anyone depending on it. */ if (!silent) { switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1)) { case NOEXIST: case NOPERM: break; case OK: (void)ex_cfile(sp, NULL, _PATH_SYSEXRC); break; } if ((p = getenv("NEXINIT")) != NULL || (p = getenv("EXINIT")) != NULL) if ((p = strdup(p)) == NULL) { msgq(sp, M_SYSERR, NULL); goto err; } else { F_SET(sp, S_VLITONLY); (void)ex_icmd(sp, NULL, p, strlen(p)); F_CLR(sp, S_VLITONLY); free(p); } else if ((p = getenv("HOME")) != NULL && *p) { (void)snprintf(path, sizeof(path), "%s/%s", p, _PATH_NEXRC); switch (exrc_isok(sp, &hsb, path, 0)) { case NOEXIST: (void)snprintf(path, sizeof(path), "%s/%s", p, _PATH_EXRC); if (exrc_isok(sp, &hsb, path, 0) == OK) (void)ex_cfile(sp, NULL, path); break; case NOPERM: break; case OK: (void)ex_cfile(sp, NULL, path); break; } } if (O_ISSET(sp, O_EXRC)) switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0)) { case NOEXIST: if (exrc_isok(sp, &lsb, _PATH_EXRC, 0) == OK && (lsb.st_dev != hsb.st_dev || lsb.st_ino != hsb.st_ino)) (void)ex_cfile(sp, NULL, _PATH_EXRC); break; case NOPERM: break; case OK: if (lsb.st_dev != hsb.st_dev || lsb.st_ino != hsb.st_ino) (void)ex_cfile(sp, NULL, _PATH_NEXRC); break; } } /* List recovery files if -l specified. */ if (flagchk == 'l') exit(rcv_list(sp)); /* Set the file snapshot flag. */ if (snapshot) F_SET(gp, G_SNAPSHOT); /* Use a tag file or recovery file if specified. */ if (tag_f != NULL && ex_tagfirst(sp, tag_f)) goto err; else if (rec_f != NULL && rcv_read(sp, rec_f)) goto err; /* Append any remaining arguments as file names. */ if (*argv != NULL) for (; *argv != NULL; ++argv) if (file_add(sp, NULL, *argv, 0) == NULL) goto err; /* * If no recovery or tag file, get an EXF structure. * If no argv file, use a temporary file. */ if (tag_f == NULL && rec_f == NULL) { if ((frp = file_first(sp)) == NULL && (frp = file_add(sp, NULL, NULL, 1)) == NULL) goto err; if (file_init(sp, frp, NULL, 0))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -