10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*2528Svb160487 * Common Development and Distribution License (the "License").
6*2528Svb160487 * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*2528Svb160487 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23*2528Svb160487 * Use is subject to license terms.
240Sstevel@tonic-gate */
250Sstevel@tonic-gate
260Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
270Sstevel@tonic-gate
280Sstevel@tonic-gate #include <stdio.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <unistd.h>
310Sstevel@tonic-gate #include <fcntl.h>
320Sstevel@tonic-gate #include <string.h>
330Sstevel@tonic-gate #include <errno.h>
340Sstevel@tonic-gate #include <sys/types.h>
350Sstevel@tonic-gate #include <signal.h>
360Sstevel@tonic-gate #include <libproc.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate static int stop(char *);
39*2528Svb160487 static int lwpstop(int *, const lwpstatus_t *, const lwpsinfo_t *);
400Sstevel@tonic-gate
410Sstevel@tonic-gate static char *command;
42*2528Svb160487 static const char *lwps;
43*2528Svb160487 static struct ps_prochandle *P;
440Sstevel@tonic-gate
450Sstevel@tonic-gate int
main(int argc,char ** argv)460Sstevel@tonic-gate main(int argc, char **argv)
470Sstevel@tonic-gate {
480Sstevel@tonic-gate int rc = 0;
490Sstevel@tonic-gate
500Sstevel@tonic-gate if ((command = strrchr(argv[0], '/')) != NULL)
510Sstevel@tonic-gate command++;
520Sstevel@tonic-gate else
530Sstevel@tonic-gate command = argv[0];
540Sstevel@tonic-gate
550Sstevel@tonic-gate if (argc <= 1) {
56*2528Svb160487 (void) fprintf(stderr, "usage:\t%s pid[/lwps] ...\n", command);
570Sstevel@tonic-gate (void) fprintf(stderr,
58*2528Svb160487 " (stop processes or lwps with /proc request)\n");
590Sstevel@tonic-gate return (2);
600Sstevel@tonic-gate }
610Sstevel@tonic-gate
620Sstevel@tonic-gate while (--argc > 0)
630Sstevel@tonic-gate rc += stop(*++argv);
640Sstevel@tonic-gate
650Sstevel@tonic-gate return (rc);
660Sstevel@tonic-gate }
670Sstevel@tonic-gate
680Sstevel@tonic-gate static int
stop(char * arg)690Sstevel@tonic-gate stop(char *arg)
700Sstevel@tonic-gate {
71*2528Svb160487 int gcode;
72*2528Svb160487 int rc = 0;
730Sstevel@tonic-gate
74*2528Svb160487 if ((P = proc_arg_xgrab(arg, NULL, PR_ARG_PIDS, PGRAB_RETAIN |
75*2528Svb160487 PGRAB_NOSTOP | PGRAB_FORCE, &gcode, &lwps)) == NULL) {
760Sstevel@tonic-gate (void) fprintf(stderr, "%s: cannot control %s: %s\n",
77*2528Svb160487 command, arg, Pgrab_error(gcode));
780Sstevel@tonic-gate return (1);
79*2528Svb160487 } else if (lwps != NULL) {
80*2528Svb160487 /*
81*2528Svb160487 * The user has provided an lwp specification. Let's consider
82*2528Svb160487 * the lwp specification as a mask. We iterate over all lwps in
83*2528Svb160487 * the process and stop every lwp, which matches the mask. If
84*2528Svb160487 * there is no lwp matching the mask or an error occured during
85*2528Svb160487 * the iteration, set the return code to 1 as indication of an
86*2528Svb160487 * error.
87*2528Svb160487 */
88*2528Svb160487 int lwpcount = 0;
89*2528Svb160487
90*2528Svb160487 (void) Plwp_iter_all(P, (proc_lwp_all_f *)lwpstop, &lwpcount);
91*2528Svb160487 if (lwpcount == 0) {
92*2528Svb160487 (void) fprintf(stderr, "%s: cannot control %s:"
93*2528Svb160487 " no matching LWPs found\n", command, arg);
94*2528Svb160487 rc = 1;
95*2528Svb160487 } else if (lwpcount == -1)
96*2528Svb160487 rc = 1;
97*2528Svb160487 } else {
98*2528Svb160487 (void) Pdstop(P); /* Stop the process. */
990Sstevel@tonic-gate }
1000Sstevel@tonic-gate
101*2528Svb160487 /*
102*2528Svb160487 * Prelease could change the tracing flags, use Pfree and unset
103*2528Svb160487 * run-on-last-close flag to prevent the process being set running
104*2528Svb160487 * after detaching from it.
105*2528Svb160487 */
106*2528Svb160487 (void) Punsetflags(P, PR_RLC);
107*2528Svb160487 Pfree(P);
108*2528Svb160487 return (rc);
1090Sstevel@tonic-gate }
1100Sstevel@tonic-gate
111*2528Svb160487 /* ARGSUSED */
1120Sstevel@tonic-gate static int
lwpstop(int * lwpcount,const lwpstatus_t * status,const lwpsinfo_t * info)113*2528Svb160487 lwpstop(int *lwpcount, const lwpstatus_t *status, const lwpsinfo_t *info)
1140Sstevel@tonic-gate {
115*2528Svb160487 struct ps_lwphandle *L;
116*2528Svb160487 int gcode;
117*2528Svb160487
118*2528Svb160487 if (proc_lwp_in_set(lwps, info->pr_lwpid)) {
119*2528Svb160487 /*
120*2528Svb160487 * There is a race between the callback from the iterator and
121*2528Svb160487 * grabbing of the lwp. If the lwp has already exited, Lgrab
122*2528Svb160487 * will return the error code G_NOPROC. It's not a real error,
123*2528Svb160487 * only if there is no lwp matching the specification.
124*2528Svb160487 */
125*2528Svb160487 if ((L = Lgrab(P, info->pr_lwpid, &gcode)) != NULL) {
126*2528Svb160487 (void) Ldstop(L);
127*2528Svb160487 Lfree(L);
128*2528Svb160487 if (*lwpcount >= 0)
129*2528Svb160487 (*lwpcount)++;
130*2528Svb160487 } else if (gcode != G_NOPROC) {
131*2528Svb160487 (void) fprintf(stderr, "%s: cannot control %d/%d: %s\n",
132*2528Svb160487 command, (int)Pstatus(P)->pr_pid,
133*2528Svb160487 (int)info->pr_lwpid, Lgrab_error(gcode));
134*2528Svb160487 *lwpcount = -1;
135*2528Svb160487 }
136*2528Svb160487 }
137*2528Svb160487 return (0);
1380Sstevel@tonic-gate }
139