diff options
| author | Seigo Tanimura <tanimura@FreeBSD.org> | 2002-02-23 11:12:57 +0000 | 
|---|---|---|
| committer | Seigo Tanimura <tanimura@FreeBSD.org> | 2002-02-23 11:12:57 +0000 | 
| commit | f591779bb575703cbb6674d324afb4bd212b8cbb (patch) | |
| tree | 2289c653c0f7aa23498f82b603c33107952652ec /sys/kern/tty.c | |
| parent | 4aaca8854285a47e7fd520d5a2797dbf03d05bec (diff) | |
Notes
Diffstat (limited to 'sys/kern/tty.c')
| -rw-r--r-- | sys/kern/tty.c | 195 | 
1 files changed, 142 insertions, 53 deletions
diff --git a/sys/kern/tty.c b/sys/kern/tty.c index 5c778b7f98c7..2ca162a69b78 100644 --- a/sys/kern/tty.c +++ b/sys/kern/tty.c @@ -75,6 +75,7 @@  #include <sys/filio.h>  #include <sys/lock.h>  #include <sys/mutex.h> +#include <sys/sx.h>  #if defined(COMPAT_43) || defined(COMPAT_SUNOS)  #include <sys/ioctl_compat.h>  #endif @@ -328,7 +329,11 @@ ttyinput(c, tp)  				return (0);  			if (ISSET(iflag, BRKINT)) {  				ttyflush(tp, FREAD | FWRITE); -				pgsignal(tp->t_pgrp, SIGINT, 1); +				if (tp->t_pgrp != NULL) { +					PGRP_LOCK(tp->t_pgrp); +					pgsignal(tp->t_pgrp, SIGINT, 1); +					PGRP_UNLOCK(tp->t_pgrp); +				}  				goto endcase;  			}  			if (ISSET(iflag, PARMRK)) @@ -406,15 +411,23 @@ parmrk:  				if (!ISSET(lflag, NOFLSH))  					ttyflush(tp, FREAD | FWRITE);  				ttyecho(c, tp); -				pgsignal(tp->t_pgrp, -				    CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); +				if (tp->t_pgrp != NULL) { +					PGRP_LOCK(tp->t_pgrp); +					pgsignal(tp->t_pgrp, +					    CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1); +					PGRP_UNLOCK(tp->t_pgrp); +				}  				goto endcase;  			}  			if (CCEQ(cc[VSUSP], c)) {  				if (!ISSET(lflag, NOFLSH))  					ttyflush(tp, FREAD);  				ttyecho(c, tp); -				pgsignal(tp->t_pgrp, SIGTSTP, 1); +				if (tp->t_pgrp != NULL) { +					PGRP_LOCK(tp->t_pgrp); +					pgsignal(tp->t_pgrp, SIGTSTP, 1); +					PGRP_UNLOCK(tp->t_pgrp); +				}  				goto endcase;  			}  		} @@ -532,8 +545,11 @@ parmrk:  		 * ^T - kernel info and generate SIGINFO  		 */  		if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) { -			if (ISSET(lflag, ISIG)) +			if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) { +				PGRP_LOCK(tp->t_pgrp);  				pgsignal(tp->t_pgrp, SIGINFO, 1); +				PGRP_UNLOCK(tp->t_pgrp); +			}  			if (!ISSET(lflag, NOKERNINFO))  				ttyinfo(tp);  			goto endcase; @@ -752,17 +768,30 @@ ttioctl(tp, cmd, data, flag)  	case  TIOCSETP:  	case  TIOCSLTC:  #endif +		PGRPSESS_SLOCK(); +		PROC_LOCK(p);  		while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&  		    !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&  		    !SIGISMEMBER(p->p_sigmask, SIGTTOU)) { -			if (p->p_pgrp->pg_jobc == 0) +			if (p->p_pgrp->pg_jobc == 0) { +				PROC_UNLOCK(p); +				PGRPSESS_SUNLOCK();  				return (EIO); +			} +			PROC_UNLOCK(p); +			PGRP_LOCK(p->p_pgrp);  			pgsignal(p->p_pgrp, SIGTTOU, 1); +			PGRP_UNLOCK(p->p_pgrp);  			error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1",  					 0); -			if (error) +			if (error) { +				PGRPSESS_SUNLOCK();  				return (error); +			} +			PROC_LOCK(p);  		} +		PROC_UNLOCK(p); +		PGRPSESS_SUNLOCK();  		break;  	} @@ -1012,22 +1041,44 @@ ttioctl(tp, cmd, data, flag)  		break;  	case TIOCSCTTY:			/* become controlling tty */  		/* Session ctty vnode pointer set in vnode layer. */ +		PGRPSESS_XLOCK();  		if (!SESS_LEADER(p) ||  		    ((p->p_session->s_ttyvp || tp->t_session) && -		    (tp->t_session != p->p_session))) +		     (tp->t_session != p->p_session))) { +			PGRPSESS_XUNLOCK();  			return (EPERM); +		}  		tp->t_session = p->p_session;  		tp->t_pgrp = p->p_pgrp; +		SESS_LOCK(p->p_session);  		p->p_session->s_ttyp = tp; +		SESS_UNLOCK(p->p_session); +		PROC_LOCK(p);  		p->p_flag |= P_CONTROLT; +		PROC_UNLOCK(p); +		PGRPSESS_XUNLOCK();  		break;  	case TIOCSPGRP: {		/* set pgrp of tty */ -		register struct pgrp *pgrp = pgfind(*(int *)data); - -		if (!isctty(p, tp)) +		register struct pgrp *pgrp; + +		PGRPSESS_SLOCK(); +		pgrp = pgfind(*(int *)data); +		if (!isctty(p, tp)) { +			if (pgrp != NULL) +				PGRP_UNLOCK(pgrp); +			PGRPSESS_SUNLOCK();  			return (ENOTTY); -		else if (pgrp == NULL || pgrp->pg_session != p->p_session) +		} +		if (pgrp == NULL) { +			PGRPSESS_SUNLOCK();  			return (EPERM); +		} +		PGRP_UNLOCK(pgrp); +		if (pgrp->pg_session != p->p_session) { +			PGRPSESS_SUNLOCK(); +			return (EPERM); +		} +		PGRPSESS_SUNLOCK();  		tp->t_pgrp = pgrp;  		break;  	} @@ -1040,7 +1091,11 @@ ttioctl(tp, cmd, data, flag)  		if (bcmp((caddr_t)&tp->t_winsize, data,  		    sizeof (struct winsize))) {  			tp->t_winsize = *(struct winsize *)data; -			pgsignal(tp->t_pgrp, SIGWINCH, 1); +			if (tp->t_pgrp != NULL) { +				PGRP_LOCK(tp->t_pgrp); +				pgsignal(tp->t_pgrp, SIGWINCH, 1); +				PGRP_UNLOCK(tp->t_pgrp); +			}  		}  		break;  	case TIOCSDRAINWAIT: @@ -1459,13 +1514,17 @@ ttymodem(tp, flag)  		    !ISSET(tp->t_cflag, CLOCAL)) {  			SET(tp->t_state, TS_ZOMBIE);  			CLR(tp->t_state, TS_CONNECTED); -			if (tp->t_session && tp->t_session->s_leader) { -				struct proc *p; - -				p = tp->t_session->s_leader; -				PROC_LOCK(p); -				psignal(p, SIGHUP); -				PROC_UNLOCK(p); +			if (tp->t_session) { +				PGRPSESS_SLOCK(); +				if (tp->t_session->s_leader) { +					struct proc *p; + +					p = tp->t_session->s_leader; +					PROC_LOCK(p); +					psignal(p, SIGHUP); +					PROC_UNLOCK(p); +				} +				PGRPSESS_SUNLOCK();  			}  			ttyflush(tp, FREAD | FWRITE);  			return (0); @@ -1549,11 +1608,20 @@ loop:  	 */  	if (isbackground(p, tp)) {  		splx(s); +		PGRPSESS_SLOCK(); +		PROC_LOCK(p);  		if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||  		    SIGISMEMBER(p->p_sigmask, SIGTTIN) || -		    (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) +		    (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) { +			PROC_UNLOCK(p); +			PGRPSESS_SUNLOCK();  			return (EIO); +		} +		PROC_UNLOCK(p); +		PGRP_LOCK(p->p_pgrp); +		PGRPSESS_SUNLOCK();  		pgsignal(p->p_pgrp, SIGTTIN, 1); +		PGRP_UNLOCK(p->p_pgrp);  		error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);  		if (error)  			return (error); @@ -1727,7 +1795,11 @@ slowcase:  		 */  		if (CCEQ(cc[VDSUSP], c) &&  		    ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) { -			pgsignal(tp->t_pgrp, SIGTSTP, 1); +			if (tp->t_pgrp != NULL) { +				PGRP_LOCK(tp->t_pgrp); +				pgsignal(tp->t_pgrp, SIGTSTP, 1); +				PGRP_UNLOCK(tp->t_pgrp); +			}  			if (first) {  				error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,  						 "ttybg3", 0); @@ -1855,19 +1927,30 @@ loop:  	 * Hang the process if it's in the background.  	 */  	p = curproc; +	PGRPSESS_SLOCK(); +	PROC_LOCK(p);  	if (isbackground(p, tp) &&  	    ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&  	    !SIGISMEMBER(p->p_sigignore, SIGTTOU) &&  	    !SIGISMEMBER(p->p_sigmask, SIGTTOU)) {  		if (p->p_pgrp->pg_jobc == 0) { +			PROC_UNLOCK(p); +			PGRPSESS_SUNLOCK();  			error = EIO;  			goto out;  		} +		PROC_UNLOCK(p); +		PGRP_LOCK(p->p_pgrp); +		PGRPSESS_SUNLOCK();  		pgsignal(p->p_pgrp, SIGTTOU, 1); +		PGRP_UNLOCK(p->p_pgrp);  		error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0);  		if (error)  			goto out;  		goto loop; +	} else { +		PROC_UNLOCK(p); +		PGRPSESS_SUNLOCK();  	}  	/*  	 * Process the user's data in at most OBUFSIZ chunks.  Perform any @@ -2328,38 +2411,44 @@ ttyinfo(tp)  		ttyprintf(tp, "not a controlling terminal\n");  	else if (tp->t_pgrp == NULL)  		ttyprintf(tp, "no foreground process group\n"); -	else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) -		ttyprintf(tp, "empty foreground process group\n");  	else { -		mtx_lock_spin(&sched_lock); - -		/* Pick interesting process. */ -		for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist)) -			if (proc_compare(pick, p)) -				pick = p; - -		td = FIRST_THREAD_IN_PROC(pick); -		stmp = pick->p_stat == SRUN ? "running" :  /* XXXKSE */ -		    td->td_wmesg ? td->td_wmesg : "iowait"; -		calcru(pick, &utime, &stime, NULL); -		ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT || -		    pick->p_stat == SZOMB ? 0 : -		    pgtok(vmspace_resident_count(pick->p_vmspace)); -		mtx_unlock_spin(&sched_lock); - -		ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, -		    stmp); - -		/* Print user time. */ -		ttyprintf(tp, "%ld.%02ldu ", -		    (long)utime.tv_sec, utime.tv_usec / 10000); - -		/* Print system time. */ -		ttyprintf(tp, "%ld.%02lds ", -		    (long)stime.tv_sec, stime.tv_usec / 10000); - -		/* Print percentage cpu, resident set size. */ -		ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp); +		PGRP_LOCK(tp->t_pgrp); +		if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) { +			PGRP_UNLOCK(tp->t_pgrp); +			ttyprintf(tp, "empty foreground process group\n"); +		} else { +			PGRP_UNLOCK(tp->t_pgrp); +			mtx_lock_spin(&sched_lock); + +			/* Pick interesting process. */ +			for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist)) +				if (proc_compare(pick, p)) +					pick = p; + +			td = FIRST_THREAD_IN_PROC(pick); +			stmp = pick->p_stat == SRUN ? "running" :  /* XXXKSE */ +			    td->td_wmesg ? td->td_wmesg : "iowait"; +			calcru(pick, &utime, &stime, NULL); +			ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT || +			    pick->p_stat == SZOMB ? 0 : +			    pgtok(vmspace_resident_count(pick->p_vmspace)); +			mtx_unlock_spin(&sched_lock); + +			ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid, +			    stmp); + +			/* Print user time. */ +			ttyprintf(tp, "%lld.%02ldu ", +			    utime.tv_sec, utime.tv_usec / 10000); + +			/* Print system time. */ +			ttyprintf(tp, "%ld.%02lds ", +			    (long)stime.tv_sec, stime.tv_usec / 10000); + +			/* Print percentage cpu, resident set size. */ +			ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp); + +		}  	}  	tp->t_rocount = 0;	/* so pending input will be retyped if BS */  }  | 
