Exemplo n.º 1
0
/*
 * ex_source -- :source file
 *	Execute ex commands from a file.
 *
 * PUBLIC: int ex_source __P((SCR *, EXCMD *));
 */
int
ex_source(SCR *sp, EXCMD *cmdp)
{
	struct stat sb;
	int fd, len;
	char *bp;
	const char *name;
	size_t nlen;
	const CHAR_T *wp;
	CHAR_T *dp;
	size_t wlen;

	INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen);
	if ((fd = open(name, O_RDONLY, 0)) < 0 || fstat(fd, &sb))
		goto err;

	/*
	 * XXX
	 * I'd like to test to see if the file is too large to malloc.  Since
	 * we don't know what size or type off_t's or size_t's are, what the
	 * largest unsigned integral type is, or what random insanity the local
	 * C compiler will perpetrate, doing the comparison in a portable way
	 * is flatly impossible.  So, put an fairly unreasonable limit on it,
	 * I don't want to be dropping core here.
	 */
#define	MEGABYTE	1048576
	if (sb.st_size > MEGABYTE) {
		errno = ENOMEM;
		goto err;
	}

	MALLOC(sp, bp, char *, (size_t)sb.st_size + 1);
	if (bp == NULL) {
		(void)close(fd);
		return (1);
	}
	bp[sb.st_size] = '\0';

	/* Read the file into memory. */
	len = read(fd, bp, (int)sb.st_size);
	(void)close(fd);
	if (len == -1 || len != sb.st_size) {
		if (len != sb.st_size)
			errno = EIO;
		free(bp);
err:		msgq_str(sp, M_SYSERR, name, "%s");
		return (1);
	}

	if (CHAR2INT(sp, bp, (size_t)sb.st_size + 1, wp, wlen))
		msgq(sp, M_ERR, "323|Invalid input. Truncated.");
	dp = v_wstrdup(sp, wp, wlen - 1);
	free(bp);
	/* Put it on the ex queue. */
	INT2CHAR(sp, cmdp->argv[0]->bp, cmdp->argv[0]->len + 1, name, nlen);
	return (ex_run_str(sp, name, dp, wlen - 1, 1, 1));
}
Exemplo n.º 2
0
/*
 * ex_exrc --
 *	Read the EXINIT environment variable and the startup exrc files,
 *	and execute their commands.
 *
 * PUBLIC: int ex_exrc(SCR *);
 */
int
ex_exrc(SCR *sp)
{
	struct stat hsb, lsb;
	char *p, *path;
	CHAR_T *wp;
	size_t wlen;

	/*
	 * 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 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.
	 */
	switch (exrc_isok(sp, &hsb, _PATH_SYSEXRC, 1, 0)) {
	case NOEXIST:
	case NOPERM:
		break;
	case RCOK:
		if (ex_run_file(sp, _PATH_SYSEXRC))
			return (1);
		break;
	}

	/* Run the commands. */
	if (EXCMD_RUNNING(sp->gp))
		(void)ex_cmd(sp);
	if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
		return (0);

	if ((p = getenv("NEXINIT")) != NULL) {
		CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
		if (ex_run_str(sp, "NEXINIT", wp, wlen - 1, 1, 0))
			return (1);
	} else if ((p = getenv("EXINIT")) != NULL) {
		CHAR2INT(sp, p, strlen(p) + 1, wp, wlen);
		if (ex_run_str(sp, "EXINIT", wp, wlen - 1, 1, 0))
			return (1);
	} else if ((p = getenv("HOME")) != NULL && *p) {
		int st = 0;

		if ((path = join(p, _PATH_NEXRC)) == NULL) {
			msgq(sp, M_SYSERR, NULL);
			return (1);
		}
		switch (exrc_isok(sp, &hsb, path, 0, 1)) {
		case NOEXIST:
			free(path);
			if ((path = join(p, _PATH_EXRC)) == NULL) {
				msgq(sp, M_SYSERR, NULL);
				return (1);
			}
			if (exrc_isok(sp,
			    &hsb, path, 0, 1) == RCOK && ex_run_file(sp, path))
				st = 1;
			break;
		case NOPERM:
			break;
		case RCOK:
			if (ex_run_file(sp, path))
				st = 1;
			break;
		}
		free(path);
		if (st)
			return st;
	}

	/* Run the commands. */
	if (EXCMD_RUNNING(sp->gp))
		(void)ex_cmd(sp);
	if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
		return (0);

	/* Previous commands may have set the exrc option. */
	if (O_ISSET(sp, O_EXRC)) {
		switch (exrc_isok(sp, &lsb, _PATH_NEXRC, 0, 0)) {
		case NOEXIST:
			if (exrc_isok(sp, &lsb, _PATH_EXRC, 0, 0) == RCOK &&
			    (lsb.st_dev != hsb.st_dev ||
			    lsb.st_ino != hsb.st_ino) &&
			    ex_run_file(sp, _PATH_EXRC))
				return (1);
			break;
		case NOPERM:
			break;
		case RCOK:
			if ((lsb.st_dev != hsb.st_dev ||
			    lsb.st_ino != hsb.st_ino) &&
			    ex_run_file(sp, _PATH_NEXRC))
				return (1);
			break;
		}
		/* Run the commands. */
		if (EXCMD_RUNNING(sp->gp))
			(void)ex_cmd(sp);
		if (F_ISSET(sp, SC_EXIT | SC_EXIT_FORCE))
			return (0);
	}

	return (0);
}
Exemplo n.º 3
0
Arquivo: exf.c Projeto: fishman/nvi
/*
 * file_cinit --
 *	Set up the initial cursor position.
 */
static void
file_cinit(SCR *sp)
{
    GS *gp;
    MARK m;
    size_t len;
    int nb;
    CHAR_T *wp;
    size_t wlen;

    /* Set some basic defaults. */
    sp->lno = 1;
    sp->cno = 0;

    /*
     * Historically, initial commands (the -c option) weren't executed
     * until a file was loaded, e.g. "vi +10 nofile", followed by an
     * :edit or :tag command, would execute the +10 on the file loaded
     * by the subsequent command, (assuming that it existed).  This
     * applied as well to files loaded using the tag commands, and we
     * follow that historic practice.  Also, all initial commands were
     * ex commands and were always executed on the last line of the file.
     *
     * Otherwise, if no initial command for this file:
     *    If in ex mode, move to the last line, first nonblank character.
     *    If the file has previously been edited, move to the last known
     *	  position, and check it for validity.
     *    Otherwise, move to the first line, first nonblank.
     *
     * This gets called by the file init code, because we may be in a
     * file of ex commands and we want to execute them from the right
     * location in the file.
     */
    nb = 0;
    gp = sp->gp;
    if (gp->c_option != NULL && !F_ISSET(sp->frp, FR_NEWFILE)) {
        if (db_last(sp, &sp->lno))
            return;
        if (sp->lno == 0) {
            sp->lno = 1;
            sp->cno = 0;
        }
        CHAR2INT(sp, gp->c_option, strlen(gp->c_option) + 1,
                 wp, wlen);
        if (ex_run_str(sp, "-c option", wp, wlen - 1, 1, 1))
            return;
        gp->c_option = NULL;
    } else if (F_ISSET(sp, SC_EX)) {
        if (db_last(sp, &sp->lno))
            return;
        if (sp->lno == 0) {
            sp->lno = 1;
            sp->cno = 0;
            return;
        }
        nb = 1;
    } else {
        if (F_ISSET(sp->frp, FR_CURSORSET)) {
            sp->lno = sp->frp->lno;
            sp->cno = sp->frp->cno;

            /* If returning to a file in vi, center the line. */
            F_SET(sp, SC_SCR_CENTER);
        } else {
            if (O_ISSET(sp, O_COMMENT))
                file_comment(sp);
            else
                sp->lno = 1;
            nb = 1;
        }
        if (db_get(sp, sp->lno, 0, NULL, &len)) {
            sp->lno = 1;
            sp->cno = 0;
            return;
        }
        if (!nb && sp->cno > len)
            nb = 1;
    }
    if (nb) {
        sp->cno = 0;
        (void)nonblank(sp, sp->lno, &sp->cno);
    }

    /*
     * !!!
     * The initial column is also the most attractive column.
     */
    sp->rcm = sp->cno;

    /*
     * !!!
     * Historically, vi initialized the absolute mark, but ex did not.
     * Which meant, that if the first command in ex mode was "visual",
     * or if an ex command was executed first (e.g. vi +10 file) vi was
     * entered without the mark being initialized.  For consistency, if
     * the file isn't empty, we initialize it for everyone, believing
     * that it can't hurt, and is generally useful.  Not initializing it
     * if the file is empty is historic practice, although it has always
     * been possible to set (and use) marks in empty vi files.
     */
    m.lno = sp->lno;
    m.cno = sp->cno;
    (void)mark_set(sp, ABSMARK1, &m, 0);
}