8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / priocntl / priocntl.c
blobf599c18dad7053e2a3c18a88524ca813ffd91468
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <wait.h>
37 #include <search.h>
38 #include <unistd.h>
39 #include <sys/types.h>
40 #include <dirent.h>
41 #include <fcntl.h>
42 #include <sys/param.h>
43 #include <sys/procset.h>
44 #include <sys/priocntl.h>
45 #include <procfs.h>
46 #include <macros.h>
47 #include <libgen.h>
48 #include <limits.h>
49 #include <errno.h>
51 #include "priocntl.h"
54 * This file contains the code implementing the class independent part
55 * of the priocntl command. Most of the useful work for the priocntl
56 * command is done by the class specific sub-commands, the code for
57 * which is elsewhere. The class independent part of the command is
58 * responsible for executing the appropriate class specific sub-commands
59 * and providing any necessary input to the sub-commands.
60 * Code in this file should never assume any knowledge of any specific
61 * scheduler class (other than the SYS class).
64 #define CLASSPATH "/usr/lib/class"
66 typedef struct classpids {
67 char clp_clname[PC_CLNMSZ];
68 pid_t *clp_pidlist;
69 int clp_pidlistsz;
70 int clp_npids;
71 } classpids_t;
73 static char usage[] =
74 "usage: priocntl -l\n\
75 priocntl -d [-i idtype] [idlist]\n\
76 priocntl -s [-c class] [c.s.o.] [-i idtype] [idlist]\n\
77 priocntl -e [-c class] [c.s.o.] command [argument(s)]\n";
79 static char basenm[BASENMSZ];
80 static char cmdpath[MAXPATHLEN];
82 static char *procdir = "/proc";
84 static int print_classlist(void);
85 static void set_procs(char *, idtype_t, int, char **, char **);
86 static void exec_cmd(char *, char **);
87 static int print_procs(idtype_t, int, char *[]);
88 static void ids2pids(idtype_t, id_t *, int, classpids_t *, int);
89 static void add_pid_tolist(classpids_t *, int, char *, pid_t);
90 static void increase_pidlist(classpids_t *);
91 static boolean_t idmatch(char *, char *, int, char **);
94 * These variables are defined to be used in prio_getopt() below.
96 static int prio_getopt();
97 /* LINTED static unused */
98 static int prio_optopt = 0;
99 static char *prio_optarg = 0;
100 static int prio_optind = 1;
101 static int prio_sp = 1;
104 main(int argc, char *argv[])
106 int c;
107 int lflag, dflag, sflag, eflag, cflag, iflag, csoptsflag;
108 char *clname;
109 char *idtypnm;
110 idtype_t idtype;
111 int idargc;
112 char **idargv;
114 (void) strlcpy(cmdpath, argv[0], MAXPATHLEN);
115 (void) strlcpy(basenm, basename(argv[0]), BASENMSZ);
116 lflag = dflag = sflag = eflag = cflag = iflag = csoptsflag = 0;
117 while ((c = prio_getopt(argc, argv, "ldsec:i:")) != -1) {
119 switch (c) {
121 case 'l':
122 lflag++;
123 break;
125 case 'd':
126 dflag++;
127 break;
129 case 's':
130 sflag++;
131 break;
133 case 'e':
134 eflag++;
135 break;
137 case 'c':
138 cflag++;
139 clname = prio_optarg;
140 break;
142 case 'i':
143 iflag++;
144 idtypnm = prio_optarg;
145 break;
147 case '?':
148 if (strcmp(argv[prio_optind - 1], "-c") == 0 ||
149 strcmp(argv[prio_optind - 1], "-i") == 0) {
152 * getopt() will return ? if either
153 * of these appear without an argument.
155 fatalerr(usage);
159 * We assume for now that any option that
160 * getopt() doesn't recognize (with the
161 * exception of c and i) is intended for a
162 * class specific subcommand. For now we also
163 * require that all class specific options
164 * take an argument (until we can get smarter
165 * about parsing our options).
167 csoptsflag++;
168 prio_optind++;
169 prio_sp = 1;
170 break;
172 default:
173 break;
177 if (lflag) {
178 if (dflag || sflag || eflag || cflag || iflag || csoptsflag)
179 fatalerr(usage);
181 return (print_classlist());
183 } else if (dflag) {
184 if (lflag || sflag || eflag || cflag || csoptsflag)
185 fatalerr(usage);
186 if (iflag) {
187 if (str2idtyp(idtypnm, &idtype) == -1)
188 fatalerr("%s: bad idtype %s\n", cmdpath,
189 idtypnm);
190 } else {
191 idtype = P_PID;
194 if (prio_optind < argc) {
195 idargc = argc - prio_optind;
196 idargv = &argv[prio_optind];
197 } else {
198 idargc = 0;
201 return (print_procs(idtype, idargc, idargv));
203 } else if (sflag) {
204 if (lflag || dflag || eflag)
205 fatalerr(usage);
206 if (iflag) {
207 if (str2idtyp(idtypnm, &idtype) == -1)
208 fatalerr("%s: bad idtype %s\n", cmdpath,
209 idtypnm);
210 } else {
211 idtype = P_PID;
214 if (cflag == 0)
215 clname = NULL;
217 if (prio_optind < argc) {
218 idargc = argc - prio_optind;
219 idargv = &argv[prio_optind];
220 } else {
221 idargc = 0;
224 set_procs(clname, idtype, idargc, idargv, argv);
226 } else if (eflag) {
227 if (lflag || dflag || sflag || iflag)
228 fatalerr(usage);
230 if (cflag == 0)
231 clname = NULL;
233 if (prio_optind >= argc)
234 fatalerr(usage);
236 exec_cmd(clname, argv);
238 } else {
239 fatalerr(usage);
242 return (0);
247 * Print the heading for the class list and execute the class
248 * specific sub-command with the -l option for each configured class.
250 static int
251 print_classlist(void)
253 id_t cid;
254 int nclass;
255 pcinfo_t pcinfo;
256 static char subcmdpath[128];
257 int status;
258 pid_t pid;
259 int error = 0;
262 * No special privileges required for this operation.
263 * Set the effective UID back to the real UID.
265 if (setuid(getuid()) == -1)
266 fatalerr("%s: Can't set effective UID back to real UID\n",
267 cmdpath);
269 if ((nclass = priocntl(0, 0, PC_GETCLINFO, NULL)) == -1)
270 fatalerr("%s: Can't get number of configured classes, priocntl"
271 " system call failed with errno %d\n", cmdpath, errno);
273 (void) printf("CONFIGURED CLASSES\n==================\n\n");
274 (void) printf("SYS (System Class)\n");
275 for (cid = 1; cid < nclass; cid++) {
276 (void) printf("\n");
277 (void) fflush(stdout);
278 pcinfo.pc_cid = cid;
279 if (priocntl(0, 0, PC_GETCLINFO, (caddr_t)&pcinfo) == -1)
280 fatalerr("%s: can't get class name (class ID = %ld)\n",
281 cmdpath, cid);
282 if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s",
283 CLASSPATH, pcinfo.pc_clname, pcinfo.pc_clname, basenm) >=
284 sizeof (subcmdpath))
285 fatalerr("%s: can't generate %s specific subcommand\n",
286 cmdpath, pcinfo.pc_clname);
287 if ((pid = fork()) == 0) {
288 (void) execl(subcmdpath, subcmdpath, "-l", (char *)0);
289 (void) printf("%s\n", pcinfo.pc_clname);
290 fatalerr("\tCan't execute %s specific subcommand\n",
291 pcinfo.pc_clname);
292 } else if (pid == (pid_t)-1) {
293 (void) printf("%s\n", pcinfo.pc_clname);
294 (void) fprintf(stderr,
295 "Can't execute %s specific subcommand)\n",
296 pcinfo.pc_clname);
297 error = 1;
298 } else {
299 (void) wait(&status);
300 if (status)
301 error = 1;
305 return (error);
310 * For each class represented within the set of processes specified by
311 * idtype/idargv, print_procs() executes the class specific sub-command
312 * with the -d option. We pipe to each sub-command a list of pids in
313 * the set belonging to that class.
315 static int
316 print_procs(idtype_t idtype, int idargc, char *idargv[])
318 int i;
319 id_t id;
320 id_t idlist[NIDS];
321 int nids;
322 classpids_t *clpids;
323 int nclass;
324 id_t cid;
325 pcinfo_t pcinfo;
326 int pidexists;
327 FILE *pipe_to_subcmd;
328 char subcmd[128];
329 int error = 0;
333 * Build a list of ids eliminating any duplicates in idargv.
335 if (idtype == P_ALL) {
337 * No idlist should be specified. If one is specified,
338 * it is ignored.
340 nids = 0;
341 } else if (idargc == 0) {
344 * No ids supplied by user; use current id.
346 if (getmyid(idtype, &idlist[0]) == -1)
347 fatalerr("%s: Can't get ID for current process,"
348 " idtype = %d\n", cmdpath, idtype);
349 nids = 1;
350 } else {
351 nids = 0;
352 for (i = 0; i < idargc && nids < NIDS; i++) {
353 if (idtype == P_CID) {
354 if ((id = clname2cid(idargv[i])) == -1) {
355 (void) fprintf(stderr, "%s: Invalid or"
356 " unconfigured class %s in idlist"
357 " - ignored\n", cmdpath, idargv[i]);
358 error = 1;
360 } else {
361 id = (id_t)str2num(idargv[i], INT_MIN, INT_MAX);
362 if (errno) {
363 (void) fprintf(stderr,
364 "%s: Invalid id \"%s\"\n",
365 cmdpath, idargv[i]);
366 error = 1;
367 id = BADPID;
372 * lsearch(3C) adds ids to the idlist,
373 * eliminating duplicates.
375 (void) lsearch((void *)&id, (void *)idlist,
376 (size_t *)&nids, sizeof (id), (int (*)())idcompar);
380 if ((nclass = priocntl(0, 0, PC_GETCLINFO, NULL)) == -1)
381 fatalerr("%s: Can't get number of configured classes, priocntl"
382 " system call failed with errno %d\n", cmdpath, errno);
384 if ((clpids = (classpids_t *)malloc(sizeof (classpids_t) * nclass)) ==
385 NULL)
386 fatalerr("%s: Can't allocate memory for clpids.\n", cmdpath);
388 for (cid = 1; cid < nclass; cid++) {
389 pcinfo.pc_cid = cid;
390 if (priocntl(0, 0, PC_GETCLINFO, (caddr_t)&pcinfo) == -1)
391 fatalerr("%s: Can't get class name, cid = %ld\n",
392 cmdpath, cid);
394 (void) strncpy(clpids[cid].clp_clname, pcinfo.pc_clname,
395 PC_CLNMSZ);
398 * The memory allocation for the pidlist uses realloc().
399 * A realloc() call is required, when "clp_npids" is
400 * equal to "clp_pidlistsz".
402 clpids[cid].clp_pidlist = (pid_t *)NULL;
403 clpids[cid].clp_pidlistsz = 0;
404 clpids[cid].clp_npids = 0;
408 * Build the pidlist.
410 ids2pids(idtype, idlist, nids, clpids, nclass);
413 * No need for special privileges any more.
414 * Set the effective UID back to the real UID.
416 if (setuid(getuid()) == -1)
417 fatalerr("%s: Can't set effective UID back to real UID\n",
418 cmdpath);
420 pidexists = 0;
421 for (cid = 1; cid < nclass; cid++) {
422 if (clpids[cid].clp_npids == 0)
423 continue;
425 pidexists = 1;
426 if (snprintf(subcmd, sizeof (subcmd), "%s/%s/%s%s -d",
427 CLASSPATH, clpids[cid].clp_clname, clpids[cid].clp_clname,
428 basenm) >= sizeof (subcmd)) {
429 (void) fprintf(stderr,
430 "Can't generate %s specific subcommand\n",
431 clpids[cid].clp_clname);
432 error = 1;
433 free(clpids[cid].clp_pidlist);
434 continue;
436 if ((pipe_to_subcmd = popen(subcmd, "w")) == NULL) {
437 (void) printf("%s\n", clpids[cid].clp_clname);
438 (void) fprintf(stderr,
439 "Can't execute %s specific subcommand\n",
440 clpids[cid].clp_clname);
441 error = 1;
442 free(clpids[cid].clp_pidlist);
443 continue;
445 (void) fwrite(clpids[cid].clp_pidlist, sizeof (pid_t),
446 clpids[cid].clp_npids, pipe_to_subcmd);
447 if (pclose(pipe_to_subcmd))
448 error = 1;
450 free(clpids[cid].clp_pidlist);
453 free(clpids);
455 if (pidexists == 0)
456 fatalerr("%s: Process(es) not found.\n", cmdpath);
458 return (error);
463 * Execute the appropriate class specific sub-command with the arguments
464 * pointed to by subcmdargv. If the user specified a class we simply
465 * exec the sub-command for that class. If no class was specified we
466 * verify that the processes in the set specified by idtype/idargv are
467 * all in the same class and then execute the sub-command for that class.
469 static void
470 set_procs(clname, idtype, idargc, idargv, subcmdargv)
471 char *clname;
472 idtype_t idtype;
473 int idargc;
474 char **idargv;
475 char **subcmdargv;
477 char idstr[PC_IDTYPNMSZ];
478 char myidstr[PC_IDTYPNMSZ];
479 char clnmbuf[PC_CLNMSZ];
480 pcinfo_t pcinfo;
481 static psinfo_t prinfo;
482 static prcred_t prcred;
483 DIR *dirp;
484 struct dirent *dentp;
485 static char pname[100];
486 char *fname;
487 int procfd;
488 int saverr;
489 static char subcmdpath[128];
490 boolean_t procinset;
491 id_t id;
492 size_t len;
494 if (clname == NULL && idtype == P_PID && idargc <= 1) {
497 * No class specified by user but only one process
498 * in specified set. Get the class the easy way.
500 if (idargc == 0) {
501 if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
502 PC_KY_CLNAME, clnmbuf, 0) == -1)
503 if (errno == ESRCH)
504 fatalerr("%s: Process not found.\n",
505 cmdpath);
506 else
507 fatalerr("%s: Can't get class of"
508 " current process\npriocntl"
509 " system call failed with"
510 " errno %d\n", cmdpath, errno);
511 } else {
512 /* idargc == 1 */
513 id = (id_t)str2num(idargv[0], INT_MIN, INT_MAX);
514 if (errno)
515 fatalerr("%s: Invalid id \"%s\"\n", cmdpath,
516 idargv[0]);
518 if (priocntl(P_PID, id, PC_GETXPARMS,
519 NULL, PC_KY_CLNAME, clnmbuf, 0) == -1)
520 if (errno == ESRCH)
521 fatalerr("%s: Process not found.\n",
522 cmdpath);
523 else
524 fatalerr("%s: Can't get class of "
525 " specified process\npriocntl"
526 " system call failed with"
527 " errno %d\n", cmdpath, errno);
530 clname = clnmbuf;
531 } else if (clname == NULL) {
534 * No class specified by user and potentially more
535 * than one process in specified set. Verify that
536 * all procs in set are in the same class.
538 if (idargc == 0 && idtype != P_ALL) {
541 * No ids supplied by user; use current id.
543 if (getmyidstr(idtype, myidstr) == -1)
544 fatalerr("%s: Can't get ID string for current"
545 " process, idtype = %d\n", cmdpath, idtype);
547 if ((dirp = opendir(procdir)) == NULL)
548 fatalerr("%s: Can't open PROC directory %s\n",
549 cmdpath, procdir);
551 while ((dentp = readdir(dirp)) != NULL) {
552 if (dentp->d_name[0] == '.') /* skip . and .. */
553 continue;
555 len = snprintf(pname, sizeof (pname), "%s/%s/",
556 procdir, dentp->d_name);
557 /* Really max(sizeof ("psinfo"), sizeof ("cred")) */
558 if (len + sizeof ("psinfo") > sizeof (pname)) {
559 (void) fprintf(stderr,
560 "%s: skipping %s, name too long.\n",
561 cmdpath, dentp->d_name);
562 continue;
564 fname = pname + len;
565 retry:
566 (void) strcpy(fname, "psinfo");
567 if ((procfd = open(pname, O_RDONLY)) < 0)
568 continue;
570 if (read(procfd, &prinfo, sizeof (prinfo)) !=
571 sizeof (prinfo)) {
572 saverr = errno;
573 (void) close(procfd);
574 if (saverr == EAGAIN)
575 goto retry;
576 if (saverr != ENOENT) {
577 (void) fprintf(stderr,
578 "%s: Can't get process info for"
579 " %s\n", cmdpath, pname);
581 continue;
583 (void) close(procfd);
585 if (idtype == P_UID || idtype == P_GID) {
586 (void) strcpy(fname, "cred");
587 if ((procfd = open(pname, O_RDONLY)) < 0 ||
588 read(procfd, &prcred, sizeof (prcred)) !=
589 sizeof (prcred)) {
590 saverr = errno;
591 if (procfd >= 0)
592 (void) close(procfd);
593 if (saverr == EAGAIN)
594 goto retry;
595 if (saverr != ENOENT) {
596 (void) fprintf(stderr,
597 "%s: Can't get process"
598 " credentials for %s\n",
599 cmdpath, pname);
601 continue;
603 (void) close(procfd);
606 if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0)
607 continue;
610 switch (idtype) {
612 case P_PID:
613 itoa((long)prinfo.pr_pid, idstr);
614 procinset = idmatch(idstr, myidstr,
615 idargc, idargv);
616 break;
618 case P_PPID:
619 itoa((long)prinfo.pr_ppid, idstr);
620 procinset = idmatch(idstr, myidstr,
621 idargc, idargv);
622 break;
624 case P_PGID:
625 itoa((long)prinfo.pr_pgid, idstr);
626 procinset = idmatch(idstr, myidstr,
627 idargc, idargv);
628 break;
630 case P_SID:
631 itoa((long)prinfo.pr_sid, idstr);
632 procinset = idmatch(idstr, myidstr,
633 idargc, idargv);
634 break;
636 case P_CID:
637 procinset = idmatch(prinfo.pr_lwp.pr_clname,
638 myidstr, idargc, idargv);
639 break;
641 case P_UID:
642 itoa((long)prcred.pr_euid, idstr);
643 procinset = idmatch(idstr, myidstr,
644 idargc, idargv);
645 break;
647 case P_GID:
648 itoa((long)prcred.pr_egid, idstr);
649 procinset = idmatch(idstr, myidstr,
650 idargc, idargv);
651 break;
653 case P_PROJID:
654 itoa((long)prinfo.pr_projid, idstr);
655 procinset = idmatch(idstr, myidstr,
656 idargc, idargv);
657 break;
659 case P_TASKID:
660 itoa((long)prinfo.pr_taskid, idstr);
661 procinset = idmatch(idstr, myidstr,
662 idargc, idargv);
663 break;
665 case P_ZONEID:
666 itoa((long)prinfo.pr_zoneid, idstr);
667 procinset = idmatch(idstr, myidstr,
668 idargc, idargv);
669 break;
671 case P_CTID:
672 itoa((long)prinfo.pr_contract, idstr);
673 procinset = idmatch(idstr, myidstr,
674 idargc, idargv);
675 break;
677 case P_ALL:
678 procinset = B_TRUE;
679 break;
681 default:
682 fatalerr("%s: Bad idtype %d in set_procs()\n",
683 cmdpath, idtype);
685 if (procinset == B_TRUE) {
686 if (clname == NULL) {
689 * First proc found in set.
691 (void) strcpy(clnmbuf,
692 prinfo.pr_lwp.pr_clname);
693 clname = clnmbuf;
694 } else if (strcmp(clname,
695 prinfo.pr_lwp.pr_clname) != 0) {
696 fatalerr("%s: Specified processes"
697 " from different classes.\n",
698 cmdpath);
702 (void) closedir(dirp);
703 if (clname == NULL)
704 fatalerr("%s: Process(es) not found.\n", cmdpath);
705 } else {
708 * User specified class. Check it for validity.
710 (void) strcpy(pcinfo.pc_clname, clname);
711 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
712 fatalerr("%s: Invalid or unconfigured class %s\n",
713 cmdpath, clname);
717 * No need for special privileges any more.
718 * Set the effective UID back to the real UID.
720 if (setuid(getuid()) == -1)
721 fatalerr("%s: Can't set effective UID back to real UID\n",
722 cmdpath);
724 if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s",
725 CLASSPATH, clname, clname, basenm) >= sizeof (subcmdpath))
726 fatalerr("%s: can't generate %s specific subcommand\n",
727 cmdpath, clname);
729 subcmdargv[0] = subcmdpath;
730 (void) execv(subcmdpath, subcmdargv);
731 fatalerr("%s: Can't execute %s sub-command\n", cmdpath, clname);
736 * Execute the appropriate class specific sub-command with the arguments
737 * pointed to by subcmdargv. If the user specified a class we simply
738 * exec the sub-command for that class. If no class was specified we
739 * execute the sub-command for our own current class.
741 static void
742 exec_cmd(clname, subcmdargv)
743 char *clname;
744 char **subcmdargv;
746 pcinfo_t pcinfo;
747 char clnmbuf[PC_CLNMSZ];
748 char subcmdpath[128];
751 * No special privileges required for this operation.
752 * Set the effective UID back to the real UID.
754 if (setuid(getuid()) == -1)
755 fatalerr("%s: Can't set effective UID back to real UID\n",
756 cmdpath);
758 if (clname == NULL) {
759 if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
760 PC_KY_CLNAME, clnmbuf, 0) == -1)
761 fatalerr("%s: Can't get class name of current process\n"
762 "priocntl system call failed with errno %d\n",
763 cmdpath, errno);
765 clname = clnmbuf;
766 } else {
769 * User specified class. Check it for validity.
771 (void) strcpy(pcinfo.pc_clname, clname);
772 if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
773 fatalerr("%s: Invalid or unconfigured class %s\n",
774 cmdpath, clname);
777 if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s",
778 CLASSPATH, clname, clname, basenm) >= sizeof (subcmdpath))
779 fatalerr("%s: can't generate %s specific subcommand\n",
780 cmdpath, clname);
781 subcmdargv[0] = subcmdpath;
782 (void) execv(subcmdpath, subcmdargv);
783 fatalerr("%s: Can't execute %s sub-command\n", cmdpath, clname);
788 * Fill in the classpids structures in the array pointed to by clpids
789 * with pids for the processes in the set specified by idtype/idlist.
790 * We read the /proc/<pid>/psinfo file to get the necessary process
791 * information.
793 static void
794 ids2pids(idtype, idlist, nids, clpids, nclass)
795 idtype_t idtype;
796 id_t *idlist;
797 int nids;
798 classpids_t *clpids;
799 int nclass;
801 static psinfo_t prinfo;
802 static prcred_t prcred;
803 DIR *dirp;
804 struct dirent *dentp;
805 char pname[100];
806 char *fname;
807 int procfd;
808 int saverr;
809 int i;
810 char *clname;
811 size_t len;
813 if ((dirp = opendir(procdir)) == NULL)
814 fatalerr("%s: Can't open PROC directory %s\n",
815 cmdpath, procdir);
817 while ((dentp = readdir(dirp)) != NULL) {
818 if (dentp->d_name[0] == '.') /* skip . and .. */
819 continue;
821 len = snprintf(pname, sizeof (pname), "%s/%s/",
822 procdir, dentp->d_name);
823 /* Really max(sizeof ("psinfo"), sizeof ("cred")) */
824 if (len + sizeof ("psinfo") > sizeof (pname)) {
825 (void) fprintf(stderr,
826 "%s: skipping %s, name too long.\n",
827 cmdpath, dentp->d_name);
828 continue;
830 fname = pname + len;
831 retry:
832 (void) strcpy(fname, "psinfo");
833 if ((procfd = open(pname, O_RDONLY)) < 0)
834 continue;
835 if (read(procfd, &prinfo, sizeof (prinfo)) != sizeof (prinfo)) {
836 saverr = errno;
837 (void) close(procfd);
838 if (saverr == EAGAIN)
839 goto retry;
840 if (saverr != ENOENT) {
841 (void) fprintf(stderr,
842 "%s: Can't get process info for %s\n",
843 cmdpath, pname);
845 continue;
847 (void) close(procfd);
849 if (idtype == P_UID || idtype == P_GID) {
850 (void) strcpy(fname, "cred");
851 if ((procfd = open(pname, O_RDONLY)) < 0 ||
852 read(procfd, &prcred, sizeof (prcred)) !=
853 sizeof (prcred)) {
854 saverr = errno;
855 (void) close(procfd);
856 if (saverr == EAGAIN)
857 goto retry;
858 if (saverr != ENOENT) {
859 (void) fprintf(stderr,
860 "%s: Can't get process credentials"
861 " for %s\n",
862 cmdpath, pname);
864 continue;
866 (void) close(procfd);
869 if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0)
870 continue;
872 switch (idtype) {
874 case P_PID:
875 for (i = 0; i < nids; i++) {
876 if (idlist[i] == (id_t)prinfo.pr_pid)
877 add_pid_tolist(clpids, nclass,
878 prinfo.pr_lwp.pr_clname,
879 prinfo.pr_pid);
881 break;
883 case P_PPID:
884 for (i = 0; i < nids; i++) {
885 if (idlist[i] == (id_t)prinfo.pr_ppid)
886 add_pid_tolist(clpids, nclass,
887 prinfo.pr_lwp.pr_clname,
888 prinfo.pr_pid);
890 break;
892 case P_PGID:
893 for (i = 0; i < nids; i++) {
894 if (idlist[i] == (id_t)prinfo.pr_pgid)
895 add_pid_tolist(clpids, nclass,
896 prinfo.pr_lwp.pr_clname,
897 prinfo.pr_pid);
899 break;
901 case P_SID:
902 for (i = 0; i < nids; i++) {
903 if (idlist[i] == (id_t)prinfo.pr_sid)
904 add_pid_tolist(clpids, nclass,
905 prinfo.pr_lwp.pr_clname,
906 prinfo.pr_pid);
908 break;
910 case P_CID:
911 for (i = 0; i < nids; i++) {
912 clname = clpids[idlist[i]].clp_clname;
913 if (strcmp(clname,
914 prinfo.pr_lwp.pr_clname) == 0)
915 add_pid_tolist(clpids, nclass,
916 prinfo.pr_lwp.pr_clname,
917 prinfo.pr_pid);
919 break;
921 case P_UID:
922 for (i = 0; i < nids; i++) {
923 if (idlist[i] == (id_t)prcred.pr_euid)
924 add_pid_tolist(clpids, nclass,
925 prinfo.pr_lwp.pr_clname,
926 prinfo.pr_pid);
928 break;
930 case P_GID:
931 for (i = 0; i < nids; i++) {
932 if (idlist[i] == (id_t)prcred.pr_egid)
933 add_pid_tolist(clpids, nclass,
934 prinfo.pr_lwp.pr_clname,
935 prinfo.pr_pid);
937 break;
939 case P_PROJID:
940 for (i = 0; i < nids; i++) {
941 if (idlist[i] == (id_t)prinfo.pr_projid)
942 add_pid_tolist(clpids, nclass,
943 prinfo.pr_lwp.pr_clname,
944 prinfo.pr_pid);
946 break;
948 case P_TASKID:
949 for (i = 0; i < nids; i++) {
950 if (idlist[i] == (id_t)prinfo.pr_taskid)
951 add_pid_tolist(clpids, nclass,
952 prinfo.pr_lwp.pr_clname,
953 prinfo.pr_pid);
955 break;
957 case P_ZONEID:
958 for (i = 0; i < nids; i++) {
959 if (idlist[i] == (id_t)prinfo.pr_zoneid)
960 add_pid_tolist(clpids, nclass,
961 prinfo.pr_lwp.pr_clname,
962 prinfo.pr_pid);
964 break;
966 case P_CTID:
967 for (i = 0; i < nids; i++) {
968 if (idlist[i] == (id_t)prinfo.pr_contract)
969 add_pid_tolist(clpids, nclass,
970 prinfo.pr_lwp.pr_clname,
971 prinfo.pr_pid);
973 break;
975 case P_ALL:
976 add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname,
977 prinfo.pr_pid);
978 break;
980 default:
981 fatalerr("%s: Bad idtype %d in ids2pids()\n",
982 cmdpath, idtype);
985 (void) closedir(dirp);
990 * Search the array pointed to by clpids for the classpids
991 * structure corresponding to clname and add pid to its
992 * pidlist.
994 static void
995 add_pid_tolist(clpids, nclass, clname, pid)
996 classpids_t *clpids;
997 int nclass;
998 char *clname;
999 pid_t pid;
1001 classpids_t *clp;
1003 for (clp = clpids; clp != &clpids[nclass]; clp++) {
1004 if (strcmp(clp->clp_clname, clname) == 0) {
1005 if (clp->clp_npids == clp->clp_pidlistsz)
1006 increase_pidlist(clp);
1008 (clp->clp_pidlist)[clp->clp_npids] = pid;
1009 clp->clp_npids++;
1010 return;
1016 static void
1017 increase_pidlist(classpids_t *clp)
1019 if ((clp->clp_pidlist = realloc(clp->clp_pidlist,
1020 (clp->clp_pidlistsz + NPIDS) * sizeof (pid_t))) == NULL)
1022 * The pidlist is filled up and we cannot increase the size.
1024 fatalerr("%s: Can't allocate memory for pidlist.\n", cmdpath);
1026 clp->clp_pidlistsz += NPIDS;
1031 * Compare id strings for equality. If idargv contains ids
1032 * (idargc > 0) compare idstr to each id in idargv, otherwise
1033 * just compare to curidstr.
1035 static boolean_t
1036 idmatch(idstr, curidstr, idargc, idargv)
1037 char *idstr;
1038 char *curidstr;
1039 int idargc;
1040 char **idargv;
1042 int i;
1044 if (idargc == 0) {
1045 if (strcmp(curidstr, idstr) == 0)
1046 return (B_TRUE);
1047 } else {
1048 for (i = 0; i < idargc; i++) {
1049 if (strcmp(idargv[i], idstr) == 0)
1050 return (B_TRUE);
1053 return (B_FALSE);
1057 * This is a copy of the getopt() function found in libc:getopt.c. A separate
1058 * copy is required to fix the bug id #1114636. To fix the problem we need to
1059 * reset the _sp to 1. Since _sp in libc:getopt() is not exposed, a copy of
1060 * the getopt() is kept so that prio_sp can be reset to 1.
1063 static int
1064 prio_getopt(argc, argv, opts)
1065 int argc;
1066 #ifdef __STDC__
1067 char *const *argv, *opts;
1068 #else
1069 char **argv, *opts;
1070 #endif
1072 register char c;
1073 register char *cp;
1075 if (prio_sp == 1)
1076 if (prio_optind >= argc ||
1077 argv[prio_optind][0] != '-' || argv[prio_optind][1] == '\0')
1078 return (EOF);
1079 else if (strcmp(argv[prio_optind], "--") == NULL) {
1080 prio_optind++;
1081 return (EOF);
1083 prio_optopt = c = (unsigned char)argv[prio_optind][prio_sp];
1084 if (c == ':' || (cp = strchr(opts, c)) == NULL) {
1085 if (argv[prio_optind][++prio_sp] == '\0') {
1086 prio_optind++;
1087 prio_sp = 1;
1089 return ('?');
1091 if (*++cp == ':') {
1092 if (argv[prio_optind][prio_sp+1] != '\0')
1093 prio_optarg = &argv[prio_optind++][prio_sp+1];
1094 else if (++prio_optind >= argc) {
1095 prio_sp = 1;
1096 return ('?');
1097 } else
1098 prio_optarg = argv[prio_optind++];
1099 prio_sp = 1;
1100 } else {
1101 if (argv[prio_optind][++prio_sp] == '\0') {
1102 prio_sp = 1;
1103 prio_optind++;
1105 prio_optarg = NULL;
1107 return (c);