示例#1
0
/*
 * v_dtoh --
 *	Move all but the current screen to the hidden queue.
 */
static void
v_dtoh(SCR *sp)
{
	GS *gp;
	SCR *tsp;
	WIN *wp;
	int hidden;

	/* Move all screens to the hidden queue, tossing screen maps. */
	for (hidden = 0, gp = sp->gp, wp = sp->wp;
	    (tsp = wp->scrq.cqh_first) != (void *)&wp->scrq; ++hidden) {
		if (_HMAP(tsp) != NULL) {
			free(_HMAP(tsp));
			_HMAP(tsp) = NULL;
		}
		CIRCLEQ_REMOVE(&wp->scrq, tsp, q);
		CIRCLEQ_INSERT_TAIL(&gp->hq, tsp, q);
		/* XXXX Change if hidden screens per window */
		tsp->wp = 0;
		gp->scr_discard(tsp, NULL);
	}

	/* Move current screen back to the display queue. */
	CIRCLEQ_REMOVE(&gp->hq, sp, q);
	CIRCLEQ_INSERT_TAIL(&wp->scrq, sp, q);
	sp->wp = wp;

	if (hidden > 1)
		msgq(sp, M_INFO,
		    "319|%d screens backgrounded; use :display to list them",
		    hidden - 1);
}
示例#2
0
/*
 * Called by main() when ufs is going to be mounted as root.
 */
lfs_mountroot()
{
	extern struct vnode *rootvp;
	struct fs *fs;
	struct mount *mp;
	struct proc *p = curproc;	/* XXX */
	int error;
	
	/*
	 * Get vnodes for swapdev and rootdev.
	 */
	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
	    (error = bdevvp(rootdev, &rootvp))) {
		printf("lfs_mountroot: can't setup bdevvp's");
		return (error);
	}
	if (error = vfs_rootmountalloc("lfs", "root_device", &mp))
		return (error);
	if (error = lfs_mountfs(rootvp, mp, p)) {
		mp->mnt_vfc->vfc_refcount--;
		vfs_unbusy(mp, p);
		free(mp, M_MOUNT);
		return (error);
	}
	simple_lock(&mountlist_slock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	simple_unlock(&mountlist_slock);
	(void)lfs_statfs(mp, &mp->mnt_stat, p);
	vfs_unbusy(mp, p);
	return (0);
}
示例#3
0
int
cd9660_mountroot()
{
	struct mount *mp;
	extern struct vnode *rootvp;
	struct proc *p = curproc;	/* XXX */
	int error;
	struct iso_args args;
	
	/*
	 * Get vnodes for swapdev and rootdev.
	 */
	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
	    (error = bdevvp(rootdev, &rootvp))) {
		printf("cd9660_mountroot: can't setup bdevvp's");
                return (error);
        }

	if ((error = vfs_rootmountalloc("cd9660", "root_device", &mp)) != 0)
		return (error);
	args.flags = ISOFSMNT_ROOT;
	if ((error = iso_mountfs(rootvp, mp, p, &args)) != 0) {
		mp->mnt_vfc->vfc_refcount--;
		vfs_unbusy(mp);
                free(mp, M_MOUNT);
                return (error);
        }

        CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
        (void)cd9660_statfs(mp, &mp->mnt_stat, p);
	vfs_unbusy(mp);
	inittodr(0);

        return (0);
}
示例#4
0
文件: ext2_vfsops.c 项目: kame/kame
static int
ext2_mountroot()
{
#if !defined(__FreeBSD__)
    extern struct vnode *rootvp;
#endif
    register struct ext2_sb_info *fs;
    register struct mount *mp;
#if defined(__FreeBSD__)
    struct proc *p = curproc;
#else
    struct proc *p = get_proc();	/* XXX */
#endif
    struct ufsmount *ump;
    u_int size;
    int error;

    /*
     * Get vnodes for swapdev and rootdev.
     */
    if (bdevvp(swapdev, &swapdev_vp) || bdevvp(rootdev, &rootvp))
        panic("ext2_mountroot: can't setup bdevvp's");

    mp = bsd_malloc((u_long)sizeof(struct mount), M_MOUNT, M_WAITOK);
    bzero((char *)mp, (u_long)sizeof(struct mount));
    mp->mnt_op = &ext2fs_vfsops;
    mp->mnt_flag = MNT_RDONLY;
    if (error = ext2_mountfs(rootvp, mp, p)) {
        bsd_free(mp, M_MOUNT);
        return (error);
    }
    if (error = vfs_lock(mp)) {
        (void)ext2_unmount(mp, 0, p);
        bsd_free(mp, M_MOUNT);
        return (error);
    }
#if defined(__FreeBSD__)
    CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#else
    TAILQ_INSERT_TAIL(&mountlist, mp, mnt_list);
#endif
    mp->mnt_flag |= MNT_ROOTFS;
    mp->mnt_vnodecovered = NULLVP;
    ump = VFSTOUFS(mp);
    fs = ump->um_e2fs;
    bzero(fs->fs_fsmnt, sizeof(fs->fs_fsmnt));
    fs->fs_fsmnt[0] = '/';
    bcopy((caddr_t)fs->fs_fsmnt, (caddr_t)mp->mnt_stat.f_mntonname,
          MNAMELEN);
    (void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
                   &size);
    bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
    (void)ext2_statfs(mp, &mp->mnt_stat, p);
    vfs_unlock(mp);
    inittodr(fs->s_es->s_wtime);		/* this helps to set the time */
    return (0);
}
示例#5
0
int
cd9660_mountroot()
{
	register struct mount *mp;
	extern struct vnode *rootvp;
	struct proc *p = current_proc();	/* XXX */
	struct iso_mnt *imp;
	size_t size;
	int error;
	struct iso_args args;
	
	/*
	 * Get vnodes for swapdev and rootdev.
	 */
	if ( bdevvp(rootdev, &rootvp))
		panic("cd9660_mountroot: can't setup bdevvp's");

	MALLOC_ZONE(mp, struct mount *,
			sizeof(struct mount), M_MOUNT, M_WAITOK);
	bzero((char *)mp, (u_long)sizeof(struct mount));

    /* Initialize the default IO constraints */
    mp->mnt_maxreadcnt = mp->mnt_maxwritecnt = MAXPHYS;
    mp->mnt_segreadcnt = mp->mnt_segwritecnt = 32;

	mp->mnt_op = &cd9660_vfsops;
	mp->mnt_flag = MNT_RDONLY;
	LIST_INIT(&mp->mnt_vnodelist);
	args.flags = ISOFSMNT_ROOT;
	args.ssector = 0;
	args.fspec = 0;
	args.toc_length = 0;
	args.toc = 0;
	if ((error = iso_mountfs(rootvp, mp, p, &args))) {
		vrele(rootvp); /* release the reference from bdevvp() */

		if (mp->mnt_kern_flag & MNTK_IO_XINFO)
		        FREE(mp->mnt_xinfo_ptr, M_TEMP);
		FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
		return (error);
	}
	simple_lock(&mountlist_slock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	simple_unlock(&mountlist_slock);
	mp->mnt_vnodecovered = NULLVP;
	imp = VFSTOISOFS(mp);
	(void) copystr("/", mp->mnt_stat.f_mntonname, MNAMELEN - 1,
		&size);
	bzero(mp->mnt_stat.f_mntonname + size, MNAMELEN - size);
	(void) copystr(ROOTNAME, mp->mnt_stat.f_mntfromname, MNAMELEN - 1,
		&size);
	bzero(mp->mnt_stat.f_mntfromname + size, MNAMELEN - size);
	(void)cd9660_statfs(mp, &mp->mnt_stat, p);
	return (0);
}
示例#6
0
文件: exf.c 项目: fishman/nvi
/*
 * file_add --
 *	Insert a file name into the FREF list, if it doesn't already
 *	appear in it.
 *
 * !!!
 * The "if it doesn't already appear" changes vi's semantics slightly.  If
 * you do a "vi foo bar", and then execute "next bar baz", the edit of bar
 * will reflect the line/column of the previous edit session.  Historic nvi
 * did not do this.  The change is a logical extension of the change where
 * vi now remembers the last location in any file that it has ever edited,
 * not just the previously edited file.
 *
 * PUBLIC: FREF *file_add __P((SCR *, char *));
 */
FREF *
file_add(SCR *sp, char *name)
{
    GS *gp;
    FREF *frp, *tfrp;

    /*
     * Return it if it already exists.  Note that we test against the
     * user's name, whatever that happens to be, including if it's a
     * temporary file.
     *
     * If the user added a file but was unable to initialize it, there
     * can be file list entries where the name field is NULL.  Discard
     * them the next time we see them.
     */
    gp = sp->gp;
    if (name != NULL)
        for (frp = gp->frefq.cqh_first;
                frp != (FREF *)&gp->frefq; frp = frp->q.cqe_next) {
            if (frp->name == NULL) {
                tfrp = frp->q.cqe_next;
                CIRCLEQ_REMOVE(&gp->frefq, frp, q);
                if (frp->name != NULL)
                    free(frp->name);
                free(frp);
                frp = tfrp;
                continue;
            }
            if (!strcmp(frp->name, name))
                return (frp);
        }

    /* Allocate and initialize the FREF structure. */
    CALLOC(sp, frp, FREF *, 1, sizeof(FREF));
    if (frp == NULL)
        return (NULL);

    /*
     * If no file name specified, or if the file name is a request
     * for something temporary, file_init() will allocate the file
     * name.  Temporary files are always ignored.
     */
    if (name != NULL && strcmp(name, TEMPORARY_FILE_STRING) &&
            (frp->name = strdup(name)) == NULL) {
        free(frp);
        msgq(sp, M_SYSERR, NULL);
        return (NULL);
    }

    /* Append into the chain of file names. */
    CIRCLEQ_INSERT_TAIL(&gp->frefq, frp, q);

    return (frp);
}
示例#7
0
文件: rec_sched.c 项目: wisicn/rr
/**
 * Registers a new thread to the runtime system. This includes
 * initialization of the hardware performance counters
 */
void rec_sched_register_thread(pid_t parent, pid_t child, int flags)
{
	struct tasklist_entry* entry = sys_malloc_zero(sizeof(*entry));
	struct task* t = &entry->t;

	assert(child > 0 && child < MAX_TID);

	t->status = 0;
	t->rec_tid = t->tid = child;
	t->child_mem_fd = sys_open_child_mem(child);
	push_placeholder_event(t);
	if (parent) {
		struct task* parent_t = get_task(parent);
		struct sighandlers* parent_handlers = parent_t->sighandlers;

		t->syscallbuf_lib_start = parent_t->syscallbuf_lib_start;
		t->syscallbuf_lib_end = parent_t->syscallbuf_lib_end;
		t->task_group =
			(SHARE_TASK_GROUP & flags) ?
			task_group_add_and_ref(parent_t->task_group, t) :
			task_group_new_and_add(t);
		t->sighandlers = (SHARE_SIGHANDLERS & flags) ?
				 sighandlers_ref(parent_handlers) :
				 sighandlers_copy(parent_handlers);
	} else {
		/* After the first task is forked, we always need to
		 * know the parent in order to initialize some task
		 * state. */
		static int is_first_task = 1;
		assert(is_first_task);
		is_first_task = 0;
		t->task_group = task_group_new_and_add(t);
		/* The very first task we fork inherits our
		 * sighandlers (which should all be default at this
		 * point, but ...).  From there on, new tasks will
		 * transitively inherit from this first task.  */
		t->sighandlers = sighandlers_new();
		sighandlers_init_from_current_process(t->sighandlers);
	}
	/* These will be initialized when the syscall buffer is. */
	t->desched_fd = t->desched_fd_child = -1;

	sys_ptrace_setup(child);

	init_hpc(t);
	start_hpc(t, rr_flags()->max_rbc);

	CIRCLEQ_INSERT_TAIL(&head, entry, entries);
	num_active_threads++;

	tid_to_entry[child] = entry;
}
示例#8
0
/*
 * Called by main() when ufs is going to be mounted as root.
 */
ffs_mountroot()
{
	extern struct vnode *rootvp;
	struct fs *fs;
	struct mount *mp;
	struct proc *p = current_proc();	/* XXX */
	struct ufsmount *ump;
	u_int size;
	int error;
	
	/*
	 * Get vnode for rootdev.
	 */
	if (error = bdevvp(rootdev, &rootvp)) {
		printf("ffs_mountroot: can't setup bdevvp");
		return (error);
	}
	if (error = vfs_rootmountalloc("ufs", "root_device", &mp)) {
		vrele(rootvp); /* release the reference from bdevvp() */
		return (error);
	}

	/* Must set the MNT_ROOTFS flag before doing the actual mount */
	mp->mnt_flag |= MNT_ROOTFS;

	/* Set asynchronous flag by default */
	mp->mnt_flag |= MNT_ASYNC;

	if (error = ffs_mountfs(rootvp, mp, p)) {
		mp->mnt_vfc->vfc_refcount--;

		if (mp->mnt_kern_flag & MNTK_IO_XINFO)
		        FREE(mp->mnt_xinfo_ptr, M_TEMP);
		vfs_unbusy(mp, p);

		vrele(rootvp); /* release the reference from bdevvp() */
		FREE_ZONE(mp, sizeof (struct mount), M_MOUNT);
		return (error);
	}
	simple_lock(&mountlist_slock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	simple_unlock(&mountlist_slock);
	ump = VFSTOUFS(mp);
	fs = ump->um_fs;
	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
	(void)ffs_statfs(mp, &mp->mnt_stat, p);
	vfs_unbusy(mp, p);
	inittodr(fs->fs_time);
	return (0);
}
示例#9
0
int
ffs_mountroot(void)
{
	struct fs *fs;
	struct mount *mp;
	struct proc *p = curproc;	/* XXX */
	struct ufsmount *ump;
	int error;

	/*
	 * Get vnodes for swapdev and rootdev.
	 */
	swapdev_vp = NULL;
	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
	    (error = bdevvp(rootdev, &rootvp))) {
		printf("ffs_mountroot: can't setup bdevvp's\n");
		if (swapdev_vp)
			vrele(swapdev_vp);
		return (error);
	}

	if ((error = vfs_rootmountalloc("ffs", "root_device", &mp)) != 0) {
		vrele(swapdev_vp);
		vrele(rootvp);
		return (error);
	}

	if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
		mp->mnt_vfc->vfc_refcount--;
		vfs_unbusy(mp);
		free(mp, M_MOUNT);
		vrele(swapdev_vp);
		vrele(rootvp);
		return (error);
	}

	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	ump = VFSTOUFS(mp);
	fs = ump->um_fs;
	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
	(void)ffs_statfs(mp, &mp->mnt_stat, p);
	vfs_unbusy(mp);
	inittodr(fs->fs_time);

	return (0);
}
示例#10
0
int
mfs_mountroot(void)
{
	struct fs *fs;
	struct mount *mp;
	struct lwp *l = curlwp;		/* XXX */
	struct ufsmount *ump;
	struct mfsnode *mfsp;
	int error = 0;

	if ((error = vfs_rootmountalloc(MOUNT_MFS, "mfs_root", &mp))) {
		vrele(rootvp);
		return (error);
	}

	mfsp = kmem_alloc(sizeof(*mfsp), KM_SLEEP);
	rootvp->v_data = mfsp;
	rootvp->v_op = mfs_vnodeop_p;
	rootvp->v_tag = VT_MFS;
	mfsp->mfs_baseoff = mfs_rootbase;
	mfsp->mfs_size = mfs_rootsize;
	mfsp->mfs_vnode = rootvp;
	mfsp->mfs_proc = NULL;		/* indicate kernel space */
	mfsp->mfs_shutdown = 0;
	cv_init(&mfsp->mfs_cv, "mfs");
	mfsp->mfs_refcnt = 1;
	bufq_alloc(&mfsp->mfs_buflist, "fcfs", 0);
	if ((error = ffs_mountfs(rootvp, mp, l)) != 0) {
		vfs_unbusy(mp, false, NULL);
		bufq_free(mfsp->mfs_buflist);
		vfs_destroy(mp);
		kmem_free(mfsp, sizeof(*mfsp));
		return (error);
	}
	mutex_enter(&mountlist_lock);
	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	mutex_exit(&mountlist_lock);
	mp->mnt_vnodecovered = NULLVP;
	ump = VFSTOUFS(mp);
	fs = ump->um_fs;
	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
	(void)ffs_statvfs(mp, &mp->mnt_stat);
	vfs_unbusy(mp, false, NULL);
	return (0);
}
示例#11
0
int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void))
{
    struct atfork_t *entry = malloc(sizeof(struct atfork_t));

    if (entry == NULL) {
        return ENOMEM;
    }

    entry->prepare = prepare;
    entry->parent = parent;
    entry->child = child;

    pthread_mutex_lock(&handler_mutex);
    CIRCLEQ_INSERT_TAIL(&atfork_head, entry, entries);
    pthread_mutex_unlock(&handler_mutex);

    return 0;
}
示例#12
0
int
mfs_mountroot(void)
{
	struct fs *fs;
	struct mount *mp;
	struct proc *p = curproc;
	struct ufsmount *ump;
	struct mfsnode *mfsp;
	int error;

	if ((error = bdevvp(swapdev, &swapdev_vp)) ||
	    (error = bdevvp(rootdev, &rootvp))) {
		printf("mfs_mountroot: can't setup bdevvp's");
		return (error);
	}
	if ((error = vfs_rootmountalloc("mfs", "mfs_root", &mp)) != 0)
		return (error);
	mfsp = malloc(sizeof *mfsp, M_MFSNODE, M_WAITOK);
	rootvp->v_data = mfsp;
	rootvp->v_op = mfs_vnodeop_p;
	rootvp->v_tag = VT_MFS;
	mfsp->mfs_baseoff = mfs_rootbase;
	mfsp->mfs_size = mfs_rootsize;
	mfsp->mfs_vnode = rootvp;
	mfsp->mfs_pid = p->p_pid;
	mfsp->mfs_buflist = (struct buf *)0;
	if ((error = ffs_mountfs(rootvp, mp, p)) != 0) {
		mp->mnt_vfc->vfc_refcount--;
		vfs_unbusy(mp);
		free(mp, M_MOUNT);
		free(mfsp, M_MFSNODE);
		return (error);
	}

	CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
	ump = VFSTOUFS(mp);
	fs = ump->um_fs;
	(void) copystr(mp->mnt_stat.f_mntonname, fs->fs_fsmnt, MNAMELEN - 1, 0);
	(void)ffs_statfs(mp, &mp->mnt_stat, p);
	vfs_unbusy(mp);
	inittodr((time_t)0);

	return (0);
}
示例#13
0
/*
 * ex_txt --
 *	Get lines from the terminal for ex.
 *
 * PUBLIC: int ex_txt __P((SCR *, TEXTH *, ARG_CHAR_T, u_int32_t));
 */
int
ex_txt(SCR *sp, TEXTH *tiqh, ARG_CHAR_T prompt, u_int32_t flags)
{
	EVENT ev;
	GS *gp;
	TEXT ait, *ntp, *tp;
	carat_t carat_st;
	size_t cnt;
	int rval;

	rval = 0;

	/*
	 * Get a TEXT structure with some initial buffer space, reusing the
	 * last one if it's big enough.  (All TEXT bookkeeping fields default
	 * to 0 -- text_init() handles this.)
	 */
	if (tiqh->cqh_first != (void *)tiqh) {
		tp = tiqh->cqh_first;
		if (tp->q.cqe_next != (void *)tiqh || tp->lb_len < 32) {
			text_lfree(tiqh);
			goto newtp;
		}
		tp->len = 0;
	} else {
newtp:		if ((tp = text_init(sp, NULL, 0, 32)) == NULL)
			goto err;
		CIRCLEQ_INSERT_HEAD(tiqh, tp, q);
	}

	/* Set the starting line number. */
	tp->lno = sp->lno + 1;

	/*
	 * If it's a terminal, set up autoindent, put out the prompt, and
	 * set it up so we know we were suspended.  Otherwise, turn off
	 * the autoindent flag, as that requires less special casing below.
	 *
	 * XXX
	 * Historic practice is that ^Z suspended command mode (but, because
	 * it ran in cooked mode, it was unaffected by the autowrite option.)
	 * On restart, any "current" input was discarded, whether in insert
	 * mode or not, and ex was in command mode.  This code matches historic
	 * practice, but not 'cause it's easier.
	 */
	gp = sp->gp;
	if (F_ISSET(gp, G_SCRIPTED))
		LF_CLR(TXT_AUTOINDENT);
	else {
		if (LF_ISSET(TXT_AUTOINDENT)) {
			LF_SET(TXT_EOFCHAR);
			if (v_txt_auto(sp, sp->lno, NULL, 0, tp))
				goto err;
		}
		txt_prompt(sp, tp, prompt, flags);
	}

	for (carat_st = C_NOTSET;;) {
		if (v_event_get(sp, &ev, 0, 0))
			goto err;

		/* Deal with all non-character events. */
		switch (ev.e_event) {
		case E_CHARACTER:
			break;
		case E_ERR:
			goto err;
		case E_REPAINT:
		case E_WRESIZE:
			continue;
		case E_EOF:
			rval = 1;
			/* FALLTHROUGH */
		case E_INTERRUPT:
			/*
			 * Handle EOF/SIGINT events by discarding partially
			 * entered text and returning.  EOF returns failure,
			 * E_INTERRUPT returns success.
			 */
			goto notlast;
		default:
			v_event_err(sp, &ev);
			goto notlast;
		}

		/*
		 * Deal with character events.
		 *
		 * Check to see if the character fits into the input buffer.
		 * (Use tp->len, ignore overwrite and non-printable chars.)
		 */
		BINC_GOTOW(sp, tp->lb, tp->lb_len, tp->len + 1);

		switch (ev.e_value) {
		case K_CR:
			/*
			 * !!!
			 * Historically, <carriage-return>'s in the command
			 * weren't special, so the ex parser would return an
			 * unknown command error message.  However, if they
			 * terminated the command if they were in a map.  I'm
			 * pretty sure this still isn't right, but it handles
			 * what I've seen so far.
			 */
			if (!FL_ISSET(ev.e_flags, CH_MAPPED))
				goto ins_ch;
			/* FALLTHROUGH */
		case K_NL:
			/*
			 * '\' can escape <carriage-return>/<newline>.  We
			 * don't discard the backslash because we need it
			 * to get the <newline> through the ex parser.
			 */
			if (LF_ISSET(TXT_BACKSLASH) &&
			    tp->len != 0 && tp->lb[tp->len - 1] == '\\')
				goto ins_ch;

			/*
			 * CR returns from the ex command line.
			 *
			 * XXX
			 * Terminate with a nul, needed by filter.
			 */
			if (LF_ISSET(TXT_CR)) {
				tp->lb[tp->len] = '\0';
				goto done;
			}

			/*
			 * '.' may terminate text input mode; free the current
			 * TEXT.
			 */
			if (LF_ISSET(TXT_DOTTERM) && tp->len == tp->ai + 1 &&
			    tp->lb[tp->len - 1] == '.') {
notlast:			CIRCLEQ_REMOVE(tiqh, tp, q);
				text_free(tp);
				goto done;
			}

			/* Set up bookkeeping for the new line. */
			if ((ntp = text_init(sp, NULL, 0, 32)) == NULL)
				goto err;
			ntp->lno = tp->lno + 1;

			/*
			 * Reset the autoindent line value.  0^D keeps the ai
			 * line from changing, ^D changes the level, even if
			 * there were no characters in the old line.  Note, if
			 * using the current tp structure, use the cursor as
			 * the length, the autoindent characters may have been
			 * erased.
			 */
			if (LF_ISSET(TXT_AUTOINDENT)) {
				if (carat_st == C_NOCHANGE) {
					if (v_txt_auto(sp,
					    OOBLNO, &ait, ait.ai, ntp))
						goto err;
					free(ait.lb);
				} else
					if (v_txt_auto(sp,
					    OOBLNO, tp, tp->len, ntp))
						goto err;
				carat_st = C_NOTSET;
			}
			txt_prompt(sp, ntp, prompt, flags);

			/*
			 * Swap old and new TEXT's, and insert the new TEXT
			 * into the queue.
			 */
			tp = ntp;
			CIRCLEQ_INSERT_TAIL(tiqh, tp, q);
			break;
		case K_CARAT:			/* Delete autoindent chars. */
			if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
				carat_st = C_CARATSET;
			goto ins_ch;
		case K_ZERO:			/* Delete autoindent chars. */
			if (tp->len <= tp->ai && LF_ISSET(TXT_AUTOINDENT))
				carat_st = C_ZEROSET;
			goto ins_ch;
		case K_CNTRLD:			/* Delete autoindent char. */
			/*
			 * !!!
			 * Historically, the ^D command took (but then ignored)
			 * a count.  For simplicity, we don't return it unless
			 * it's the first character entered.  The check for len
			 * equal to 0 is okay, TXT_AUTOINDENT won't be set.
			 */
			if (LF_ISSET(TXT_CNTRLD)) {
				for (cnt = 0; cnt < tp->len; ++cnt)
					if (!isblank(tp->lb[cnt]))
						break;
				if (cnt == tp->len) {
					tp->len = 1;
					tp->lb[0] = ev.e_c;
					tp->lb[1] = '\0';

					/*
					 * Put out a line separator, in case
					 * the command fails.
					 */
					(void)putchar('\n');
					goto done;
				}
			}

			/*
			 * POSIX 1003.1b-1993, paragraph 7.1.1.9, states that
			 * the EOF characters are discarded if there are other
			 * characters to process in the line, i.e. if the EOF
			 * is not the first character in the line.  For this
			 * reason, historic ex discarded the EOF characters,
			 * even if occurring in the middle of the input line.
			 * We match that historic practice.
			 *
			 * !!!
			 * The test for discarding in the middle of the line is
			 * done in the switch, because the CARAT forms are N+1,
			 * not N.
			 *
			 * !!!
			 * There's considerable magic to make the terminal code
			 * return the EOF character at all.  See that code for
			 * details.
			 */
			if (!LF_ISSET(TXT_AUTOINDENT) || tp->len == 0)
				continue;
			switch (carat_st) {
			case C_CARATSET:		/* ^^D */
				if (tp->len > tp->ai + 1)
					continue;

				/* Save the ai string for later. */
				ait.lb = NULL;
				ait.lb_len = 0;
				BINC_GOTOW(sp, ait.lb, ait.lb_len, tp->ai);
				MEMCPYW(ait.lb, tp->lb, tp->ai);
				ait.ai = ait.len = tp->ai;

				carat_st = C_NOCHANGE;
				goto leftmargin;
			case C_ZEROSET:			/* 0^D */
				if (tp->len > tp->ai + 1)
					continue;

				carat_st = C_NOTSET;
leftmargin:			(void)gp->scr_ex_adjust(sp, EX_TERM_CE);
				tp->ai = tp->len = 0;
				break;
			case C_NOTSET:			/* ^D */
				if (tp->len > tp->ai)
					continue;

				if (txt_dent(sp, tp))
					goto err;
				break;
			default:
				abort();
			}

			/* Clear and redisplay the line. */
			(void)gp->scr_ex_adjust(sp, EX_TERM_CE);
			txt_prompt(sp, tp, prompt, flags);
			break;
		default:
			/*
			 * See the TXT_BEAUTIFY comment in vi/v_txt_ev.c.
			 *
			 * Silently eliminate any iscntrl() character that was
			 * not already handled specially, except for <tab> and
			 * <ff>.
			 */
ins_ch:			if (LF_ISSET(TXT_BEAUTIFY) && ISCNTRL(ev.e_c) &&
			    ev.e_value != K_FORMFEED && ev.e_value != K_TAB)
				break;

			tp->lb[tp->len++] = ev.e_c;
			break;
		}
	}
	/* NOTREACHED */

done:	return (rval);

err:	
alloc_err:
	return (1);
}
示例#14
0
static void get_prompt_str(struct gstr *r, struct property *prop,
                           struct jk_head *head)
{
    int i, j;
    struct menu *submenu[8], *menu, *location = NULL;
    struct jump_key *jump;

    str_printf(r, _("Prompt: %s\n"), _(prop->text));
    str_printf(r, _("  Defined at %s:%d\n"), prop->menu->file->name,
               prop->menu->lineno);
    if (!expr_is_yes(prop->visible.expr)) {
        str_append(r, _("  Depends on: "));
        expr_gstr_print(prop->visible.expr, r);
        str_append(r, "\n");
    }
    menu = prop->menu->parent;
    for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
        bool accessible = menu_is_visible(menu);

        submenu[i++] = menu;
        if (location == NULL && accessible)
            location = menu;
    }
    if (head && location) {
        jump = malloc(sizeof(struct jump_key));

        if (menu_is_visible(prop->menu)) {
            /*
             * There is not enough room to put the hint at the
             * beginning of the "Prompt" line. Put the hint on the
             * last "Location" line even when it would belong on
             * the former.
             */
            jump->target = prop->menu;
        } else
            jump->target = location;

        if (CIRCLEQ_EMPTY(head))
            jump->index = 0;
        else
            jump->index = CIRCLEQ_LAST(head)->index + 1;

        CIRCLEQ_INSERT_TAIL(head, jump, entries);
    }

    if (i > 0) {
        str_printf(r, _("  Location:\n"));
        for (j = 4; --i >= 0; j += 2) {
            menu = submenu[i];
            if (head && location && menu == location)
                jump->offset = r->len - 1;
            str_printf(r, "%*c-> %s", j, ' ',
                       _(menu_get_prompt(menu)));
            if (menu->sym) {
                str_printf(r, " (%s [=%s])", menu->sym->name ?
                           menu->sym->name : _("<choice>"),
                           sym_get_string_value(menu->sym));
            }
            str_append(r, "\n");
        }
    }
}
示例#15
0
文件: exf.c 项目: fishman/nvi
/*
 * file_init --
 *	Start editing a file, based on the FREF structure.  If successsful,
 *	let go of any previous file.  Don't release the previous file until
 *	absolutely sure we have the new one.
 *
 * PUBLIC: int file_init __P((SCR *, FREF *, char *, int));
 */
int
file_init(SCR *sp, FREF *frp, char *rcv_name, int flags)
{
    EXF *ep;
    struct stat sb;
    size_t psize;
    int fd, exists, open_err, readonly, stolen;
    char *oname, tname[MAXPATHLEN];

    stolen = open_err = readonly = 0;

    /*
     * If the file is a recovery file, let the recovery code handle it.
     * Clear the FR_RECOVER flag first -- the recovery code does set up,
     * and then calls us!  If the recovery call fails, it's probably
     * because the named file doesn't exist.  So, move boldly forward,
     * presuming that there's an error message the user will get to see.
     */
    if (F_ISSET(frp, FR_RECOVER)) {
        F_CLR(frp, FR_RECOVER);
        return (rcv_read(sp, frp));
    }

    /*
     * Required FRP initialization; the only flag we keep is the
     * cursor information.
     */
    F_CLR(frp, ~FR_CURSORSET);

    /*
     * Scan the user's path to find the file that we're going to
     * try and open.
     */
    if (file_spath(sp, frp, &sb, &exists))
        return (1);

    /*
     * Check whether we already have this file opened in some
     * other screen.
     */
    if (exists) {
        EXF *exfp;
        for (exfp = sp->gp->exfq.cqh_first;
                exfp != (EXF *)&sp->gp->exfq; exfp = exfp->q.cqe_next) {
            if (exfp->mdev == sb.st_dev &&
                    exfp->minode == sb.st_ino &&
                    (exfp != sp->ep || exfp->refcnt > 1)) {
                ep = exfp;
                goto postinit;
            }
        }
    }

    /*
     * Required EXF initialization:
     *	Flush the line caches.
     *	Default recover mail file fd to -1.
     *	Set initial EXF flag bits.
     */
    CALLOC_RET(sp, ep, EXF *, 1, sizeof(EXF));
    CIRCLEQ_INIT(&ep->scrq);
    sp->c_lno = ep->c_nlines = OOBLNO;
    ep->rcv_fd = ep->fcntl_fd = -1;
    F_SET(ep, F_FIRSTMODIFY);

    /*
     * If no name or backing file, for whatever reason, create a backing
     * temporary file, saving the temp file name so we can later unlink
     * it.  If the user never named this file, copy the temporary file name
     * to the real name (we display that until the user renames it).
     */
    oname = frp->name;
    if (LF_ISSET(FS_OPENERR) || oname == NULL || !exists) {
        if (opts_empty(sp, O_TMP_DIRECTORY, 0))
            goto err;
        (void)snprintf(tname, sizeof(tname),
                       "%s/vi.XXXXXX", O_STR(sp, O_TMP_DIRECTORY));
        if ((fd = mkstemp(tname)) == -1) {
            msgq(sp, M_SYSERR,
                 "237|Unable to create temporary file");
            goto err;
        }
        (void)close(fd);

        if (frp->name == NULL)
            F_SET(frp, FR_TMPFILE);
        if ((frp->tname = strdup(tname)) == NULL ||
                (frp->name == NULL &&
                 (frp->name = strdup(tname)) == NULL)) {
            if (frp->tname != NULL) {
                free(frp->tname);
            }
            msgq(sp, M_SYSERR, NULL);
            (void)unlink(tname);
            goto err;
        }
        oname = frp->tname;
        psize = 1024;
        if (!LF_ISSET(FS_OPENERR))
            F_SET(frp, FR_NEWFILE);

        time(&ep->mtime);
    } else {
        /*
         * XXX
         * A seat of the pants calculation: try to keep the file in
         * 15 pages or less.  Don't use a page size larger than 10K
         * (vi should have good locality) or smaller than 1K.
         */
        psize = ((sb.st_size / 15) + 1023) / 1024;
        if (psize > 10)
            psize = 10;
        if (psize == 0)
            psize = 1;
        psize *= 1024;

        F_SET(ep, F_DEVSET);
        ep->mdev = sb.st_dev;
        ep->minode = sb.st_ino;

        ep->mtime = sb.st_mtime;

        if (!S_ISREG(sb.st_mode))
            msgq_str(sp, M_ERR, oname,
                     "238|Warning: %s is not a regular file");
    }

    /* Set up recovery. */
    if (rcv_name == NULL) {
        /* ep->rcv_path NULL if rcv_tmp fails */
        rcv_tmp(sp, ep, frp->name);
    } else {
        if ((ep->rcv_path = strdup(rcv_name)) == NULL) {
            msgq(sp, M_SYSERR, NULL);
            goto err;
        }
        F_SET(ep, F_MODIFIED);
    }

    if (db_setup(sp, ep))
        goto err;

    /* Open a db structure. */
    if ((sp->db_error = db_create(&ep->db, 0, 0)) != 0) {
        msgq(sp, M_DBERR, "db_create");
        goto err;
    }

    ep->db->set_re_delim(ep->db, '\n');		/* Always set. */
    ep->db->set_pagesize(ep->db, psize);
    ep->db->set_flags(ep->db, DB_RENUMBER | DB_SNAPSHOT);
    if (rcv_name == NULL)
        ep->db->set_re_source(ep->db, oname);

    /*
     * Don't let db use mmap when using fcntl for locking
     */
#ifdef HAVE_LOCK_FCNTL
#define NOMMAPIFFCNTL DB_NOMMAP
#else
#define NOMMAPIFFCNTL 0
#endif

#define _DB_OPEN_MODE	S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH

    if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO,
                                ((rcv_name == 0) ? DB_TRUNCATE : 0) | VI_DB_THREAD | NOMMAPIFFCNTL,
                                _DB_OPEN_MODE)) != 0) {
        msgq_str(sp,
                 M_DBERR, rcv_name == NULL ? oname : rcv_name, "%s");
        /*
         * !!!
         * Historically, vi permitted users to edit files that couldn't
         * be read.  This isn't useful for single files from a command
         * line, but it's quite useful for "vi *.c", since you can skip
         * past files that you can't read.
         */
        ep->db = NULL; /* Don't close it; it wasn't opened */

        if (LF_ISSET(FS_OPENERR))
            goto err;

        open_err = 1;
        goto oerr;
    }

    /* re_source is loaded into the database.
     * Close it and reopen it in the environment.
     */
    if ((sp->db_error = ep->db->close(ep->db, 0))) {
        msgq(sp, M_DBERR, "close");
        goto err;
    }
    if ((sp->db_error = db_create(&ep->db, ep->env, 0)) != 0) {
        msgq(sp, M_DBERR, "db_create 2");
        goto err;
    }
    if ((sp->db_error = db_open(ep->db, ep->rcv_path, DB_RECNO,
                                VI_DB_THREAD | NOMMAPIFFCNTL, _DB_OPEN_MODE)) != 0) {
        msgq_str(sp,
                 M_DBERR, ep->rcv_path, "%s");
        goto err;
    }

    /*
     * Do the remaining things that can cause failure of the new file,
     * mark and logging initialization.
     */
    if (mark_init(sp, ep) || log_init(sp, ep))
        goto err;

postinit:
    /*
     * Set the alternate file name to be the file we're discarding.
     *
     * !!!
     * Temporary files can't become alternate files, so there's no file
     * name.  This matches historical practice, although it could only
     * happen in historical vi as the result of the initial command, i.e.
     * if vi was executed without a file name.
     */
    if (LF_ISSET(FS_SETALT))
        set_alt_name(sp, sp->frp == NULL ||
                     F_ISSET(sp->frp, FR_TMPFILE) ? NULL : sp->frp->name);

    /*
     * Close the previous file; if that fails, close the new one and run
     * for the border.
     *
     * !!!
     * There's a nasty special case.  If the user edits a temporary file,
     * and then does an ":e! %", we need to re-initialize the backing
     * file, but we can't change the name.  (It's worse -- we're dealing
     * with *names* here, we can't even detect that it happened.)  Set a
     * flag so that the file_end routine ignores the backing information
     * of the old file if it happens to be the same as the new one.
     *
     * !!!
     * Side-effect: after the call to file_end(), sp->frp may be NULL.
     */
    if (sp->ep != NULL) {
        F_SET(frp, FR_DONTDELETE);
        if (file_end(sp, NULL, LF_ISSET(FS_FORCE))) {
            (void)file_end(sp, ep, 1);
            goto err;
        }
        sp->ep = NULL;
        F_CLR(frp, FR_DONTDELETE);
    }

    /*
     * Lock the file; if it's a recovery file, it should already be
     * locked.  Note, we acquire the lock after the previous file
     * has been ended, so that we don't get an "already locked" error
     * for ":edit!".
     *
     * XXX
     * While the user can't interrupt us between the open and here,
     * there's a race between the dbopen() and the lock.  Not much
     * we can do about it.
     *
     * XXX
     * We don't make a big deal of not being able to lock the file.  As
     * locking rarely works over NFS, and often fails if the file was
     * mmap(2)'d, it's far too common to do anything like print an error
     * message, let alone make the file readonly.  At some future time,
     * when locking is a little more reliable, this should change to be
     * an error.
     */
    if (rcv_name == NULL && ep->refcnt == 0) {
        if ((ep->fd = open(oname, O_RDWR)) == -1)
            goto no_lock;

        switch (file_lock(sp, oname, &ep->fcntl_fd, ep->fd, 1)) {
        case LOCK_FAILED:
no_lock:
            F_SET(frp, FR_UNLOCKED);
            break;
        case LOCK_UNAVAIL:
            readonly = 1;
            msgq_str(sp, M_INFO, oname,
                     "239|%s already locked, session is read-only");
            break;
        case LOCK_SUCCESS:
            break;
        }
    }

    /*
         * Historically, the readonly edit option was set per edit buffer in
         * vi, unless the -R command-line option was specified or the program
         * was executed as "view".  (Well, to be truthful, if the letter 'w'
         * occurred anywhere in the program name, but let's not get into that.)
     * So, the persistant readonly state has to be stored in the screen
     * structure, and the edit option value toggles with the contents of
     * the edit buffer.  If the persistant readonly flag is set, set the
     * readonly edit option.
     *
     * Otherwise, try and figure out if a file is readonly.  This is a
     * dangerous thing to do.  The kernel is the only arbiter of whether
     * or not a file is writeable, and the best that a user program can
     * do is guess.  Obvious loopholes are files that are on a file system
     * mounted readonly (access catches this one on a few systems), or
     * alternate protection mechanisms, ACL's for example, that we can't
     * portably check.  Lots of fun, and only here because users whined.
     *
     * !!!
     * Historic vi displayed the readonly message if none of the file
     * write bits were set, or if an an access(2) call on the path
     * failed.  This seems reasonable.  If the file is mode 444, root
     * users may want to know that the owner of the file did not expect
     * it to be written.
     *
     * Historic vi set the readonly bit if no write bits were set for
     * a file, even if the access call would have succeeded.  This makes
     * the superuser force the write even when vi expects that it will
     * succeed.  I'm less supportive of this semantic, but it's historic
     * practice and the conservative approach to vi'ing files as root.
     *
     * It would be nice if there was some way to update this when the user
     * does a "^Z; chmod ...".  The problem is that we'd first have to
     * distinguish between readonly bits set because of file permissions
     * and those set for other reasons.  That's not too hard, but deciding
     * when to reevaluate the permissions is trickier.  An alternative
     * might be to turn off the readonly bit if the user forces a write
     * and it succeeds.
     *
     * XXX
     * Access(2) doesn't consider the effective uid/gid values.  This
     * probably isn't a problem for vi when it's running standalone.
     */
    if (readonly || F_ISSET(sp, SC_READONLY) ||
            (!F_ISSET(frp, FR_NEWFILE) &&
             (!(sb.st_mode & (S_IWUSR | S_IWGRP | S_IWOTH)) ||
              access(frp->name, W_OK))))
        O_SET(sp, O_READONLY);
    else
        O_CLR(sp, O_READONLY);

    /* Switch... */
    ++ep->refcnt;
    CIRCLEQ_INSERT_HEAD(&ep->scrq, sp, eq);
    sp->ep = ep;
    sp->frp = frp;

    /* Set the initial cursor position, queue initial command. */
    file_cinit(sp);

    /* Report conversion errors again. */
    F_CLR(sp, SC_CONV_ERROR);

    /* Redraw the screen from scratch, schedule a welcome message. */
    F_SET(sp, SC_SCR_REFORMAT | SC_STATUS);

    if (frp->lno == OOBLNO)
        F_SET(sp, SC_SCR_TOP);

    /* Append into the chain of file structures. */
    if (ep->refcnt == 1)
        CIRCLEQ_INSERT_TAIL(&sp->gp->exfq, ep, q);

    return (0);

err:
    if (frp->name != NULL) {
        free(frp->name);
        frp->name = NULL;
    }
    if (frp->tname != NULL) {
        (void)unlink(frp->tname);
        free(frp->tname);
        frp->tname = NULL;
    }

oerr:
    if (F_ISSET(ep, F_RCV_ON))
        (void)unlink(ep->rcv_path);
    if (ep->rcv_path != NULL) {
        free(ep->rcv_path);
        ep->rcv_path = NULL;
    }
    if (ep->db != NULL) {
        (void)ep->db->close(ep->db, DB_NOSYNC);
        ep->db = NULL;
    }
    free(ep);

    return (open_err && !LF_ISSET(FS_OPENERR) ?
            file_init(sp, frp, rcv_name, flags | FS_OPENERR) : 1);
}
示例#16
0
int
domount(kthread_t *td, vnode_t *vp, const char *fstype, char *fspath,
    char *fspec, int fsflags)
{
	struct mount *mp;
	struct vfsconf *vfsp;
	struct ucred *newcr, *oldcr;
	int error;
	
	/*
	 * Be ultra-paranoid about making sure the type and fspath
	 * variables will fit in our mp buffers, including the
	 * terminating NUL.
	 */
	if (strlen(fstype) >= MFSNAMELEN || strlen(fspath) >= MNAMELEN)
		return (ENAMETOOLONG);

	vfsp = vfs_byname_kld(fstype, td, &error);
	if (vfsp == NULL)
		return (ENODEV);

	if (vp->v_type != VDIR)
		return (ENOTDIR);
	simple_lock(&vp->v_interlock);
	if ((vp->v_iflag & VI_MOUNT) != 0 ||
	    vp->v_mountedhere != NULL) {
		simple_unlock(&vp->v_interlock);
		return (EBUSY);
	}
	vp->v_iflag |= VI_MOUNT;
	simple_unlock(&vp->v_interlock);

	/*
	 * Allocate and initialize the filesystem.
	 */
	vn_lock(vp, LK_SHARED | LK_RETRY);
	mp = vfs_mount_alloc(vp, vfsp, fspath, td);
	VOP_UNLOCK(vp);

	mp->mnt_optnew = NULL;
	vfs_setmntopt(mp, "from", fspec, 0);
	mp->mnt_optnew = mp->mnt_opt;
	mp->mnt_opt = NULL;

	/*
	 * Set the mount level flags.
	 * crdup() can sleep, so do it before acquiring a mutex.
	 */
	newcr = crdup(kcred);
	MNT_ILOCK(mp);
	if (fsflags & MNT_RDONLY)
		mp->mnt_flag |= MNT_RDONLY;
	mp->mnt_flag &=~ MNT_UPDATEMASK;
	mp->mnt_flag |= fsflags & (MNT_UPDATEMASK | MNT_FORCE | MNT_ROOTFS);
	/*
	 * Unprivileged user can trigger mounting a snapshot, but we don't want
	 * him to unmount it, so we switch to privileged credentials.
	 */
	oldcr = mp->mnt_cred;
	mp->mnt_cred = newcr;
	mp->mnt_stat.f_owner = mp->mnt_cred->cr_uid;
	MNT_IUNLOCK(mp);
	crfree(oldcr);
	/*
	 * Mount the filesystem.
	 * XXX The final recipients of VFS_MOUNT just overwrite the ndp they
	 * get.  No freeing of cn_pnbuf.
	 */
	error = VFS_MOUNT(mp, td);

	if (!error) {
		if (mp->mnt_opt != NULL)
			vfs_freeopts(mp->mnt_opt);
		mp->mnt_opt = mp->mnt_optnew;
		(void)VFS_STATFS(mp, &mp->mnt_stat, td);
	}
	/*
	 * Prevent external consumers of mount options from reading
	 * mnt_optnew.
	*/
	mp->mnt_optnew = NULL;
	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
	/*
	 * Put the new filesystem on the mount list after root.
	 */
#ifdef FREEBSD_NAMECACHE
	cache_purge(vp);
#endif
	if (!error) {
		vnode_t *mvp;

		simple_lock(&vp->v_interlock);
		vp->v_iflag &= ~VI_MOUNT;
		simple_unlock(&vp->v_interlock);
		vp->v_mountedhere = mp;
		mutex_enter(&mountlist_lock);
		CIRCLEQ_INSERT_TAIL(&mountlist, mp, mnt_list);
		mutex_exit(&mountlist_lock);
		vfs_event_signal(NULL, VQ_MOUNT, 0);
		if (VFS_ROOT(mp, LK_EXCLUSIVE, &mvp, td))
			panic("mount: lost mount");
		mountcheckdirs(vp, mvp);
		vput(mvp);
		VOP_UNLOCK(vp);
		if ((mp->mnt_flag & MNT_RDONLY) == 0)
			error = vfs_allocate_syncvnode(mp);
		vfs_unbusy(mp, td);
		if (error)
			vrele(vp);
		else
			vfs_mountedfrom(mp, fspec);
	} else {
		simple_lock(&vp->v_interlock);
		vp->v_iflag &= ~VI_MOUNT;
		simple_unlock(&vp->v_interlock);
		VOP_UNLOCK(vp);
		vfs_unbusy(mp, td);
		vfs_mount_destroy(mp);
	}
	return (error);
}