Home | History | Annotate | Download | only in syscall
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
     27 /*	  All Rights Reserved	*/
     28 
     29 
     30 #pragma ident	"@(#)pgrpsys.c	1.9	06/09/11 SMI"	/* from SVr4.0 1.78 */
     31 
     32 #include <sys/param.h>
     33 #include <sys/types.h>
     34 #include <sys/sysmacros.h>
     35 #include <sys/systm.h>
     36 #include <sys/errno.h>
     37 #include <sys/file.h>
     38 #include <sys/proc.h>
     39 #include <sys/session.h>
     40 #include <sys/debug.h>
     41 
     42 /* ARGSUSED */
     43 int
     44 setpgrp(int flag, int pid, int pgid)
     45 {
     46 	proc_t	*p = curproc;
     47 	int	retval = 0;
     48 	int	sid;
     49 
     50 	switch (flag) {
     51 
     52 	case 1: /* setpgrp() */
     53 		mutex_enter(&pidlock);
     54 		if (p->p_sessp->s_sidp != p->p_pidp && !pgmembers(p->p_pid)) {
     55 			mutex_exit(&pidlock);
     56 			sess_create();
     57 		} else
     58 			mutex_exit(&pidlock);
     59 		mutex_enter(&p->p_splock);
     60 		sid = p->p_sessp->s_sid;
     61 		mutex_exit(&p->p_splock);
     62 		return (sid);
     63 
     64 	case 3: /* setsid() */
     65 		mutex_enter(&pidlock);
     66 		if (p->p_pgidp == p->p_pidp || pgmembers(p->p_pid)) {
     67 			mutex_exit(&pidlock);
     68 			return (set_errno(EPERM));
     69 		}
     70 		mutex_exit(&pidlock);
     71 		sess_create();
     72 		mutex_enter(&p->p_splock);
     73 		sid = p->p_sessp->s_sid;
     74 		mutex_exit(&p->p_splock);
     75 		return (sid);
     76 
     77 	case 5: /* setpgid() */
     78 	{
     79 		mutex_enter(&pidlock);
     80 		if (pid == 0)
     81 			pid = p->p_pid;
     82 		else if (pid < 0 || pid >= maxpid) {
     83 			mutex_exit(&pidlock);
     84 			return (set_errno(EINVAL));
     85 		} else if (pid != p->p_pid) {
     86 			for (p = p->p_child; /* empty */; p = p->p_sibling) {
     87 				if (p == NULL) {
     88 					mutex_exit(&pidlock);
     89 					return (set_errno(ESRCH));
     90 				}
     91 				if (p->p_pid == pid)
     92 					break;
     93 			}
     94 			if (p->p_flag & SEXECED) {
     95 				mutex_exit(&pidlock);
     96 				return (set_errno(EACCES));
     97 			}
     98 			if (p->p_sessp != ttoproc(curthread)->p_sessp) {
     99 				mutex_exit(&pidlock);
    100 				return (set_errno(EPERM));
    101 			}
    102 		}
    103 
    104 		if (p->p_sessp->s_sid == pid) {
    105 			mutex_exit(&pidlock);
    106 			return (set_errno(EPERM));
    107 		}
    108 
    109 		if (pgid == 0)
    110 			pgid = p->p_pid;
    111 		else if (pgid < 0 || pgid >= maxpid) {
    112 			mutex_exit(&pidlock);
    113 			return (set_errno(EINVAL));
    114 		}
    115 
    116 		if (p->p_pgrp == pgid) {
    117 			mutex_exit(&pidlock);
    118 			break;
    119 		} else if (p->p_pid == pgid) {
    120 			/*
    121 			 * We need to protect p_pgidp with p_lock because
    122 			 * /proc looks at it while holding only p_lock.
    123 			 */
    124 			mutex_enter(&p->p_lock);
    125 			pgexit(p);
    126 			pgjoin(p, p->p_pidp);
    127 			mutex_exit(&p->p_lock);
    128 		} else {
    129 			register proc_t *q;
    130 
    131 			if ((q = pgfind(pgid)) == NULL ||
    132 			    q->p_sessp != p->p_sessp) {
    133 				mutex_exit(&pidlock);
    134 				return (set_errno(EPERM));
    135 			}
    136 			/*
    137 			 * See comment above about p_lock and /proc
    138 			 */
    139 			mutex_enter(&p->p_lock);
    140 			pgexit(p);
    141 			pgjoin(p, q->p_pgidp);
    142 			mutex_exit(&p->p_lock);
    143 		}
    144 		mutex_exit(&pidlock);
    145 		break;
    146 	}
    147 
    148 	case 0: /* getpgrp() */
    149 		mutex_enter(&pidlock);
    150 		retval = p->p_pgrp;
    151 		mutex_exit(&pidlock);
    152 		break;
    153 
    154 	case 2: /* getsid() */
    155 	case 4: /* getpgid() */
    156 		if (pid < 0 || pid >= maxpid) {
    157 			return (set_errno(EINVAL));
    158 		}
    159 		mutex_enter(&pidlock);
    160 		if (pid != 0 && p->p_pid != pid &&
    161 		    ((p = prfind(pid)) == NULL || p->p_stat == SIDL)) {
    162 			mutex_exit(&pidlock);
    163 			return (set_errno(ESRCH));
    164 		}
    165 		if (flag == 2)
    166 			retval = p->p_sessp->s_sid;
    167 		else
    168 			retval = p->p_pgrp;
    169 		mutex_exit(&pidlock);
    170 		break;
    171 
    172 	}
    173 	return (retval);
    174 }
    175