Beispiel #1
0
/*
 * v_quit --
 *	Quit command.
 */
static int
v_quit(SCR *sp, VICMD *vp)
{
	EXCMD cmd;

	ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
	return (v_exec_ex(sp, vp, &cmd));
}
Beispiel #2
0
/*
 * v_edit --
 *	Edit command.
 */
static int
v_edit(SCR *sp, VICMD *vp)
{
	EXCMD cmd;

	ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
	argv_exp0(sp, &cmd, vp->ev.e_csp, vp->ev.e_len);
	return (v_exec_ex(sp, vp, &cmd));
}
Beispiel #3
0
/*
 * api_edit
 *	Create a new screen and return its id 
 *	or edit a new file in the current screen.
 *
 * PUBLIC: int api_edit __P((SCR *, char *, SCR **, int));
 */
int
api_edit(SCR *sp, char *file, SCR **spp, int newscreen)
{
	EXCMD cmd;
	size_t wlen;
	const CHAR_T *wp;

	if (file) {
		ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
		CHAR2INT(sp, file, strlen(file) + 1, wp, wlen);
		argv_exp0(sp, &cmd, wp, wlen - 1 /* terminating 0 */);
	} else
		ex_cinit(sp, &cmd, C_EDIT, 0, OOBLNO, OOBLNO, 0);
	if (newscreen)
		cmd.flags |= E_NEWSCREEN;		/* XXX */
	if (cmd.cmd->fn(sp, &cmd))
		return (1);
	*spp = sp->nextdisp;
	return (0);
}
Beispiel #4
0
/*
 * ex_run_file --
 *	Set up a file of ex commands to run.
 */
static int
ex_run_file(SCR *sp, char *name)
{
	EXCMD cmd;
	CHAR_T *wp;
	size_t wlen;

	ex_cinit(sp, &cmd, C_SOURCE, 0, OOBLNO, OOBLNO, 0);
	CHAR2INT(sp, name, strlen(name)+1, wp, wlen);
	argv_exp0(sp, &cmd, wp, wlen - 1);
	return (ex_source(sp, &cmd));
}
Beispiel #5
0
/*
 * v_write --
 *	Write command.
 */
static int
v_write(SCR *sp, VICMD *vp)
{
	EXCMD cmd;

	ex_cinit(sp, &cmd, C_WRITE, 0, OOBLNO, OOBLNO, 0);

	cmd.addr1.lno = 1;
	if (db_last(sp, &cmd.addr2.lno))
		return (1);
	return (v_exec_ex(sp, vp, &cmd));
}
Beispiel #6
0
/*
 * v_tag --
 *	Tag command.
 */
static int
v_tag(SCR *sp, VICMD *vp)
{
	EXCMD cmd;

	if (v_curword(sp))
		return (1);

	ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
	argv_exp0(sp, &cmd, VIP(sp)->keyw, STRLEN(VIP(sp)->keyw));
	return (v_exec_ex(sp, vp, &cmd));
}
Beispiel #7
0
/*
 * api_escreen
 *	End a screen.
 *
 * PUBLIC: int api_escreen __P((SCR *));
 */
int
api_escreen(SCR *sp)
{
	EXCMD cmd;

	/*
	 * XXX
	 * If the interpreter exits anything other than the current
	 * screen, vi isn't going to update everything correctly.
	 */
	ex_cinit(sp, &cmd, C_QUIT, 0, OOBLNO, OOBLNO, 0);
	return (cmd.cmd->fn(sp, &cmd));
}
Beispiel #8
0
/*
 * ex_tag_first --
 *	The tag code can be entered from main, e.g., "vi -t tag".
 *
 * PUBLIC: int ex_tag_first __P((SCR *, CHAR_T *));
 */
int
ex_tag_first(SCR *sp, const CHAR_T *tagarg)
{
	EXCMD cmd;

	/* Build an argument for the ex :tag command. */
	ex_cinit(sp, &cmd, C_TAG, 0, OOBLNO, OOBLNO, 0);
	argv_exp0(sp, &cmd, tagarg, STRLEN(tagarg));

	/*
	 * XXX
	 * Historic vi went ahead and created a temporary file when it failed
	 * to find the tag.  We match historic practice, but don't distinguish
	 * between real error and failure to find the tag.
	 */
	if (ex_tag_push(sp, &cmd))
		return (0);

	/* Display tags in the center of the screen. */
	F_CLR(sp, SC_SCR_TOP);
	F_SET(sp, SC_SCR_CENTER);

	return (0);
}
Beispiel #9
0
Datei: exf.c Projekt: fishman/nvi
/*
 * file_backup --
 *	Backup the about-to-be-written file.
 *
 * XXX
 * We do the backup by copying the entire file.  It would be nice to do
 * a rename instead, but: (1) both files may not fit and we want to fail
 * before doing the rename; (2) the backup file may not be on the same
 * disk partition as the file being written; (3) there may be optional
 * file information (MACs, DACs, whatever) that we won't get right if we
 * recreate the file.  So, let's not risk it.
 */
static int
file_backup(SCR *sp, char *name, char *bname)
{
    struct dirent *dp;
    struct stat sb;
    DIR *dirp;
    EXCMD cmd;
    off_t off;
    size_t blen;
    int flags, maxnum, nr, num, nw, rfd, wfd, version;
    char *bp, *estr, *p, *pct, *slash, *t, *wfname, buf[8192];
    CHAR_T *wp;
    size_t wlen;
    size_t nlen;
    char *d = NULL;

    rfd = wfd = -1;
    bp = estr = wfname = NULL;

    /*
     * Open the current file for reading.  Do this first, so that
     * we don't exec a shell before the most likely failure point.
     * If it doesn't exist, it's okay, there's just nothing to back
     * up.
     */
    errno = 0;
    if ((rfd = open(name, O_RDONLY, 0)) < 0) {
        if (errno == ENOENT)
            return (0);
        estr = name;
        goto err;
    }

    /*
     * If the name starts with an 'N' character, add a version number
     * to the name.  Strip the leading N from the string passed to the
     * expansion routines, for no particular reason.  It would be nice
     * to permit users to put the version number anywhere in the backup
     * name, but there isn't a special character that we can use in the
     * name, and giving a new character a special meaning leads to ugly
     * hacks both here and in the supporting ex routines.
     *
     * Shell and file name expand the option's value.
     */
    ex_cinit(sp, &cmd, 0, 0, 0, 0, 0);
    if (bname[0] == 'N') {
        version = 1;
        ++bname;
    } else
        version = 0;
    CHAR2INT(sp, bname, strlen(bname) + 1, wp, wlen);
    if (argv_exp2(sp, &cmd, wp, wlen - 1))
        return (1);

    /*
     *  0 args: impossible.
     *  1 args: use it.
     * >1 args: object, too many args.
     */
    if (cmd.argc != 1) {
        msgq_str(sp, M_ERR, bname,
                 "258|%s expanded into too many file names");
        (void)close(rfd);
        return (1);
    }

    /*
     * If appending a version number, read through the directory, looking
     * for file names that match the name followed by a number.  Make all
     * of the other % characters in name literal, so the user doesn't get
     * surprised and sscanf doesn't drop core indirecting through pointers
     * that don't exist.  If any such files are found, increment its number
     * by one.
     */
    if (version) {
        GET_SPACE_GOTOC(sp, bp, blen, cmd.argv[0]->len * 2 + 50);
        INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
                p, nlen);
        d = strdup(p);
        p = d;
        for (t = bp, slash = NULL;
                p[0] != '\0'; *t++ = *p++)
            if (p[0] == '%') {
                if (p[1] != '%')
                    *t++ = '%';
            } else if (p[0] == '/')
                slash = t;
        pct = t;
        *t++ = '%';
        *t++ = 'd';
        *t = '\0';

        if (slash == NULL) {
            dirp = opendir(".");
            p = bp;
        } else {
            *slash = '\0';
            dirp = opendir(bp);
            *slash = '/';
            p = slash + 1;
        }
        if (dirp == NULL) {
            INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
                    estr, nlen);
            goto err;
        }

        for (maxnum = 0; (dp = readdir(dirp)) != NULL;)
            if (sscanf(dp->d_name, p, &num) == 1 && num > maxnum)
                maxnum = num;
        (void)closedir(dirp);

        /* Format the backup file name. */
        (void)snprintf(pct, blen - (pct - bp), "%d", maxnum + 1);
        wfname = bp;
    } else {
        bp = NULL;
        INT2SYS(sp, cmd.argv[0]->bp, cmd.argv[0]->len + 1,
                wfname, nlen);
    }

    /* Open the backup file, avoiding lurkers. */
    if (stat(wfname, &sb) == 0) {
        if (!S_ISREG(sb.st_mode)) {
            msgq_str(sp, M_ERR, bname,
                     "259|%s: not a regular file");
            goto err;
        }
        if (sb.st_uid != getuid()) {
            msgq_str(sp, M_ERR, bname, "260|%s: not owned by you");
            goto err;
        }
        if (sb.st_mode & (S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH)) {
            msgq_str(sp, M_ERR, bname,
                     "261|%s: accessible by a user other than the owner");
            goto err;
        }
        flags = O_TRUNC;
    } else
        flags = O_CREAT | O_EXCL;
    if ((wfd = open(wfname, flags | O_WRONLY, S_IRUSR | S_IWUSR)) < 0) {
        estr = bname;
        goto err;
    }

    /* Copy the file's current contents to its backup value. */
    while ((nr = read(rfd, buf, sizeof(buf))) > 0)
        for (off = 0; nr != 0; nr -= nw, off += nw)
            if ((nw = write(wfd, buf + off, nr)) < 0) {
                estr = wfname;
                goto err;
            }
    if (nr < 0) {
        estr = name;
        goto err;
    }

    if (close(rfd)) {
        estr = name;
        goto err;
    }
    if (close(wfd)) {
        estr = wfname;
        goto err;
    }
    if (bp != NULL)
        FREE_SPACE(sp, bp, blen);
    return (0);

alloc_err:
err:
    if (rfd != -1)
        (void)close(rfd);
    if (wfd != -1) {
        (void)unlink(wfname);
        (void)close(wfd);
    }
    if (estr)
        msgq_str(sp, M_SYSERR, estr, "%s");
    if (d != NULL)
        free(d);
    if (bp != NULL)
        FREE_SPACE(sp, bp, blen);
    return (1);
}