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

📄 csh.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/*- * Copyright (c) 1980, 1991, 1993 *	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) 1980, 1991, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)csh.c	8.2 (Berkeley) 10/12/93";#endif /* not lint */#include <sys/types.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <fcntl.h>#include <errno.h>#include <pwd.h>#include <stdlib.h>#include <string.h>#include <locale.h>#include <unistd.h>#include <vis.h>#if __STDC__# include <stdarg.h>#else# include <varargs.h>#endif#include "csh.h"#include "proc.h"#include "extern.h"#include "pathnames.h"extern bool MapsAreInited;extern bool NLSMapsAreInited;/* * C Shell * * Bill Joy, UC Berkeley, California, USA * October 1978, May 1980 * * Jim Kulp, IIASA, Laxenburg, Austria * April 1980 * * Christos Zoulas, Cornell University * June, 1991 */Char   *dumphist[] = {STRhistory, STRmh, 0, 0};Char   *loadhist[] = {STRsource, STRmh, STRtildothist, 0};int     nofile = 0;bool    reenter = 0;bool    nverbose = 0;bool    nexececho = 0;bool    quitit = 0;bool    fast = 0;bool    batch = 0;bool    mflag = 0;bool    prompt = 1;bool    enterhist = 0;bool    tellwhat = 0;extern char **environ;static int	readf __P((void *, char *, int));static fpos_t	seekf __P((void *, fpos_t, int));static int	writef __P((void *, const char *, int));static int	closef __P((void *));static int	srccat __P((Char *, Char *));static int	srcfile __P((char *, bool, bool));static void	phup __P((int));static void	srcunit __P((int, bool, bool));static void	mailchk __P((void));static Char   **defaultpath __P((void));intmain(argc, argv)    int     argc;    char  **argv;{    register Char *cp;    register char *tcp;    register int f;    register char **tempv;    struct sigvec osv;    cshin = stdin;    cshout = stdout;    csherr = stderr;    settimes();			/* Immed. estab. timing base */    /*     * Initialize non constant strings     */#ifdef _PATH_BSHELL    STR_BSHELL = SAVE(_PATH_BSHELL);#endif#ifdef _PATH_CSHELL    STR_SHELLPATH = SAVE(_PATH_CSHELL);#endif    STR_environ = blk2short(environ);    environ = short2blk(STR_environ);	/* So that we can free it */    STR_WORD_CHARS = SAVE(WORD_CHARS);    HIST = '!';    HISTSUB = '^';    word_chars = STR_WORD_CHARS;    tempv = argv;    if (eq(str2short(tempv[0]), STRaout))	/* A.out's are quittable */	quitit = 1;    uid = getuid();    gid = getgid();    euid = geteuid();    egid = getegid();    /*     * We are a login shell if: 1. we were invoked as -<something> and we had     * no arguments 2. or we were invoked only with the -l flag     */    loginsh = (**tempv == '-' && argc == 1) ||	(argc == 2 && tempv[1][0] == '-' && tempv[1][1] == 'l' &&	 tempv[1][2] == '\0');    if (loginsh && **tempv != '-') {	/*	 * Mangle the argv space	 */	tempv[1][0] = '\0';	tempv[1][1] = '\0';	tempv[1] = NULL;	for (tcp = *tempv; *tcp++;)	    continue;	for (tcp--; tcp >= *tempv; tcp--)	    tcp[1] = tcp[0];	*++tcp = '-';	argc--;    }    if (loginsh)	(void) time(&chktim);    AsciiOnly = 1;#ifdef NLS    (void) setlocale(LC_ALL, "");    {	int     k;	for (k = 0200; k <= 0377 && !Isprint(k); k++)	    continue;	AsciiOnly = k > 0377;    }#else    AsciiOnly = getenv("LANG") == NULL && getenv("LC_CTYPE") == NULL;#endif				/* NLS */    /*     * Move the descriptors to safe places. The variable didfds is 0 while we     * have only FSH* to work with. When didfds is true, we have 0,1,2 and     * prefer to use these.     */    initdesc();    /*     * XXX: This is to keep programs that use stdio happy.     *	    what we really want is freunopen() ....     *	    Closing cshin cshout and csherr (which are really stdin stdout     *	    and stderr at this point and then reopening them in the same order     *	    gives us again stdin == cshin stdout == cshout and stderr == csherr.     *	    If that was not the case builtins like printf that use stdio     *	    would break. But in any case we could fix that with memcpy and     *	    a bit of pointer manipulation...     *	    Fortunately this is not needed under the current implementation     *	    of stdio.     */    (void) fclose(cshin);    (void) fclose(cshout);    (void) fclose(csherr);    if (!(cshin  = funopen((void *) &SHIN,  readf, writef, seekf, closef)))	exit(1);    if (!(cshout = funopen((void *) &SHOUT, readf, writef, seekf, closef)))	exit(1);    if (!(csherr = funopen((void *) &SHERR, readf, writef, seekf, closef)))	exit(1);    (void) setvbuf(cshin,  NULL, _IOLBF, 0);    (void) setvbuf(cshout, NULL, _IOLBF, 0);    (void) setvbuf(csherr, NULL, _IOLBF, 0);    /*     * Initialize the shell variables. ARGV and PROMPT are initialized later.     * STATUS is also munged in several places. CHILD is munged when     * forking/waiting     */    set(STRstatus, Strsave(STR0));    if ((tcp = getenv("HOME")) != NULL)	cp = SAVE(tcp);    else	cp = NULL;    if (cp == NULL)	fast = 1;		/* No home -> can't read scripts */    else	set(STRhome, cp);    dinit(cp);			/* dinit thinks that HOME == cwd in a login				 * shell */    /*     * Grab other useful things from the environment. Should we grab     * everything??     */    if ((tcp = getenv("LOGNAME")) != NULL ||	(tcp = getenv("USER")) != NULL)	set(STRuser, SAVE(tcp));    if ((tcp = getenv("TERM")) != NULL)	set(STRterm, SAVE(tcp));    /*     * Re-initialize path if set in environment     */    if ((tcp = getenv("PATH")) == NULL)	set1(STRpath, defaultpath(), &shvhed);    else	importpath(SAVE(tcp));    set(STRshell, Strsave(STR_SHELLPATH));    doldol = putn((int) getpid());	/* For $$ */    shtemp = Strspl(STRtmpsh, doldol);	/* For << */    /*     * Record the interrupt states from the parent process. If the parent is     * non-interruptible our hand must be forced or we (and our children) won't     * be either. Our children inherit termination from our parent. We catch it     * only if we are the login shell.     */    /* parents interruptibility */    (void) sigvec(SIGINT, NULL, &osv);    parintr = (void (*) ()) osv.sv_handler;    (void) sigvec(SIGTERM, NULL, &osv);    parterm = (void (*) ()) osv.sv_handler;    if (loginsh) {	(void) signal(SIGHUP, phup);	/* exit processing on HUP */	(void) signal(SIGXCPU, phup);	/* ...and on XCPU */	(void) signal(SIGXFSZ, phup);	/* ...and on XFSZ */    }    /*     * Process the arguments.     *     * Note that processing of -v/-x is actually delayed till after script     * processing.     *     * We set the first character of our name to be '-' if we are a shell     * running interruptible commands.  Many programs which examine ps'es     * use this to filter such shells out.     */    argc--, tempv++;    while (argc > 0 && (tcp = tempv[0])[0] == '-' && *++tcp != '\0' && !batch) {	do	    switch (*tcp++) {	    case 0:		/* -	Interruptible, no prompt */		prompt = 0;		setintr = 1;		nofile = 1;		break;	    case 'b':		/* -b	Next arg is input file */		batch = 1;		break;	    case 'c':		/* -c	Command input from arg */		if (argc == 1)		    xexit(0);		argc--, tempv++;		arginp = SAVE(tempv[0]);		prompt = 0;		nofile = 1;		break;	    case 'e':		/* -e	Exit on any error */		exiterr = 1;		break;	    case 'f':		/* -f	Fast start */		fast = 1;		break;	    case 'i':		/* -i	Interactive, even if !intty */		intact = 1;		nofile = 1;		break;	    case 'm':		/* -m	read .cshrc (from su) */		mflag = 1;		break;	    case 'n':		/* -n	Don't execute */		noexec = 1;		break;	    case 'q':		/* -q	(Undoc'd) ... die on quit */		quitit = 1;		break;	    case 's':		/* -s	Read from std input */		nofile = 1;		break;	    case 't':		/* -t	Read one line from input */		onelflg = 2;		prompt = 0;		nofile = 1;		break;	    case 'v':		/* -v	Echo hist expanded input */		nverbose = 1;	/* ... later */		break;	    case 'x':		/* -x	Echo just before execution */		nexececho = 1;	/* ... later */		break;	    case 'V':		/* -V	Echo hist expanded input */		setNS(STRverbose);	/* NOW! */		break;	    case 'X':		/* -X	Echo just before execution */		setNS(STRecho);	/* NOW! */		break;	} while (*tcp);	tempv++, argc--;    }    if (quitit)			/* With all due haste, for debugging */	(void) signal(SIGQUIT, SIG_DFL);    /*     * Unless prevented by -, -c, -i, -s, or -t, if there are remaining     * arguments the first of them is the name of a shell file from which to     * read commands.     */    if (nofile == 0 && argc > 0) {	nofile = open(tempv[0], O_RDONLY);	if (nofile < 0) {	    child = 1;		/* So this doesn't return */	    stderror(ERR_SYSTEM, tempv[0], strerror(errno));	}	ffile = SAVE(tempv[0]);	/*	 * Replace FSHIN. Handle /dev/std{in,out,err} specially	 * since once they are closed we cannot open them again.	 * In that case we use our own saved descriptors	 */	if ((SHIN = dmove(nofile, FSHIN)) < 0)	    switch(nofile) {	    case 0:		SHIN = FSHIN;		break;	    case 1:		SHIN = FSHOUT;		break;	    case 2:		SHIN = FSHERR;		break;	    default:		stderror(ERR_SYSTEM, tempv[0], strerror(errno));		break;	    }	(void) ioctl(SHIN, FIOCLEX, NULL);	prompt = 0;	 /* argc not used any more */ tempv++;    }    intty = isatty(SHIN);    intty |= intact;    if (intty || (intact && isatty(SHOUT))) {	if (!batch && (uid != euid || gid != egid)) {	    errno = EACCES;	    child = 1;		/* So this doesn't return */	    stderror(ERR_SYSTEM, "csh", strerror(errno));	}    }    /*     * Decide whether we should play with signals or not. If we are explicitly     * told (via -i, or -) or we are a login shell (arg0 starts with -) or the     * input and output are both the ttys("csh", or "csh</dev/ttyx>/dev/ttyx")     * Note that in only the login shell is it likely that parent may have set     * signals to be ignored     */    if (loginsh || intact || (intty && isatty(SHOUT)))	setintr = 1;    settell();    /*     * Save the remaining arguments in argv.     */    setq(STRargv, blk2short(tempv), &shvhed);    /*     * Set up the prompt.     */    if (prompt) {	set(STRprompt, Strsave(uid == 0 ? STRsymhash : STRsymcent));	/* that's a meta-questionmark */	set(STRprompt2, Strsave(STRmquestion));    }    /*     * If we are an interactive shell, then start fiddling with the signals;     * this is a tricky game.     */    shpgrp = getpgrp();    opgrp = tpgrp = -1;    if (setintr) {	**argv = '-';	if (!quitit)		/* Wary! */	    (void) signal(SIGQUIT, SIG_IGN);

⌨️ 快捷键说明

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