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