xref: /onnv-gate/usr/src/cmd/psrset/psrset.c (revision 10089:3b42b78e6a26)
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*10089SSurya.Prakki@Sun.COM  * Common Development and Distribution License (the "License").
6*10089SSurya.Prakki@Sun.COM  * 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*10089SSurya.Prakki@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * psrset - create and manage processor sets
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <sys/procset.h>
320Sstevel@tonic-gate #include <sys/processor.h>
330Sstevel@tonic-gate #include <sys/pset.h>
340Sstevel@tonic-gate #include <fcntl.h>
350Sstevel@tonic-gate #include <stdio.h>
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <dirent.h>
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <limits.h>
410Sstevel@tonic-gate #include <procfs.h>
420Sstevel@tonic-gate #include <libproc.h>
430Sstevel@tonic-gate #include <stdarg.h>
440Sstevel@tonic-gate 
450Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)		/* should be defined by cc -D */
460Sstevel@tonic-gate #define	TEXT_DOMAIN 	"SYS_TEST"	/* Use this only if it wasn't */
470Sstevel@tonic-gate #endif
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #define	MAX_PROCFS_PATH	80
500Sstevel@tonic-gate 
510Sstevel@tonic-gate #define	ERR_OK		0		/* exit status for success */
520Sstevel@tonic-gate #define	ERR_FAIL	1		/* exit status for errors */
530Sstevel@tonic-gate #define	ERR_USAGE	2		/* exit status for usage errors */
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static char *progname;
560Sstevel@tonic-gate static int errors;
570Sstevel@tonic-gate static char cflag;
580Sstevel@tonic-gate static char dflag;
590Sstevel@tonic-gate static char aflag;
600Sstevel@tonic-gate static char rflag;
610Sstevel@tonic-gate static char iflag;
620Sstevel@tonic-gate static char bflag;
630Sstevel@tonic-gate static char uflag;
640Sstevel@tonic-gate static char Uflag;
650Sstevel@tonic-gate static char qflag;
660Sstevel@tonic-gate static char Qflag;
670Sstevel@tonic-gate static char pflag;
680Sstevel@tonic-gate static char nflag;
690Sstevel@tonic-gate static char fflag;
700Sstevel@tonic-gate static char Fflag;
710Sstevel@tonic-gate static char eflag;
720Sstevel@tonic-gate 
730Sstevel@tonic-gate extern int pset_assign_forced(psetid_t, processorid_t, psetid_t *);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate /*PRINTFLIKE1*/
760Sstevel@tonic-gate static void
warn(char * format,...)770Sstevel@tonic-gate warn(char *format, ...)
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	int err = errno;
800Sstevel@tonic-gate 	va_list alist;
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", progname);
830Sstevel@tonic-gate 	va_start(alist, format);
840Sstevel@tonic-gate 	(void) vfprintf(stderr, format, alist);
850Sstevel@tonic-gate 	va_end(alist);
860Sstevel@tonic-gate 	if (strchr(format, '\n') == NULL)
870Sstevel@tonic-gate 		(void) fprintf(stderr, ": %s\n", strerror(err));
880Sstevel@tonic-gate }
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /*PRINTFLIKE1*/
910Sstevel@tonic-gate static void
die(char * format,...)920Sstevel@tonic-gate die(char *format, ...)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate 	int err = errno;
950Sstevel@tonic-gate 	va_list alist;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	(void) fprintf(stderr, "%s: ", progname);
980Sstevel@tonic-gate 	va_start(alist, format);
990Sstevel@tonic-gate 	(void) vfprintf(stderr, format, alist);
1000Sstevel@tonic-gate 	va_end(alist);
1010Sstevel@tonic-gate 	if (strchr(format, '\n') == NULL)
1020Sstevel@tonic-gate 		(void) fprintf(stderr, ": %s\n", strerror(err));
1030Sstevel@tonic-gate 	exit(ERR_FAIL);
1040Sstevel@tonic-gate }
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate static struct ps_prochandle *
grab_proc(id_t pid)1070Sstevel@tonic-gate grab_proc(id_t pid)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 	int ret;
1100Sstevel@tonic-gate 	struct ps_prochandle *Pr;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	if ((Pr = Pgrab(pid, 0, &ret)) == NULL) {
1130Sstevel@tonic-gate 		warn(gettext("cannot control process %d: %s\n"),
1140Sstevel@tonic-gate 		    (int)pid, Pgrab_error(ret));
1150Sstevel@tonic-gate 		errors = ERR_FAIL;
1160Sstevel@tonic-gate 		return (NULL);
1170Sstevel@tonic-gate 	}
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	return (Pr);
1200Sstevel@tonic-gate }
1210Sstevel@tonic-gate 
1220Sstevel@tonic-gate static void
rele_proc(struct ps_prochandle * Pr)1230Sstevel@tonic-gate rele_proc(struct ps_prochandle *Pr)
1240Sstevel@tonic-gate {
1250Sstevel@tonic-gate 	if (Pr == NULL)
1260Sstevel@tonic-gate 		return;
1270Sstevel@tonic-gate 	Prelease(Pr, 0);
1280Sstevel@tonic-gate }
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate static void
bind_err(psetid_t pset,id_t pid,id_t lwpid,int err)1310Sstevel@tonic-gate bind_err(psetid_t pset, id_t pid, id_t lwpid, int err)
1320Sstevel@tonic-gate {
1330Sstevel@tonic-gate 	char    *msg;
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	switch (pset) {
1360Sstevel@tonic-gate 	case PS_NONE:
1370Sstevel@tonic-gate 		msg = gettext("unbind");
1380Sstevel@tonic-gate 		break;
1390Sstevel@tonic-gate 	case PS_QUERY:
1400Sstevel@tonic-gate 		msg = gettext("query");
1410Sstevel@tonic-gate 		break;
1420Sstevel@tonic-gate 	default:
1430Sstevel@tonic-gate 		msg = gettext("bind");
1440Sstevel@tonic-gate 		break;
1450Sstevel@tonic-gate 	}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 	errno = err;
1480Sstevel@tonic-gate 	if (lwpid == -1)
1490Sstevel@tonic-gate 		warn(gettext("cannot %s pid %d"), msg, pid);
1500Sstevel@tonic-gate 	else
1510Sstevel@tonic-gate 		warn(gettext("cannot %s lwpid %d/%d"), msg, pid, lwpid);
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate  * Output for create.
1560Sstevel@tonic-gate  */
1570Sstevel@tonic-gate static void
create_out(psetid_t pset)1580Sstevel@tonic-gate create_out(psetid_t pset)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	(void) printf("%s %d\n", gettext("created processor set"), pset);
1610Sstevel@tonic-gate }
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate /*
1640Sstevel@tonic-gate  * Output for assign.
1650Sstevel@tonic-gate  */
1660Sstevel@tonic-gate static void
assign_out(processorid_t cpu,psetid_t old,psetid_t new)1670Sstevel@tonic-gate assign_out(processorid_t cpu, psetid_t old, psetid_t new)
1680Sstevel@tonic-gate {
1690Sstevel@tonic-gate 	if (old == PS_NONE) {
1700Sstevel@tonic-gate 		if (new == PS_NONE)
1710Sstevel@tonic-gate 			(void) printf(gettext("processor %d: was not assigned,"
1720Sstevel@tonic-gate 			    " now not assigned\n"), cpu);
1730Sstevel@tonic-gate 		else
1740Sstevel@tonic-gate 			(void) printf(gettext("processor %d: was not assigned,"
1750Sstevel@tonic-gate 			    " now %d\n"), cpu, new);
1760Sstevel@tonic-gate 	} else {
1770Sstevel@tonic-gate 		if (new == PS_NONE)
1780Sstevel@tonic-gate 			(void) printf(gettext("processor %d: was %d, "
1790Sstevel@tonic-gate 			    "now not assigned\n"), cpu, old);
1800Sstevel@tonic-gate 		else
1810Sstevel@tonic-gate 			(void) printf(gettext("processor %d: was %d, "
1820Sstevel@tonic-gate 			    "now %d\n"), cpu, old, new);
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate }
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate /*
1870Sstevel@tonic-gate  * Output for query.
1880Sstevel@tonic-gate  */
1890Sstevel@tonic-gate static void
query_out(id_t pid,id_t lwpid,psetid_t pset)1900Sstevel@tonic-gate query_out(id_t pid, id_t lwpid, psetid_t pset)
1910Sstevel@tonic-gate {
1920Sstevel@tonic-gate 	char *proclwp;
1930Sstevel@tonic-gate 	char pidstr[21];
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	if (lwpid == -1) {
1960Sstevel@tonic-gate 		(void) snprintf(pidstr, 20, "%d", pid);
1970Sstevel@tonic-gate 		proclwp = "process";
1980Sstevel@tonic-gate 	} else {
1990Sstevel@tonic-gate 		(void) snprintf(pidstr, 20, "%d/%d", pid, lwpid);
2000Sstevel@tonic-gate 		proclwp = "lwp";
2010Sstevel@tonic-gate 	}
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 	if (pset == PS_NONE)
2040Sstevel@tonic-gate 		(void) printf(gettext("%s id %s: not bound\n"),
2050Sstevel@tonic-gate 		    proclwp, pidstr);
2060Sstevel@tonic-gate 	else
2070Sstevel@tonic-gate 		(void) printf(gettext("%s id %s: %d\n"), proclwp, pidstr, pset);
2080Sstevel@tonic-gate }
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate  * Output for info.
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate static void
info_out(psetid_t pset,int type,uint_t numcpus,processorid_t * cpus)2140Sstevel@tonic-gate info_out(psetid_t pset, int type, uint_t numcpus, processorid_t *cpus)
2150Sstevel@tonic-gate {
2160Sstevel@tonic-gate 	int i;
2170Sstevel@tonic-gate 	if (type == PS_SYSTEM)
2180Sstevel@tonic-gate 		(void) printf(gettext("system processor set %d:"), pset);
2190Sstevel@tonic-gate 	else
2200Sstevel@tonic-gate 		(void) printf(gettext("user processor set %d:"), pset);
2210Sstevel@tonic-gate 	if (numcpus == 0)
2220Sstevel@tonic-gate 		(void) printf(gettext(" empty"));
2230Sstevel@tonic-gate 	else if (numcpus > 1)
2240Sstevel@tonic-gate 		(void) printf(gettext(" processors"));
2250Sstevel@tonic-gate 	else
2260Sstevel@tonic-gate 		(void) printf(gettext(" processor"));
2270Sstevel@tonic-gate 	for (i = 0; i < numcpus; i++)
2280Sstevel@tonic-gate 		(void) printf(" %d", cpus[i]);
2290Sstevel@tonic-gate 	(void) printf("\n");
2300Sstevel@tonic-gate }
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate /*
2330Sstevel@tonic-gate  * Output for print.
2340Sstevel@tonic-gate  */
2350Sstevel@tonic-gate static void
print_out(processorid_t cpu,psetid_t pset)2360Sstevel@tonic-gate print_out(processorid_t cpu, psetid_t pset)
2370Sstevel@tonic-gate {
2380Sstevel@tonic-gate 	if (pset == PS_NONE)
2390Sstevel@tonic-gate 		(void) printf(gettext("processor %d: not assigned\n"), cpu);
2400Sstevel@tonic-gate 	else
2410Sstevel@tonic-gate 		(void) printf(gettext("processor %d: %d\n"), cpu, pset);
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate /*
2450Sstevel@tonic-gate  * Output for bind.
2460Sstevel@tonic-gate  */
2470Sstevel@tonic-gate static void
bind_out(id_t pid,id_t lwpid,psetid_t old,psetid_t new)2480Sstevel@tonic-gate bind_out(id_t pid, id_t lwpid, psetid_t old, psetid_t new)
2490Sstevel@tonic-gate {
2500Sstevel@tonic-gate 	char *proclwp;
2510Sstevel@tonic-gate 	char pidstr[21];
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	if (lwpid == -1) {
2540Sstevel@tonic-gate 		(void) snprintf(pidstr, 20, "%d", pid);
2550Sstevel@tonic-gate 		proclwp = "process";
2560Sstevel@tonic-gate 	} else {
2570Sstevel@tonic-gate 		(void) snprintf(pidstr, 20, "%d/%d", pid, lwpid);
2580Sstevel@tonic-gate 		proclwp = "lwp";
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	if (old == PS_NONE) {
2620Sstevel@tonic-gate 		if (new == PS_NONE)
2630Sstevel@tonic-gate 			(void) printf(gettext("%s id %s: was not bound, "
264*10089SSurya.Prakki@Sun.COM 			    "now not bound\n"), proclwp, pidstr);
2650Sstevel@tonic-gate 		else
2660Sstevel@tonic-gate 			(void) printf(gettext("%s id %s: was not bound, "
267*10089SSurya.Prakki@Sun.COM 			    "now %d\n"), proclwp, pidstr, new);
2680Sstevel@tonic-gate 	} else {
2690Sstevel@tonic-gate 		if (new == PS_NONE)
2700Sstevel@tonic-gate 			(void) printf(gettext("%s id %s: was %d, "
271*10089SSurya.Prakki@Sun.COM 			    "now not bound\n"), proclwp, pidstr, old);
2720Sstevel@tonic-gate 		else
2730Sstevel@tonic-gate 			(void) printf(gettext("%s id %s: was %d, "
274*10089SSurya.Prakki@Sun.COM 			    "now %d\n"), proclwp, pidstr, old, new);
2750Sstevel@tonic-gate 	}
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate 
2780Sstevel@tonic-gate static void
bind_lwp(id_t pid,id_t lwpid,psetid_t pset)279*10089SSurya.Prakki@Sun.COM bind_lwp(id_t pid, id_t lwpid, psetid_t pset)
2800Sstevel@tonic-gate {
2810Sstevel@tonic-gate 	psetid_t old_pset;
2820Sstevel@tonic-gate 
283*10089SSurya.Prakki@Sun.COM 	if (pset_bind_lwp(pset, lwpid, pid, &old_pset) != 0) {
2840Sstevel@tonic-gate 		bind_err(pset, pid, lwpid, errno);
2850Sstevel@tonic-gate 		errors = ERR_FAIL;
286*10089SSurya.Prakki@Sun.COM 	}
287*10089SSurya.Prakki@Sun.COM 	if (errors != ERR_FAIL) {
2880Sstevel@tonic-gate 		if (qflag)
2890Sstevel@tonic-gate 			query_out(pid, lwpid, old_pset);
2900Sstevel@tonic-gate 		else
2910Sstevel@tonic-gate 			bind_out(pid, lwpid, old_pset, pset);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate }
2940Sstevel@tonic-gate 
2950Sstevel@tonic-gate static int
do_cpu(psetid_t pset,processorid_t cpu,int print,int mustexist)2960Sstevel@tonic-gate do_cpu(psetid_t pset, processorid_t cpu, int print, int mustexist)
2970Sstevel@tonic-gate {
2980Sstevel@tonic-gate 	psetid_t old_pset;
2990Sstevel@tonic-gate 	int err;
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if ((!Fflag && pset_assign(pset, cpu, &old_pset) != 0) ||
3020Sstevel@tonic-gate 	    (Fflag && pset_assign_forced(pset, cpu, &old_pset) != 0)) {
3030Sstevel@tonic-gate 		if (errno == EINVAL && !mustexist)
3040Sstevel@tonic-gate 			return (EINVAL);
3050Sstevel@tonic-gate 		err = errno;
3060Sstevel@tonic-gate 
3070Sstevel@tonic-gate 		switch (pset) {
3080Sstevel@tonic-gate 		case PS_NONE:
3090Sstevel@tonic-gate 			warn(gettext("cannot remove processor %d"), cpu);
3100Sstevel@tonic-gate 			break;
3110Sstevel@tonic-gate 		case PS_QUERY:
3120Sstevel@tonic-gate 			warn(gettext("cannot query processor %d"), cpu);
3130Sstevel@tonic-gate 			break;
3140Sstevel@tonic-gate 		default:
3150Sstevel@tonic-gate 			warn(gettext("cannot assign processor %d"), cpu);
3160Sstevel@tonic-gate 			break;
3170Sstevel@tonic-gate 		}
3180Sstevel@tonic-gate 		return (err);
3190Sstevel@tonic-gate 	}
3200Sstevel@tonic-gate 	if (print)
3210Sstevel@tonic-gate 		print_out(cpu, old_pset);
3220Sstevel@tonic-gate 	else
3230Sstevel@tonic-gate 		assign_out(cpu, old_pset, pset);
3240Sstevel@tonic-gate 	return (0);
3250Sstevel@tonic-gate }
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate static int
do_range(psetid_t pset,processorid_t first,processorid_t last,int print)3280Sstevel@tonic-gate do_range(psetid_t pset, processorid_t first, processorid_t last, int print)
3290Sstevel@tonic-gate {
3300Sstevel@tonic-gate 	processorid_t cpu;
3310Sstevel@tonic-gate 	int error = ERR_OK;
3320Sstevel@tonic-gate 	int err;
3330Sstevel@tonic-gate 	int found_one = 0;
3340Sstevel@tonic-gate 
3350Sstevel@tonic-gate 	for (cpu = first; cpu <= last; cpu++) {
3360Sstevel@tonic-gate 		if ((err = do_cpu(pset, cpu, print, 0)) == 0)
3370Sstevel@tonic-gate 			found_one = 1;
3380Sstevel@tonic-gate 		else if (err != EINVAL)
3390Sstevel@tonic-gate 			error = ERR_FAIL;
3400Sstevel@tonic-gate 	}
3410Sstevel@tonic-gate 	if (!found_one && error == ERR_OK) {
3420Sstevel@tonic-gate 		warn(gettext("no processors in range %d-%d\n"), first, last);
3430Sstevel@tonic-gate 		error = ERR_FAIL;
3440Sstevel@tonic-gate 	}
3450Sstevel@tonic-gate 	return (error);
3460Sstevel@tonic-gate }
3470Sstevel@tonic-gate 
3480Sstevel@tonic-gate static int
do_info(psetid_t pset)3490Sstevel@tonic-gate do_info(psetid_t pset)
3500Sstevel@tonic-gate {
3510Sstevel@tonic-gate 	int	type;
3520Sstevel@tonic-gate 	uint_t	numcpus;
3530Sstevel@tonic-gate 	processorid_t	*cpus;
3540Sstevel@tonic-gate 
3550Sstevel@tonic-gate 	numcpus = (uint_t)sysconf(_SC_NPROCESSORS_MAX);
3560Sstevel@tonic-gate 	cpus = (processorid_t *)
3570Sstevel@tonic-gate 	    malloc(numcpus * sizeof (processorid_t));
3580Sstevel@tonic-gate 	if (cpus == NULL) {
3590Sstevel@tonic-gate 		warn(gettext("memory allocation failed"));
3600Sstevel@tonic-gate 		return (ERR_FAIL);
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 	if (pset_info(pset, &type, &numcpus, cpus) != 0) {
3630Sstevel@tonic-gate 		warn(gettext("cannot get info for processor set %d"), pset);
3640Sstevel@tonic-gate 		free(cpus);
3650Sstevel@tonic-gate 		return (ERR_FAIL);
3660Sstevel@tonic-gate 	}
3670Sstevel@tonic-gate 	info_out(pset, type, numcpus, cpus);
3680Sstevel@tonic-gate 	free(cpus);
3690Sstevel@tonic-gate 	return (ERR_OK);
3700Sstevel@tonic-gate }
3710Sstevel@tonic-gate 
3720Sstevel@tonic-gate static int
do_destroy(psetid_t pset)3730Sstevel@tonic-gate do_destroy(psetid_t pset)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 	if (pset_destroy(pset) != 0) {
3760Sstevel@tonic-gate 		warn(gettext("could not remove processor set %d"), pset);
3770Sstevel@tonic-gate 		return (ERR_FAIL);
3780Sstevel@tonic-gate 	}
3790Sstevel@tonic-gate 	(void) printf(gettext("removed processor set %d\n"), pset);
3800Sstevel@tonic-gate 	return (ERR_OK);
3810Sstevel@tonic-gate }
3820Sstevel@tonic-gate 
3830Sstevel@tonic-gate static int
do_intr(psetid_t pset,int flag)3840Sstevel@tonic-gate do_intr(psetid_t pset, int flag)
3850Sstevel@tonic-gate {
3860Sstevel@tonic-gate 	uint_t i, numcpus;
3870Sstevel@tonic-gate 	processorid_t *cpus;
3880Sstevel@tonic-gate 	int error = ERR_OK;
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 	numcpus = (uint_t)sysconf(_SC_NPROCESSORS_MAX);
3910Sstevel@tonic-gate 	cpus = (processorid_t *)
3920Sstevel@tonic-gate 	    malloc(numcpus * sizeof (processorid_t));
3930Sstevel@tonic-gate 	if (cpus == NULL) {
3940Sstevel@tonic-gate 		warn(gettext("memory allocation failed"));
3950Sstevel@tonic-gate 		return (ERR_FAIL);
3960Sstevel@tonic-gate 	}
3970Sstevel@tonic-gate 	if (pset_info(pset, NULL, &numcpus, cpus) != 0) {
3980Sstevel@tonic-gate 		warn(gettext(
3990Sstevel@tonic-gate 		    "cannot set interrupt status for processor set %d"), pset);
4000Sstevel@tonic-gate 		free(cpus);
4010Sstevel@tonic-gate 		return (ERR_FAIL);
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 	for (i = 0; i < numcpus; i++) {
4040Sstevel@tonic-gate 		int status = p_online(cpus[i], P_STATUS);
4050Sstevel@tonic-gate 		if (status != P_OFFLINE && status != P_POWEROFF &&
4060Sstevel@tonic-gate 		    status != flag) {
4070Sstevel@tonic-gate 			if (p_online(cpus[i], flag) == -1) {
4080Sstevel@tonic-gate 				warn(gettext("processor %d"), cpus[i]);
4090Sstevel@tonic-gate 				error = ERR_FAIL;
4100Sstevel@tonic-gate 			}
4110Sstevel@tonic-gate 		}
4120Sstevel@tonic-gate 	}
4130Sstevel@tonic-gate 	free(cpus);
4140Sstevel@tonic-gate 	return (error);
4150Sstevel@tonic-gate }
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate /*
4180Sstevel@tonic-gate  * Query the type and CPUs for all active processor sets in the system.
4190Sstevel@tonic-gate  */
4200Sstevel@tonic-gate static int
info_all(void)4210Sstevel@tonic-gate info_all(void)
4220Sstevel@tonic-gate {
4230Sstevel@tonic-gate 	psetid_t *psetlist;
4240Sstevel@tonic-gate 	uint_t	npsets, oldnpsets;
4250Sstevel@tonic-gate 	int	i;
4260Sstevel@tonic-gate 	int	errors = ERR_OK;
4270Sstevel@tonic-gate 
4280Sstevel@tonic-gate 	if (pset_list(NULL, &npsets) != 0) {
4290Sstevel@tonic-gate 		warn(gettext("cannot get number of processor sets"));
4300Sstevel@tonic-gate 		return (1);
4310Sstevel@tonic-gate 	}
4320Sstevel@tonic-gate 	for (;;) {
4330Sstevel@tonic-gate 		psetlist = malloc(sizeof (psetid_t) * npsets);
4340Sstevel@tonic-gate 		if (psetlist == NULL) {
4350Sstevel@tonic-gate 			warn(gettext("memory allocation failed"));
4360Sstevel@tonic-gate 			return (ERR_FAIL);
4370Sstevel@tonic-gate 		}
4380Sstevel@tonic-gate 		oldnpsets = npsets;
4390Sstevel@tonic-gate 		if (pset_list(psetlist, &npsets) != 0) {
4400Sstevel@tonic-gate 			warn(gettext("cannot get list of processor sets"));
4410Sstevel@tonic-gate 			free(psetlist);
4420Sstevel@tonic-gate 			return (ERR_FAIL);
4430Sstevel@tonic-gate 		}
4440Sstevel@tonic-gate 		if (npsets <= oldnpsets)
4450Sstevel@tonic-gate 			break;
4460Sstevel@tonic-gate 		free(psetlist);
4470Sstevel@tonic-gate 	}
4480Sstevel@tonic-gate 
4490Sstevel@tonic-gate 	for (i = 0; i < npsets; i++) {
4500Sstevel@tonic-gate 		if (do_info(psetlist[i]))
4510Sstevel@tonic-gate 			errors = ERR_FAIL;
4520Sstevel@tonic-gate 	}
4530Sstevel@tonic-gate 	free(psetlist);
4540Sstevel@tonic-gate 	return (errors);
4550Sstevel@tonic-gate }
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate /*
4580Sstevel@tonic-gate  * Query the processor set assignments for all CPUs in the system.
4590Sstevel@tonic-gate  */
4600Sstevel@tonic-gate static int
print_all(void)4610Sstevel@tonic-gate print_all(void)
4620Sstevel@tonic-gate {
4630Sstevel@tonic-gate 	psetid_t	pset;
4640Sstevel@tonic-gate 	processorid_t cpuid, max_cpuid;
4650Sstevel@tonic-gate 	int	errors = ERR_OK;
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	max_cpuid = (processorid_t)sysconf(_SC_CPUID_MAX);
4680Sstevel@tonic-gate 	for (cpuid = 0; cpuid <= max_cpuid; cpuid++) {
4690Sstevel@tonic-gate 		if (pset_assign(PS_QUERY, cpuid, &pset) == 0) {
4700Sstevel@tonic-gate 			if (pset != PS_NONE)
4710Sstevel@tonic-gate 				print_out(cpuid, pset);
4720Sstevel@tonic-gate 		} else if (errno != EINVAL) {
4730Sstevel@tonic-gate 			warn(gettext("cannot query processor %d"), cpuid);
4740Sstevel@tonic-gate 			errors = ERR_FAIL;
4750Sstevel@tonic-gate 		}
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 	return (errors);
4780Sstevel@tonic-gate }
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate /*ARGSUSED*/
4810Sstevel@tonic-gate static int
query_all_proc(psinfo_t * psinfo,lwpsinfo_t * lwpsinfo,void * arg)4820Sstevel@tonic-gate query_all_proc(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg)
4830Sstevel@tonic-gate {
4840Sstevel@tonic-gate 	id_t pid = psinfo->pr_pid;
4850Sstevel@tonic-gate 	psetid_t binding;
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (pset_bind(PS_QUERY, P_PID, pid, &binding) < 0) {
4880Sstevel@tonic-gate 		/*
4890Sstevel@tonic-gate 		 * Ignore search errors.  The process may have exited
4900Sstevel@tonic-gate 		 * since we read the directory.
4910Sstevel@tonic-gate 		 */
4920Sstevel@tonic-gate 		if (errno == ESRCH)
4930Sstevel@tonic-gate 			return (0);
4940Sstevel@tonic-gate 		bind_err(PS_QUERY, pid, -1, errno);
4950Sstevel@tonic-gate 		errors = ERR_FAIL;
4960Sstevel@tonic-gate 		return (0);
4970Sstevel@tonic-gate 	}
4980Sstevel@tonic-gate 	if (binding != PS_NONE)
4990Sstevel@tonic-gate 		query_out(pid, -1, binding);
5000Sstevel@tonic-gate 	return (0);
5010Sstevel@tonic-gate }
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate static int
query_all_lwp(psinfo_t * psinfo,lwpsinfo_t * lwpsinfo,void * arg)5040Sstevel@tonic-gate query_all_lwp(psinfo_t *psinfo, lwpsinfo_t *lwpsinfo, void *arg)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate 	id_t pid = psinfo->pr_pid;
5070Sstevel@tonic-gate 	id_t lwpid = lwpsinfo->pr_lwpid;
5080Sstevel@tonic-gate 	psetid_t *cpuid = arg;
5090Sstevel@tonic-gate 	psetid_t binding = lwpsinfo->pr_bindpset;
5100Sstevel@tonic-gate 
5110Sstevel@tonic-gate 	if (psinfo->pr_nlwp == 1)
5120Sstevel@tonic-gate 		lwpid = -1;	/* report process bindings if only 1 lwp */
5130Sstevel@tonic-gate 	if ((cpuid != NULL && *cpuid == binding) ||
5140Sstevel@tonic-gate 	    (cpuid == NULL && binding != PBIND_NONE))
5150Sstevel@tonic-gate 		query_out(pid, lwpid, binding);
5160Sstevel@tonic-gate 	return (0);
5170Sstevel@tonic-gate }
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate void
exec_cmd(psetid_t pset,char ** argv)5200Sstevel@tonic-gate exec_cmd(psetid_t pset, char **argv)
5210Sstevel@tonic-gate {
5220Sstevel@tonic-gate 	if (pset_bind(pset, P_PID, P_MYID, NULL) != 0) {
5230Sstevel@tonic-gate 		warn(gettext("cannot exec in processor set %d"), pset);
5240Sstevel@tonic-gate 		return;
5250Sstevel@tonic-gate 	}
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	(void) execvp(argv[0], argv);
5280Sstevel@tonic-gate 	warn(gettext("cannot exec command %s"), argv[0]);
5290Sstevel@tonic-gate }
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate int
usage(void)5320Sstevel@tonic-gate usage(void)
5330Sstevel@tonic-gate {
5340Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
535*10089SSurya.Prakki@Sun.COM 	    "usage: \n"
536*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -c [-F] [processor_id ...]\n"
537*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -d processor_set_id ...\n"
538*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -n processor_set_id\n"
539*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -f processor_set_id\n"
540*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -e processor_set_id command [argument(s)...]\n"
541*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -a [-F] processor_set_id processor_id ...\n"
542*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -r [-F] processor_id ...\n"
543*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -p [processorid ...]\n"
544*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -b processor_set_id pid[/lwpids] ...\n"
545*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -u pid[/lwpids] ...\n"
546*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -q [pid[/lwpids] ...]\n"
547*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -U [processor_set_id] ...\n"
548*10089SSurya.Prakki@Sun.COM 	    "\t%1$s -Q [processor_set_id] ...\n"
549*10089SSurya.Prakki@Sun.COM 	    "\t%1$s [-i] [processor_set_id ...]\n"),
550*10089SSurya.Prakki@Sun.COM 	    progname);
5510Sstevel@tonic-gate 	return (ERR_USAGE);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate  * Query, set, or clear bindings for the range of LWPs in the given process.
5560Sstevel@tonic-gate  */
5570Sstevel@tonic-gate static int
do_lwps(id_t pid,const char * range,psetid_t pset)5580Sstevel@tonic-gate do_lwps(id_t pid, const char *range, psetid_t pset)
5590Sstevel@tonic-gate {
5600Sstevel@tonic-gate 	char procfile[MAX_PROCFS_PATH];
5610Sstevel@tonic-gate 	struct ps_prochandle *Pr;
5620Sstevel@tonic-gate 	struct prheader header;
5630Sstevel@tonic-gate 	struct lwpsinfo *lwp;
5640Sstevel@tonic-gate 	char *lpsinfo, *ptr;
5650Sstevel@tonic-gate 	psetid_t binding;
5660Sstevel@tonic-gate 	int nent, size;
5670Sstevel@tonic-gate 	int i, fd, found;
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 	/*
5700Sstevel@tonic-gate 	 * Report bindings for LWPs in process 'pid'.
5710Sstevel@tonic-gate 	 */
5720Sstevel@tonic-gate 	(void) snprintf(procfile, MAX_PROCFS_PATH,
5730Sstevel@tonic-gate 	    "/proc/%d/lpsinfo", (int)pid);
5740Sstevel@tonic-gate 	if ((fd = open(procfile, O_RDONLY)) < 0) {
5750Sstevel@tonic-gate 		if (errno == ENOENT)
5760Sstevel@tonic-gate 			errno = ESRCH;
5770Sstevel@tonic-gate 		bind_err(pset, pid, -1, errno);
5780Sstevel@tonic-gate 		return (ERR_FAIL);
5790Sstevel@tonic-gate 	}
5800Sstevel@tonic-gate 	if (pread(fd, &header, sizeof (header), 0) != sizeof (header)) {
5810Sstevel@tonic-gate 		(void) close(fd);
5820Sstevel@tonic-gate 		bind_err(pset, pid, -1, errno);
5830Sstevel@tonic-gate 		return (ERR_FAIL);
5840Sstevel@tonic-gate 	}
5850Sstevel@tonic-gate 	nent = header.pr_nent;
5860Sstevel@tonic-gate 	size = header.pr_entsize * nent;
5870Sstevel@tonic-gate 	ptr = lpsinfo = malloc(size);
5880Sstevel@tonic-gate 	if (lpsinfo == NULL) {
5890Sstevel@tonic-gate 		bind_err(pset, pid, -1, errno);
5900Sstevel@tonic-gate 		return (ERR_FAIL);
5910Sstevel@tonic-gate 	}
5920Sstevel@tonic-gate 	if (pread(fd, lpsinfo, size, sizeof (header)) != size) {
5930Sstevel@tonic-gate 		bind_err(pset, pid, -1, errno);
5940Sstevel@tonic-gate 		free(lpsinfo);
5950Sstevel@tonic-gate 		(void) close(fd);
5960Sstevel@tonic-gate 		return (ERR_FAIL);
5970Sstevel@tonic-gate 	}
5980Sstevel@tonic-gate 
5990Sstevel@tonic-gate 	if ((bflag || uflag) && (Pr = grab_proc(pid)) == NULL) {
6000Sstevel@tonic-gate 		free(lpsinfo);
6010Sstevel@tonic-gate 		(void) close(fd);
6020Sstevel@tonic-gate 		return (ERR_FAIL);
6030Sstevel@tonic-gate 	}
6040Sstevel@tonic-gate 	found = 0;
6050Sstevel@tonic-gate 	for (i = 0; i < nent; i++, ptr += header.pr_entsize) {
6060Sstevel@tonic-gate 		/*LINTED ALIGNMENT*/
6070Sstevel@tonic-gate 		lwp = (lwpsinfo_t *)ptr;
6080Sstevel@tonic-gate 		binding = lwp->pr_bindpset;
6090Sstevel@tonic-gate 		if (!proc_lwp_in_set(range, lwp->pr_lwpid))
6100Sstevel@tonic-gate 			continue;
6110Sstevel@tonic-gate 		found++;
6120Sstevel@tonic-gate 		if (bflag || uflag)
613*10089SSurya.Prakki@Sun.COM 			bind_lwp(pid, lwp->pr_lwpid, pset);
6140Sstevel@tonic-gate 		else if (binding != PBIND_NONE)
6150Sstevel@tonic-gate 			query_out(pid, lwp->pr_lwpid, binding);
6160Sstevel@tonic-gate 	}
6170Sstevel@tonic-gate 	if (bflag || uflag)
6180Sstevel@tonic-gate 		rele_proc(Pr);
6190Sstevel@tonic-gate 	free(lpsinfo);
6200Sstevel@tonic-gate 	(void) close(fd);
6210Sstevel@tonic-gate 	if (found == 0) {
6220Sstevel@tonic-gate 		warn(gettext("cannot %s lwpid %d/%s: "
6230Sstevel@tonic-gate 		    "No matching LWPs found\n"),
6240Sstevel@tonic-gate 		    bflag ? "bind" : "query", pid, range);
6250Sstevel@tonic-gate 		return (ERR_FAIL);
6260Sstevel@tonic-gate 	}
6270Sstevel@tonic-gate 	return (ERR_OK);
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate int
main(int argc,char * argv[])6310Sstevel@tonic-gate main(int argc, char *argv[])
6320Sstevel@tonic-gate {
6330Sstevel@tonic-gate 	extern int optind;
6340Sstevel@tonic-gate 	int	c;
6350Sstevel@tonic-gate 	id_t	pid;
6360Sstevel@tonic-gate 	processorid_t	cpu;
6370Sstevel@tonic-gate 	psetid_t	pset, old_pset;
6380Sstevel@tonic-gate 	char	*errptr;
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	progname = argv[0];	/* put actual command name in messages */
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");	/* setup localization */
6430Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "cdFarpibqQuUnfe")) != EOF) {
6460Sstevel@tonic-gate 		switch (c) {
6470Sstevel@tonic-gate 		case 'c':
6480Sstevel@tonic-gate 			cflag = 1;
6490Sstevel@tonic-gate 			break;
6500Sstevel@tonic-gate 		case 'd':
6510Sstevel@tonic-gate 			dflag = 1;
6520Sstevel@tonic-gate 			break;
6530Sstevel@tonic-gate 		case 'e':
6540Sstevel@tonic-gate 			eflag = 1;
6550Sstevel@tonic-gate 			break;
6560Sstevel@tonic-gate 		case 'a':
6570Sstevel@tonic-gate 			aflag = 1;
6580Sstevel@tonic-gate 			break;
6590Sstevel@tonic-gate 		case 'r':
6600Sstevel@tonic-gate 			rflag = 1;
6610Sstevel@tonic-gate 			pset = PS_NONE;
6620Sstevel@tonic-gate 			break;
6630Sstevel@tonic-gate 		case 'p':
6640Sstevel@tonic-gate 			pflag = 1;
6650Sstevel@tonic-gate 			pset = PS_QUERY;
6660Sstevel@tonic-gate 			break;
6670Sstevel@tonic-gate 		case 'i':
6680Sstevel@tonic-gate 			iflag = 1;
6690Sstevel@tonic-gate 			break;
6700Sstevel@tonic-gate 		case 'b':
6710Sstevel@tonic-gate 			bflag = 1;
6720Sstevel@tonic-gate 			break;
6730Sstevel@tonic-gate 		case 'u':
6740Sstevel@tonic-gate 			uflag = 1;
6750Sstevel@tonic-gate 			pset = PS_NONE;
6760Sstevel@tonic-gate 			break;
6770Sstevel@tonic-gate 		case 'U':
6780Sstevel@tonic-gate 			Uflag = 1;
6790Sstevel@tonic-gate 			break;
6800Sstevel@tonic-gate 		case 'q':
6810Sstevel@tonic-gate 			qflag = 1;
6820Sstevel@tonic-gate 			pset = PS_QUERY;
6830Sstevel@tonic-gate 			break;
6840Sstevel@tonic-gate 		case 'Q':
6850Sstevel@tonic-gate 			Qflag = 1;
6860Sstevel@tonic-gate 			break;
6870Sstevel@tonic-gate 		case 'f':
6880Sstevel@tonic-gate 			fflag = 1;
6890Sstevel@tonic-gate 			break;
6900Sstevel@tonic-gate 		case 'F':
6910Sstevel@tonic-gate 			Fflag = 1;
6920Sstevel@tonic-gate 			break;
6930Sstevel@tonic-gate 		case 'n':
6940Sstevel@tonic-gate 			nflag = 1;
6950Sstevel@tonic-gate 			break;
6960Sstevel@tonic-gate 		default:
6970Sstevel@tonic-gate 			return (usage());
6980Sstevel@tonic-gate 		}
6990Sstevel@tonic-gate 	}
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	/*
7020Sstevel@tonic-gate 	 * Make sure that at most one of the options was specified.
7030Sstevel@tonic-gate 	 */
7040Sstevel@tonic-gate 	c = cflag + dflag + aflag + rflag + pflag +
7050Sstevel@tonic-gate 	    iflag + bflag + uflag + Uflag +
7060Sstevel@tonic-gate 	    qflag + Qflag + fflag + nflag + eflag;
7070Sstevel@tonic-gate 	if (c < 1) {				/* nothing specified */
7080Sstevel@tonic-gate 		iflag = 1;			/* default is to get info */
7090Sstevel@tonic-gate 	} else if (c > 1) {
7100Sstevel@tonic-gate 		warn(gettext("options are mutually exclusive\n"));
7110Sstevel@tonic-gate 		return (usage());
7120Sstevel@tonic-gate 	}
7130Sstevel@tonic-gate 
7140Sstevel@tonic-gate 	if (Fflag && (cflag + aflag + rflag == 0))
7150Sstevel@tonic-gate 		return (usage());
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	errors = 0;
7180Sstevel@tonic-gate 	argc -= optind;
7190Sstevel@tonic-gate 	argv += optind;
7200Sstevel@tonic-gate 
7210Sstevel@tonic-gate 	if (argc == 0) {
7220Sstevel@tonic-gate 		/*
7230Sstevel@tonic-gate 		 * Handle single option cases.
7240Sstevel@tonic-gate 		 */
7250Sstevel@tonic-gate 		if (qflag) {
7260Sstevel@tonic-gate 			(void) proc_walk(query_all_proc, NULL, PR_WALK_PROC);
7270Sstevel@tonic-gate 			return (errors);
7280Sstevel@tonic-gate 		}
7290Sstevel@tonic-gate 		if (Qflag) {
7300Sstevel@tonic-gate 			(void) proc_walk(query_all_lwp, NULL, PR_WALK_LWP);
7310Sstevel@tonic-gate 			return (errors);
7320Sstevel@tonic-gate 		}
7330Sstevel@tonic-gate 		if (Uflag) {
7340Sstevel@tonic-gate 			if (pset_bind(PS_NONE, P_ALL, 0, &old_pset) != 0)
7350Sstevel@tonic-gate 				die(gettext("failed to unbind all LWPs"));
7360Sstevel@tonic-gate 		}
7370Sstevel@tonic-gate 		if (pflag)
7380Sstevel@tonic-gate 			return (print_all());
7390Sstevel@tonic-gate 		if (iflag)
7400Sstevel@tonic-gate 			return (info_all());
7410Sstevel@tonic-gate 	}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	/*
7440Sstevel@tonic-gate 	 * Get processor set id.
7450Sstevel@tonic-gate 	 */
7460Sstevel@tonic-gate 	if (aflag || bflag || fflag || nflag || eflag) {
7470Sstevel@tonic-gate 		if (argc < 1) {
7480Sstevel@tonic-gate 			/* must specify processor set */
7490Sstevel@tonic-gate 			warn(gettext("must specify processor set\n"));
7500Sstevel@tonic-gate 			return (usage());
7510Sstevel@tonic-gate 		}
7520Sstevel@tonic-gate 		pset = strtol(*argv, &errptr, 10);
7530Sstevel@tonic-gate 		if (errptr != NULL && *errptr != '\0' || pset < 0) {
7540Sstevel@tonic-gate 			warn(gettext("invalid processor set ID %s\n"), *argv);
7550Sstevel@tonic-gate 			return (ERR_FAIL);
7560Sstevel@tonic-gate 		}
7570Sstevel@tonic-gate 		argv++;
7580Sstevel@tonic-gate 		argc--;
7590Sstevel@tonic-gate 	}
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 	if (cflag) {
7620Sstevel@tonic-gate 		if (pset_create(&pset) != 0) {
7630Sstevel@tonic-gate 			warn(gettext("could not create processor set"));
7640Sstevel@tonic-gate 			return (ERR_FAIL);
7650Sstevel@tonic-gate 		} else {
7660Sstevel@tonic-gate 			create_out(pset);
7670Sstevel@tonic-gate 			if (argc == 0)
7680Sstevel@tonic-gate 				return (ERR_OK);
7690Sstevel@tonic-gate 		}
7700Sstevel@tonic-gate 	} else if (iflag || dflag) {
7710Sstevel@tonic-gate 		if (argc == 0) {
7720Sstevel@tonic-gate 			warn(gettext("must specify at least one "
7730Sstevel@tonic-gate 			    "processor set\n"));
7740Sstevel@tonic-gate 			return (usage());
7750Sstevel@tonic-gate 		}
7760Sstevel@tonic-gate 		/*
7770Sstevel@tonic-gate 		 * Go through listed processor sets.
7780Sstevel@tonic-gate 		 */
7790Sstevel@tonic-gate 		for (; argc > 0; argv++, argc--) {
7800Sstevel@tonic-gate 			pset = (psetid_t)strtol(*argv, &errptr, 10);
7810Sstevel@tonic-gate 			if (errptr != NULL && *errptr != '\0') {
7820Sstevel@tonic-gate 				warn(gettext("invalid processor set ID %s\n"),
7830Sstevel@tonic-gate 				    *argv);
7840Sstevel@tonic-gate 				errors = ERR_FAIL;
7850Sstevel@tonic-gate 				continue;
7860Sstevel@tonic-gate 			}
7870Sstevel@tonic-gate 			if (iflag) {
7880Sstevel@tonic-gate 				errors = do_info(pset);
7890Sstevel@tonic-gate 			} else {
7900Sstevel@tonic-gate 				errors = do_destroy(pset);
7910Sstevel@tonic-gate 			}
7920Sstevel@tonic-gate 		}
7930Sstevel@tonic-gate 	} else if (nflag) {
7940Sstevel@tonic-gate 		errors = do_intr(pset, P_ONLINE);
7950Sstevel@tonic-gate 	} else if (fflag) {
7960Sstevel@tonic-gate 		errors = do_intr(pset, P_NOINTR);
7970Sstevel@tonic-gate 	} else if (eflag) {
7980Sstevel@tonic-gate 		if (argc == 0) {
7990Sstevel@tonic-gate 			warn(gettext("must specify command\n"));
8000Sstevel@tonic-gate 			return (usage());
8010Sstevel@tonic-gate 		}
8020Sstevel@tonic-gate 		exec_cmd(pset, argv);
8030Sstevel@tonic-gate 		/* if returning, must have had an error */
8040Sstevel@tonic-gate 		return (ERR_USAGE);
8050Sstevel@tonic-gate 	}
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	if (cflag || aflag || rflag || pflag) {
8080Sstevel@tonic-gate 		/*
8090Sstevel@tonic-gate 		 * Perform function for each processor specified.
8100Sstevel@tonic-gate 		 */
8110Sstevel@tonic-gate 		if (argc == 0) {
8120Sstevel@tonic-gate 			warn(gettext("must specify at least one processor\n"));
8130Sstevel@tonic-gate 			return (usage());
8140Sstevel@tonic-gate 		}
8150Sstevel@tonic-gate 
8160Sstevel@tonic-gate 		/*
8170Sstevel@tonic-gate 		 * Go through listed processors.
8180Sstevel@tonic-gate 		 */
8190Sstevel@tonic-gate 		for (; argc > 0; argv++, argc--) {
8200Sstevel@tonic-gate 			if (strchr(*argv, '-') == NULL) {
8210Sstevel@tonic-gate 				/* individual processor id */
8220Sstevel@tonic-gate 				cpu = (processorid_t)strtol(*argv, &errptr, 10);
8230Sstevel@tonic-gate 				if (errptr != NULL && *errptr != '\0') {
8240Sstevel@tonic-gate 					warn(gettext("invalid processor "
8250Sstevel@tonic-gate 					    "ID %s\n"), *argv);
8260Sstevel@tonic-gate 					errors = ERR_FAIL;
8270Sstevel@tonic-gate 					continue;
8280Sstevel@tonic-gate 				}
8290Sstevel@tonic-gate 				if (do_cpu(pset, cpu, pflag, 1))
8300Sstevel@tonic-gate 					errors = ERR_FAIL;
8310Sstevel@tonic-gate 			} else {
8320Sstevel@tonic-gate 				/* range of processors */
8330Sstevel@tonic-gate 				processorid_t first, last;
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 				first = (processorid_t)
8360Sstevel@tonic-gate 				    strtol(*argv, &errptr, 10);
8370Sstevel@tonic-gate 				if (*errptr++ != '-') {
8380Sstevel@tonic-gate 					warn(gettext(
8390Sstevel@tonic-gate 					    "invalid processor range %s\n"),
8400Sstevel@tonic-gate 					    *argv);
8410Sstevel@tonic-gate 					errors = ERR_USAGE;
8420Sstevel@tonic-gate 					continue;
8430Sstevel@tonic-gate 				}
8440Sstevel@tonic-gate 				last = (processorid_t)
8450Sstevel@tonic-gate 				    strtol(errptr, &errptr, 10);
8460Sstevel@tonic-gate 				if ((errptr != NULL && *errptr != '\0') ||
8470Sstevel@tonic-gate 				    last < first || first < 0) {
8480Sstevel@tonic-gate 					warn(gettext(
8490Sstevel@tonic-gate 					    "invalid processor range %s\n"),
8500Sstevel@tonic-gate 					    *argv);
8510Sstevel@tonic-gate 					errors = ERR_USAGE;
8520Sstevel@tonic-gate 					continue;
8530Sstevel@tonic-gate 				}
8540Sstevel@tonic-gate 				if (do_range(pset, first, last, pflag))
8550Sstevel@tonic-gate 					errors = ERR_FAIL;
8560Sstevel@tonic-gate 			}
8570Sstevel@tonic-gate 		}
8580Sstevel@tonic-gate 	} else if (bflag || uflag || qflag) {
8590Sstevel@tonic-gate 		/*
8600Sstevel@tonic-gate 		 * Perform function for each pid/lwpid specified.
8610Sstevel@tonic-gate 		 */
8620Sstevel@tonic-gate 		if (argc == 0) {
8630Sstevel@tonic-gate 			warn(gettext("must specify at least one pid\n"));
8640Sstevel@tonic-gate 			return (usage());
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate 		/*
8680Sstevel@tonic-gate 		 * Go through listed processes/lwp_ranges.
8690Sstevel@tonic-gate 		 */
8700Sstevel@tonic-gate 		for (; argc > 0; argv++, argc--) {
8710Sstevel@tonic-gate 			pid = (id_t)strtol(*argv, &errptr, 10);
8720Sstevel@tonic-gate 			if (errno != 0 ||
8730Sstevel@tonic-gate 			    (errptr != NULL && *errptr != '\0' &&
874*10089SSurya.Prakki@Sun.COM 			    *errptr != '/')) {
8750Sstevel@tonic-gate 				warn(gettext("invalid process ID: %s\n"),
8760Sstevel@tonic-gate 				    *argv);
8770Sstevel@tonic-gate 				continue;
8780Sstevel@tonic-gate 			}
8790Sstevel@tonic-gate 			if (errptr != NULL && *errptr == '/') {
8800Sstevel@tonic-gate 				int ret;
8810Sstevel@tonic-gate 				/*
8820Sstevel@tonic-gate 				 * Handle lwp range case
8830Sstevel@tonic-gate 				 */
8840Sstevel@tonic-gate 				const char *lwps = (const char *)(++errptr);
8850Sstevel@tonic-gate 				if (*lwps == '\0' ||
8860Sstevel@tonic-gate 				    proc_lwp_range_valid(lwps) != 0) {
8870Sstevel@tonic-gate 					warn(gettext("invalid lwp range "
8880Sstevel@tonic-gate 					    "for pid %d\n"), (int)pid);
8890Sstevel@tonic-gate 					errors = ERR_FAIL;
8900Sstevel@tonic-gate 					continue;
8910Sstevel@tonic-gate 				}
8920Sstevel@tonic-gate 				if (!qflag)
8930Sstevel@tonic-gate 					(void) proc_initstdio();
8940Sstevel@tonic-gate 				ret = do_lwps(pid, lwps, pset);
8950Sstevel@tonic-gate 				if (!qflag)
8960Sstevel@tonic-gate 					(void) proc_finistdio();
8970Sstevel@tonic-gate 				if (ret != ERR_OK)
8980Sstevel@tonic-gate 					errors = ret;
8990Sstevel@tonic-gate 			} else {
9000Sstevel@tonic-gate 				/*
9010Sstevel@tonic-gate 				 * Handle whole process case.
9020Sstevel@tonic-gate 				 */
9030Sstevel@tonic-gate 				if (pset_bind(pset, P_PID, pid,
9040Sstevel@tonic-gate 				    &old_pset) < 0) {
9050Sstevel@tonic-gate 					bind_err(pset, pid, -1, errno);
9060Sstevel@tonic-gate 					errors = ERR_FAIL;
9070Sstevel@tonic-gate 					continue;
9080Sstevel@tonic-gate 				}
9090Sstevel@tonic-gate 				if (qflag)
9100Sstevel@tonic-gate 					query_out(pid, -1, old_pset);
9110Sstevel@tonic-gate 				else
9120Sstevel@tonic-gate 					bind_out(pid, -1, old_pset, pset);
9130Sstevel@tonic-gate 			}
9140Sstevel@tonic-gate 		}
9150Sstevel@tonic-gate 	}
9160Sstevel@tonic-gate 
9170Sstevel@tonic-gate 	if (Qflag || Uflag) {
9180Sstevel@tonic-gate 		/*
9190Sstevel@tonic-gate 		 * Go through listed processor set IDs.
9200Sstevel@tonic-gate 		 */
9210Sstevel@tonic-gate 		for (; argc > 0; argv++, argc--) {
9220Sstevel@tonic-gate 			errno = 0;
9230Sstevel@tonic-gate 			pset = (id_t)strtol(*argv, &errptr, 10);
9240Sstevel@tonic-gate 			if (errno != 0 ||
9250Sstevel@tonic-gate 			    (errptr != NULL && *errptr != '\0')) {
9260Sstevel@tonic-gate 				warn(gettext("invalid processor set ID\n"));
9270Sstevel@tonic-gate 				continue;
9280Sstevel@tonic-gate 			}
9290Sstevel@tonic-gate 			if (Qflag) {
9300Sstevel@tonic-gate 				(void) proc_walk(query_all_lwp,
9310Sstevel@tonic-gate 				    &pset, PR_WALK_LWP);
9320Sstevel@tonic-gate 				continue;
9330Sstevel@tonic-gate 			}
9340Sstevel@tonic-gate 			if (Uflag) {
9350Sstevel@tonic-gate 				if (pset_bind(PS_NONE, P_PSETID, pset,
9360Sstevel@tonic-gate 				    &old_pset) != 0) {
9370Sstevel@tonic-gate 					warn(gettext("failed to unbind from "
9380Sstevel@tonic-gate 					    "processor set %d"), (int)pset);
9390Sstevel@tonic-gate 					errors = ERR_FAIL;
9400Sstevel@tonic-gate 				}
9410Sstevel@tonic-gate 				continue;
9420Sstevel@tonic-gate 			}
9430Sstevel@tonic-gate 		}
9440Sstevel@tonic-gate 	}
9450Sstevel@tonic-gate 
9460Sstevel@tonic-gate 	return (errors);
9470Sstevel@tonic-gate }
948