1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <unistd.h> 36*7c478bd9Sstevel@tonic-gate #include <ctype.h> 37*7c478bd9Sstevel@tonic-gate #include <string.h> 38*7c478bd9Sstevel@tonic-gate #include <signal.h> 39*7c478bd9Sstevel@tonic-gate #include <stropts.h> 40*7c478bd9Sstevel@tonic-gate #include <errno.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/termio.h> 43*7c478bd9Sstevel@tonic-gate #include <libproc.h> 44*7c478bd9Sstevel@tonic-gate #include "ramdata.h" 45*7c478bd9Sstevel@tonic-gate #include "proto.h" 46*7c478bd9Sstevel@tonic-gate 47*7c478bd9Sstevel@tonic-gate /* 48*7c478bd9Sstevel@tonic-gate * Routines related to interprocess communication 49*7c478bd9Sstevel@tonic-gate * among the truss processes which are controlling 50*7c478bd9Sstevel@tonic-gate * multiple traced processes. 51*7c478bd9Sstevel@tonic-gate */ 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate /* 54*7c478bd9Sstevel@tonic-gate * Function prototypes for static routines in this module. 55*7c478bd9Sstevel@tonic-gate */ 56*7c478bd9Sstevel@tonic-gate void Ecritical(int); 57*7c478bd9Sstevel@tonic-gate void Xcritical(int); 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate /* 60*7c478bd9Sstevel@tonic-gate * Ensure everyone keeps out of each other's way 61*7c478bd9Sstevel@tonic-gate * while writing lines of trace output. 62*7c478bd9Sstevel@tonic-gate */ 63*7c478bd9Sstevel@tonic-gate void 64*7c478bd9Sstevel@tonic-gate Flush() 65*7c478bd9Sstevel@tonic-gate { 66*7c478bd9Sstevel@tonic-gate /* 67*7c478bd9Sstevel@tonic-gate * Except for regions bounded by Eserialize()/Xserialize(), 68*7c478bd9Sstevel@tonic-gate * this is the only place anywhere in the program where a 69*7c478bd9Sstevel@tonic-gate * write() to the trace output file takes place, so here 70*7c478bd9Sstevel@tonic-gate * is where we detect errors writing to the output. 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate 73*7c478bd9Sstevel@tonic-gate errno = 0; 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate Ecritical(0); 76*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 77*7c478bd9Sstevel@tonic-gate Xcritical(0); 78*7c478bd9Sstevel@tonic-gate 79*7c478bd9Sstevel@tonic-gate if (ferror(stdout) && errno) /* error on write(), probably EPIPE */ 80*7c478bd9Sstevel@tonic-gate interrupt = SIGTERM; /* post an interrupt */ 81*7c478bd9Sstevel@tonic-gate } 82*7c478bd9Sstevel@tonic-gate 83*7c478bd9Sstevel@tonic-gate /* 84*7c478bd9Sstevel@tonic-gate * Eserialize() and Xserialize() are used to bracket 85*7c478bd9Sstevel@tonic-gate * a region which may produce large amounts of output, 86*7c478bd9Sstevel@tonic-gate * such as showargs()/dumpargs(). 87*7c478bd9Sstevel@tonic-gate */ 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate void 90*7c478bd9Sstevel@tonic-gate Eserialize() 91*7c478bd9Sstevel@tonic-gate { 92*7c478bd9Sstevel@tonic-gate /* serialize output */ 93*7c478bd9Sstevel@tonic-gate Ecritical(0); 94*7c478bd9Sstevel@tonic-gate } 95*7c478bd9Sstevel@tonic-gate 96*7c478bd9Sstevel@tonic-gate void 97*7c478bd9Sstevel@tonic-gate Xserialize() 98*7c478bd9Sstevel@tonic-gate { 99*7c478bd9Sstevel@tonic-gate (void) fflush(stdout); 100*7c478bd9Sstevel@tonic-gate Xcritical(0); 101*7c478bd9Sstevel@tonic-gate } 102*7c478bd9Sstevel@tonic-gate 103*7c478bd9Sstevel@tonic-gate /* 104*7c478bd9Sstevel@tonic-gate * Enter critical region --- Wait on mutex, lock out other processes. 105*7c478bd9Sstevel@tonic-gate * Lock zero is used to serialize output in situations where multiple processes 106*7c478bd9Sstevel@tonic-gate * may be writing to stdout/stderr and order must be preserved. Most of these 107*7c478bd9Sstevel@tonic-gate * are in expound.c 108*7c478bd9Sstevel@tonic-gate * Lock one is used to protect the table of processes currently being traced 109*7c478bd9Sstevel@tonic-gate * every time a pid is added or removed from the table Ecritical(1)/Xcritical(1) 110*7c478bd9Sstevel@tonic-gate * get called. 111*7c478bd9Sstevel@tonic-gate */ 112*7c478bd9Sstevel@tonic-gate void 113*7c478bd9Sstevel@tonic-gate Ecritical(int num) 114*7c478bd9Sstevel@tonic-gate { 115*7c478bd9Sstevel@tonic-gate int rv; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate if (num == 0) 118*7c478bd9Sstevel@tonic-gate rv = mutex_lock(&gps->ps_mutex0); 119*7c478bd9Sstevel@tonic-gate else if (num == 1) 120*7c478bd9Sstevel@tonic-gate rv = mutex_lock(&gps->ps_mutex1); 121*7c478bd9Sstevel@tonic-gate else 122*7c478bd9Sstevel@tonic-gate abend("Invalid mutex specified", NULL); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate if (rv != 0) { 125*7c478bd9Sstevel@tonic-gate char mnum[2]; 126*7c478bd9Sstevel@tonic-gate mnum[0] = '0' + num; 127*7c478bd9Sstevel@tonic-gate mnum[1] = '\0'; 128*7c478bd9Sstevel@tonic-gate errno = rv; 129*7c478bd9Sstevel@tonic-gate perror(command); 130*7c478bd9Sstevel@tonic-gate errmsg("cannot grab mutex #", mnum); 131*7c478bd9Sstevel@tonic-gate } 132*7c478bd9Sstevel@tonic-gate } 133*7c478bd9Sstevel@tonic-gate 134*7c478bd9Sstevel@tonic-gate /* 135*7c478bd9Sstevel@tonic-gate * Exit critical region --- 136*7c478bd9Sstevel@tonic-gate * Release other processes waiting on mutex. 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate void 139*7c478bd9Sstevel@tonic-gate Xcritical(int num) 140*7c478bd9Sstevel@tonic-gate { 141*7c478bd9Sstevel@tonic-gate int rv; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate if (num == 0) 144*7c478bd9Sstevel@tonic-gate rv = mutex_unlock(&gps->ps_mutex0); 145*7c478bd9Sstevel@tonic-gate else if (num == 1) 146*7c478bd9Sstevel@tonic-gate rv = mutex_unlock(&gps->ps_mutex1); 147*7c478bd9Sstevel@tonic-gate else 148*7c478bd9Sstevel@tonic-gate abend("Invalid mutex specified", NULL); 149*7c478bd9Sstevel@tonic-gate 150*7c478bd9Sstevel@tonic-gate 151*7c478bd9Sstevel@tonic-gate if (rv != 0) { 152*7c478bd9Sstevel@tonic-gate char mnum[2]; 153*7c478bd9Sstevel@tonic-gate mnum[0] = '0' + num; 154*7c478bd9Sstevel@tonic-gate mnum[1] = '\0'; 155*7c478bd9Sstevel@tonic-gate errno = rv; 156*7c478bd9Sstevel@tonic-gate perror(command); 157*7c478bd9Sstevel@tonic-gate errmsg("cannot release mutex #", mnum); 158*7c478bd9Sstevel@tonic-gate } 159*7c478bd9Sstevel@tonic-gate } 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate /* 162*7c478bd9Sstevel@tonic-gate * Add process to set of those being traced. 163*7c478bd9Sstevel@tonic-gate */ 164*7c478bd9Sstevel@tonic-gate void 165*7c478bd9Sstevel@tonic-gate procadd(pid_t spid, const char *lwplist) 166*7c478bd9Sstevel@tonic-gate { 167*7c478bd9Sstevel@tonic-gate int i; 168*7c478bd9Sstevel@tonic-gate int j = -1; 169*7c478bd9Sstevel@tonic-gate 170*7c478bd9Sstevel@tonic-gate if (gps == NULL) 171*7c478bd9Sstevel@tonic-gate return; 172*7c478bd9Sstevel@tonic-gate 173*7c478bd9Sstevel@tonic-gate Ecritical(1); 174*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 175*7c478bd9Sstevel@tonic-gate if (gps->tpid[i] == 0) { 176*7c478bd9Sstevel@tonic-gate if (j == -1) /* remember first vacant slot */ 177*7c478bd9Sstevel@tonic-gate j = i; 178*7c478bd9Sstevel@tonic-gate if (gps->spid[i] == 0) /* this slot is better */ 179*7c478bd9Sstevel@tonic-gate break; 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate } 182*7c478bd9Sstevel@tonic-gate if (i < sizeof (gps->tpid) / sizeof (gps->tpid[0])) 183*7c478bd9Sstevel@tonic-gate j = i; 184*7c478bd9Sstevel@tonic-gate if (j >= 0) { 185*7c478bd9Sstevel@tonic-gate gps->tpid[j] = getpid(); 186*7c478bd9Sstevel@tonic-gate gps->spid[j] = spid; 187*7c478bd9Sstevel@tonic-gate gps->lwps[j] = lwplist; 188*7c478bd9Sstevel@tonic-gate } 189*7c478bd9Sstevel@tonic-gate Xcritical(1); 190*7c478bd9Sstevel@tonic-gate } 191*7c478bd9Sstevel@tonic-gate 192*7c478bd9Sstevel@tonic-gate /* 193*7c478bd9Sstevel@tonic-gate * Delete process from set of those being traced. 194*7c478bd9Sstevel@tonic-gate */ 195*7c478bd9Sstevel@tonic-gate void 196*7c478bd9Sstevel@tonic-gate procdel() 197*7c478bd9Sstevel@tonic-gate { 198*7c478bd9Sstevel@tonic-gate int i; 199*7c478bd9Sstevel@tonic-gate pid_t tpid; 200*7c478bd9Sstevel@tonic-gate 201*7c478bd9Sstevel@tonic-gate if (gps == NULL) 202*7c478bd9Sstevel@tonic-gate return; 203*7c478bd9Sstevel@tonic-gate 204*7c478bd9Sstevel@tonic-gate tpid = getpid(); 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate Ecritical(1); 207*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 208*7c478bd9Sstevel@tonic-gate if (gps->tpid[i] == tpid) { 209*7c478bd9Sstevel@tonic-gate gps->tpid[i] = 0; 210*7c478bd9Sstevel@tonic-gate break; 211*7c478bd9Sstevel@tonic-gate } 212*7c478bd9Sstevel@tonic-gate } 213*7c478bd9Sstevel@tonic-gate Xcritical(1); 214*7c478bd9Sstevel@tonic-gate } 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* 217*7c478bd9Sstevel@tonic-gate * Determine if the lwp for this process should be traced. 218*7c478bd9Sstevel@tonic-gate */ 219*7c478bd9Sstevel@tonic-gate int 220*7c478bd9Sstevel@tonic-gate lwptrace(pid_t spid, lwpid_t lwpid) 221*7c478bd9Sstevel@tonic-gate { 222*7c478bd9Sstevel@tonic-gate int i; 223*7c478bd9Sstevel@tonic-gate pid_t tpid; 224*7c478bd9Sstevel@tonic-gate const char *lwps; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate if (gps == NULL) 227*7c478bd9Sstevel@tonic-gate return (0); 228*7c478bd9Sstevel@tonic-gate 229*7c478bd9Sstevel@tonic-gate tpid = getpid(); 230*7c478bd9Sstevel@tonic-gate 231*7c478bd9Sstevel@tonic-gate Ecritical(1); 232*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid) / sizeof (gps->tpid[0]); i++) { 233*7c478bd9Sstevel@tonic-gate if (gps->tpid[i] == tpid && 234*7c478bd9Sstevel@tonic-gate gps->spid[i] == spid) 235*7c478bd9Sstevel@tonic-gate break; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate lwps = gps->lwps[i]; 238*7c478bd9Sstevel@tonic-gate Xcritical(1); 239*7c478bd9Sstevel@tonic-gate 240*7c478bd9Sstevel@tonic-gate return (proc_lwp_in_set(lwps, lwpid)); 241*7c478bd9Sstevel@tonic-gate } 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate /* 244*7c478bd9Sstevel@tonic-gate * Check for open of a /proc/nnnnn file. 245*7c478bd9Sstevel@tonic-gate * Return 0 if this is not an open of a /proc file. 246*7c478bd9Sstevel@tonic-gate * Return 1 if the process opened itself. 247*7c478bd9Sstevel@tonic-gate * Return 2 if the process failed to open another process 248*7c478bd9Sstevel@tonic-gate * in truss's set of controlled processes. 249*7c478bd9Sstevel@tonic-gate * Return 3 if the process successfully opened another process 250*7c478bd9Sstevel@tonic-gate * in truss's set of controlled processes. 251*7c478bd9Sstevel@tonic-gate * We notify and wait for the other controlling truss process 252*7c478bd9Sstevel@tonic-gate * to terminate before returning in cases 2 and 3. 253*7c478bd9Sstevel@tonic-gate */ 254*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 255*7c478bd9Sstevel@tonic-gate int 256*7c478bd9Sstevel@tonic-gate checkproc(private_t *pri) 257*7c478bd9Sstevel@tonic-gate { 258*7c478bd9Sstevel@tonic-gate char *path = pri->sys_path; 259*7c478bd9Sstevel@tonic-gate const pstatus_t *Psp = Pstatus(Proc); 260*7c478bd9Sstevel@tonic-gate struct ps_lwphandle *Lwp = pri->Lwp; 261*7c478bd9Sstevel@tonic-gate const lwpstatus_t *Lsp = pri->lwpstat; 262*7c478bd9Sstevel@tonic-gate int what = Lsp->pr_what; /* SYS_open or SYS_open64 */ 263*7c478bd9Sstevel@tonic-gate int err = Lsp->pr_errno; 264*7c478bd9Sstevel@tonic-gate int pid; 265*7c478bd9Sstevel@tonic-gate int i; 266*7c478bd9Sstevel@tonic-gate const char *dirname; 267*7c478bd9Sstevel@tonic-gate char *next; 268*7c478bd9Sstevel@tonic-gate char *sp1; 269*7c478bd9Sstevel@tonic-gate char *sp2; 270*7c478bd9Sstevel@tonic-gate prgreg_t pc; 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate /* 273*7c478bd9Sstevel@tonic-gate * A bit heuristic ... 274*7c478bd9Sstevel@tonic-gate * Test for the cases: 275*7c478bd9Sstevel@tonic-gate * 1234 276*7c478bd9Sstevel@tonic-gate * 1234/as 277*7c478bd9Sstevel@tonic-gate * 1234/ctl 278*7c478bd9Sstevel@tonic-gate * 1234/lwp/24/lwpctl 279*7c478bd9Sstevel@tonic-gate * .../1234 280*7c478bd9Sstevel@tonic-gate * .../1234/as 281*7c478bd9Sstevel@tonic-gate * .../1234/ctl 282*7c478bd9Sstevel@tonic-gate * .../1234/lwp/24/lwpctl 283*7c478bd9Sstevel@tonic-gate * Insert a '\0', if necessary, so the path becomes ".../1234". 284*7c478bd9Sstevel@tonic-gate * 285*7c478bd9Sstevel@tonic-gate * Along the way, watch out for /proc/self and /proc/1234/lwp/agent 286*7c478bd9Sstevel@tonic-gate */ 287*7c478bd9Sstevel@tonic-gate if ((sp1 = strrchr(path, '/')) == NULL) /* last component */ 288*7c478bd9Sstevel@tonic-gate /* EMPTY */; 289*7c478bd9Sstevel@tonic-gate else if (isdigit(*(sp1+1))) { 290*7c478bd9Sstevel@tonic-gate sp1 += strlen(sp1); 291*7c478bd9Sstevel@tonic-gate while (--sp1 > path && isdigit(*sp1)) 292*7c478bd9Sstevel@tonic-gate ; 293*7c478bd9Sstevel@tonic-gate if (*sp1 != '/') 294*7c478bd9Sstevel@tonic-gate return (0); 295*7c478bd9Sstevel@tonic-gate } else if (strcmp(sp1+1, "as") == 0 || 296*7c478bd9Sstevel@tonic-gate strcmp(sp1+1, "ctl") == 0) { 297*7c478bd9Sstevel@tonic-gate *sp1 = '\0'; 298*7c478bd9Sstevel@tonic-gate } else if (strcmp(sp1+1, "lwpctl") == 0) { 299*7c478bd9Sstevel@tonic-gate /* 300*7c478bd9Sstevel@tonic-gate * .../1234/lwp/24/lwpctl 301*7c478bd9Sstevel@tonic-gate * ............ ^-- sp1 302*7c478bd9Sstevel@tonic-gate */ 303*7c478bd9Sstevel@tonic-gate if (sp1-6 >= path && strncmp(sp1-6, "/agent", 6) == 0) 304*7c478bd9Sstevel@tonic-gate sp1 -= 6; 305*7c478bd9Sstevel@tonic-gate else { 306*7c478bd9Sstevel@tonic-gate while (--sp1 > path && isdigit(*sp1)) 307*7c478bd9Sstevel@tonic-gate ; 308*7c478bd9Sstevel@tonic-gate } 309*7c478bd9Sstevel@tonic-gate if (*sp1 != '/' || 310*7c478bd9Sstevel@tonic-gate (sp1 -= 4) <= path || 311*7c478bd9Sstevel@tonic-gate strncmp(sp1, "/lwp", 4) != 0) 312*7c478bd9Sstevel@tonic-gate return (0); 313*7c478bd9Sstevel@tonic-gate *sp1 = '\0'; 314*7c478bd9Sstevel@tonic-gate } else if (strcmp(sp1+1, "self") != 0) { 315*7c478bd9Sstevel@tonic-gate return (0); 316*7c478bd9Sstevel@tonic-gate } 317*7c478bd9Sstevel@tonic-gate 318*7c478bd9Sstevel@tonic-gate if ((sp2 = strrchr(path, '/')) == NULL) 319*7c478bd9Sstevel@tonic-gate dirname = path; 320*7c478bd9Sstevel@tonic-gate else 321*7c478bd9Sstevel@tonic-gate dirname = sp2 + 1; 322*7c478bd9Sstevel@tonic-gate 323*7c478bd9Sstevel@tonic-gate if (strcmp(dirname, "self") == 0) { 324*7c478bd9Sstevel@tonic-gate pid = Psp->pr_pid; 325*7c478bd9Sstevel@tonic-gate } else if ((pid = strtol(dirname, &next, 10)) < 0 || 326*7c478bd9Sstevel@tonic-gate *next != '\0') { /* dirname not a number */ 327*7c478bd9Sstevel@tonic-gate if (sp1 != NULL) 328*7c478bd9Sstevel@tonic-gate *sp1 = '/'; 329*7c478bd9Sstevel@tonic-gate return (0); 330*7c478bd9Sstevel@tonic-gate } 331*7c478bd9Sstevel@tonic-gate if (sp2 == NULL) 332*7c478bd9Sstevel@tonic-gate dirname = "."; 333*7c478bd9Sstevel@tonic-gate else { 334*7c478bd9Sstevel@tonic-gate *sp2 = '\0'; 335*7c478bd9Sstevel@tonic-gate dirname = path; 336*7c478bd9Sstevel@tonic-gate } 337*7c478bd9Sstevel@tonic-gate 338*7c478bd9Sstevel@tonic-gate if (!Pisprocdir(Proc, dirname) || /* file not in a /proc directory */ 339*7c478bd9Sstevel@tonic-gate pid == getpid() || /* process opened truss's /proc file */ 340*7c478bd9Sstevel@tonic-gate pid == 0) { /* process opened process 0 */ 341*7c478bd9Sstevel@tonic-gate if (sp1 != NULL) 342*7c478bd9Sstevel@tonic-gate *sp1 = '/'; 343*7c478bd9Sstevel@tonic-gate if (sp2 != NULL) 344*7c478bd9Sstevel@tonic-gate *sp2 = '/'; 345*7c478bd9Sstevel@tonic-gate return (0); 346*7c478bd9Sstevel@tonic-gate } 347*7c478bd9Sstevel@tonic-gate if (sp1 != NULL) 348*7c478bd9Sstevel@tonic-gate *sp1 = '/'; 349*7c478bd9Sstevel@tonic-gate if (sp2 != NULL) 350*7c478bd9Sstevel@tonic-gate *sp2 = '/'; 351*7c478bd9Sstevel@tonic-gate 352*7c478bd9Sstevel@tonic-gate /* 353*7c478bd9Sstevel@tonic-gate * Process did open a /proc file --- 354*7c478bd9Sstevel@tonic-gate */ 355*7c478bd9Sstevel@tonic-gate if (pid == Psp->pr_pid) { /* process opened its own /proc file */ 356*7c478bd9Sstevel@tonic-gate /* 357*7c478bd9Sstevel@tonic-gate * In SunOS 5.6 and beyond, self-opens always succeed. 358*7c478bd9Sstevel@tonic-gate */ 359*7c478bd9Sstevel@tonic-gate return (1); 360*7c478bd9Sstevel@tonic-gate } 361*7c478bd9Sstevel@tonic-gate 362*7c478bd9Sstevel@tonic-gate /* 363*7c478bd9Sstevel@tonic-gate * Search for a matching pid in our set of controlled processes. 364*7c478bd9Sstevel@tonic-gate */ 365*7c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (gps->tpid)/sizeof (gps->tpid[0]); i++) { 366*7c478bd9Sstevel@tonic-gate if (gps->spid[i] == pid) { 367*7c478bd9Sstevel@tonic-gate pid = gps->tpid[i]; 368*7c478bd9Sstevel@tonic-gate break; 369*7c478bd9Sstevel@tonic-gate } 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate if (i >= sizeof (gps->tpid) / sizeof (gps->tpid[0])) { 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * The process opened a /proc file, but not one we care about. 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate return (0); 376*7c478bd9Sstevel@tonic-gate } 377*7c478bd9Sstevel@tonic-gate 378*7c478bd9Sstevel@tonic-gate /* 379*7c478bd9Sstevel@tonic-gate * Notify and wait for the controlling process to terminate. 380*7c478bd9Sstevel@tonic-gate */ 381*7c478bd9Sstevel@tonic-gate while (pid && gps->tpid[i] == pid) { 382*7c478bd9Sstevel@tonic-gate if (kill(pid, SIGUSR1) == -1) 383*7c478bd9Sstevel@tonic-gate break; 384*7c478bd9Sstevel@tonic-gate (void) usleep(1000000); 385*7c478bd9Sstevel@tonic-gate } 386*7c478bd9Sstevel@tonic-gate Ecritical(1); 387*7c478bd9Sstevel@tonic-gate if (gps->tpid[i] == 0) 388*7c478bd9Sstevel@tonic-gate gps->spid[i] = 0; 389*7c478bd9Sstevel@tonic-gate Xcritical(1); 390*7c478bd9Sstevel@tonic-gate 391*7c478bd9Sstevel@tonic-gate if (err) { /* prepare to reissue the failed open() system call */ 392*7c478bd9Sstevel@tonic-gate #if defined(__sparc) 393*7c478bd9Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 394*7c478bd9Sstevel@tonic-gate if (pri->sys_indirect) { 395*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_G1, (prgreg_t)SYS_syscall); 396*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_O0, (prgreg_t)what); 397*7c478bd9Sstevel@tonic-gate for (i = 0; i < 5; i++) 398*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_O1+i, pri->sys_args[i]); 399*7c478bd9Sstevel@tonic-gate } else { 400*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_G1, (prgreg_t)what); 401*7c478bd9Sstevel@tonic-gate for (i = 0; i < 6; i++) 402*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_O0+i, pri->sys_args[i]); 403*7c478bd9Sstevel@tonic-gate } 404*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_nPC, pc); 405*7c478bd9Sstevel@tonic-gate #elif defined(__amd64) 406*7c478bd9Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 407*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, REG_RAX, (prgreg_t)what); 408*7c478bd9Sstevel@tonic-gate #elif defined(__i386) 409*7c478bd9Sstevel@tonic-gate (void) Lgetareg(Lwp, R_PC, &pc); 410*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, EAX, (prgreg_t)what); 411*7c478bd9Sstevel@tonic-gate #else 412*7c478bd9Sstevel@tonic-gate #error "unrecognized architecture" 413*7c478bd9Sstevel@tonic-gate #endif 414*7c478bd9Sstevel@tonic-gate (void) Pissyscall_prev(Proc, pc, (uintptr_t *)&pc); 415*7c478bd9Sstevel@tonic-gate (void) Lputareg(Lwp, R_PC, pc); 416*7c478bd9Sstevel@tonic-gate return (2); 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate return (3); 420*7c478bd9Sstevel@tonic-gate } 421