/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License, Version 1.0 only * (the "License"). You may not use this file except in compliance * with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "priocntl.h" /* * This file contains the code implementing the class independent part * of the priocntl command. Most of the useful work for the priocntl * command is done by the class specific sub-commands, the code for * which is elsewhere. The class independent part of the command is * responsible for executing the appropriate class specific sub-commands * and providing any necessary input to the sub-commands. * Code in this file should never assume any knowledge of any specific * scheduler class (other than the SYS class). */ #define CLASSPATH "/usr/lib/class" typedef struct classpids { char clp_clname[PC_CLNMSZ]; pid_t *clp_pidlist; int clp_pidlistsz; int clp_npids; } classpids_t; static char usage[] = "usage: priocntl -l\n\ priocntl -d [-i idtype] [idlist]\n\ priocntl -s [-c class] [c.s.o.] [-i idtype] [idlist]\n\ priocntl -e [-c class] [c.s.o.] command [argument(s)]\n"; static char basenm[BASENMSZ]; static char cmdpath[MAXPATHLEN]; static char *procdir = "/proc"; static int print_classlist(void); static void set_procs(char *, idtype_t, int, char **, char **); static void exec_cmd(char *, char **); static int print_procs(idtype_t, int, char *[]); static void ids2pids(idtype_t, id_t *, int, classpids_t *, int); static void add_pid_tolist(classpids_t *, int, char *, pid_t); static void increase_pidlist(classpids_t *); static boolean_t idmatch(char *, char *, int, char **); /* * These variables are defined to be used in prio_getopt() below. */ static int prio_getopt(); /* LINTED static unused */ static int prio_optopt = 0; static char *prio_optarg = 0; static int prio_optind = 1; static int prio_sp = 1; int main(int argc, char *argv[]) { int c; int lflag, dflag, sflag, eflag, cflag, iflag, csoptsflag; char *clname; char *idtypnm; idtype_t idtype; int idargc; char **idargv; (void) strlcpy(cmdpath, argv[0], MAXPATHLEN); (void) strlcpy(basenm, basename(argv[0]), BASENMSZ); lflag = dflag = sflag = eflag = cflag = iflag = csoptsflag = 0; while ((c = prio_getopt(argc, argv, "ldsec:i:")) != -1) { switch (c) { case 'l': lflag++; break; case 'd': dflag++; break; case 's': sflag++; break; case 'e': eflag++; break; case 'c': cflag++; clname = prio_optarg; break; case 'i': iflag++; idtypnm = prio_optarg; break; case '?': if (strcmp(argv[prio_optind - 1], "-c") == 0 || strcmp(argv[prio_optind - 1], "-i") == 0) { /* * getopt() will return ? if either * of these appear without an argument. */ fatalerr(usage); } /* * We assume for now that any option that * getopt() doesn't recognize (with the * exception of c and i) is intended for a * class specific subcommand. For now we also * require that all class specific options * take an argument (until we can get smarter * about parsing our options). */ csoptsflag++; prio_optind++; prio_sp = 1; break; default: break; } } if (lflag) { if (dflag || sflag || eflag || cflag || iflag || csoptsflag) fatalerr(usage); return (print_classlist()); } else if (dflag) { if (lflag || sflag || eflag || cflag || csoptsflag) fatalerr(usage); if (iflag) { if (str2idtyp(idtypnm, &idtype) == -1) fatalerr("%s: bad idtype %s\n", cmdpath, idtypnm); } else { idtype = P_PID; } if (prio_optind < argc) { idargc = argc - prio_optind; idargv = &argv[prio_optind]; } else { idargc = 0; } return (print_procs(idtype, idargc, idargv)); } else if (sflag) { if (lflag || dflag || eflag) fatalerr(usage); if (iflag) { if (str2idtyp(idtypnm, &idtype) == -1) fatalerr("%s: bad idtype %s\n", cmdpath, idtypnm); } else { idtype = P_PID; } if (cflag == 0) clname = NULL; if (prio_optind < argc) { idargc = argc - prio_optind; idargv = &argv[prio_optind]; } else { idargc = 0; } set_procs(clname, idtype, idargc, idargv, argv); } else if (eflag) { if (lflag || dflag || sflag || iflag) fatalerr(usage); if (cflag == 0) clname = NULL; if (prio_optind >= argc) fatalerr(usage); exec_cmd(clname, argv); } else { fatalerr(usage); } return (0); } /* * Print the heading for the class list and execute the class * specific sub-command with the -l option for each configured class. */ static int print_classlist(void) { id_t cid; int nclass; pcinfo_t pcinfo; static char subcmdpath[128]; int status; pid_t pid; int error = 0; /* * No special privileges required for this operation. * Set the effective UID back to the real UID. */ if (setuid(getuid()) == -1) fatalerr("%s: Can't set effective UID back to real UID\n", cmdpath); if ((nclass = priocntl(0, 0, PC_GETCLINFO, NULL)) == -1) fatalerr("%s: Can't get number of configured classes, priocntl" " system call failed with errno %d\n", cmdpath, errno); (void) printf("CONFIGURED CLASSES\n==================\n\n"); (void) printf("SYS (System Class)\n"); for (cid = 1; cid < nclass; cid++) { (void) printf("\n"); (void) fflush(stdout); pcinfo.pc_cid = cid; if (priocntl(0, 0, PC_GETCLINFO, (caddr_t)&pcinfo) == -1) fatalerr("%s: can't get class name (class ID = %ld)\n", cmdpath, cid); if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s", CLASSPATH, pcinfo.pc_clname, pcinfo.pc_clname, basenm) >= sizeof (subcmdpath)) fatalerr("%s: can't generate %s specific subcommand\n", cmdpath, pcinfo.pc_clname); if ((pid = fork()) == 0) { (void) execl(subcmdpath, subcmdpath, "-l", (char *)0); (void) printf("%s\n", pcinfo.pc_clname); fatalerr("\tCan't execute %s specific subcommand\n", pcinfo.pc_clname); } else if (pid == (pid_t)-1) { (void) printf("%s\n", pcinfo.pc_clname); (void) fprintf(stderr, "Can't execute %s specific subcommand)\n", pcinfo.pc_clname); error = 1; } else { (void) wait(&status); if (status) error = 1; } } return (error); } /* * For each class represented within the set of processes specified by * idtype/idargv, print_procs() executes the class specific sub-command * with the -d option. We pipe to each sub-command a list of pids in * the set belonging to that class. */ static int print_procs(idtype_t idtype, int idargc, char *idargv[]) { int i; id_t id; id_t idlist[NIDS]; int nids; classpids_t *clpids; int nclass; id_t cid; pcinfo_t pcinfo; int pidexists; FILE *pipe_to_subcmd; char subcmd[128]; int error = 0; /* * Build a list of ids eliminating any duplicates in idargv. */ if (idtype == P_ALL) { /* * No idlist should be specified. If one is specified, * it is ignored. */ nids = 0; } else if (idargc == 0) { /* * No ids supplied by user; use current id. */ if (getmyid(idtype, &idlist[0]) == -1) fatalerr("%s: Can't get ID for current process," " idtype = %d\n", cmdpath, idtype); nids = 1; } else { nids = 0; for (i = 0; i < idargc && nids < NIDS; i++) { if (idtype == P_CID) { if ((id = clname2cid(idargv[i])) == -1) { (void) fprintf(stderr, "%s: Invalid or" " unconfigured class %s in idlist" " - ignored\n", cmdpath, idargv[i]); error = 1; } } else { id = (id_t)str2num(idargv[i], INT_MIN, INT_MAX); if (errno) { (void) fprintf(stderr, "%s: Invalid id \"%s\"\n", cmdpath, idargv[i]); error = 1; id = BADPID; } } /* * lsearch(3C) adds ids to the idlist, * eliminating duplicates. */ (void) lsearch((void *)&id, (void *)idlist, (size_t *)&nids, sizeof (id), (int (*)())idcompar); } } if ((nclass = priocntl(0, 0, PC_GETCLINFO, NULL)) == -1) fatalerr("%s: Can't get number of configured classes, priocntl" " system call failed with errno %d\n", cmdpath, errno); if ((clpids = (classpids_t *)malloc(sizeof (classpids_t) * nclass)) == NULL) fatalerr("%s: Can't allocate memory for clpids.\n", cmdpath); for (cid = 1; cid < nclass; cid++) { pcinfo.pc_cid = cid; if (priocntl(0, 0, PC_GETCLINFO, (caddr_t)&pcinfo) == -1) fatalerr("%s: Can't get class name, cid = %ld\n", cmdpath, cid); (void) strncpy(clpids[cid].clp_clname, pcinfo.pc_clname, PC_CLNMSZ); /* * The memory allocation for the pidlist uses realloc(). * A realloc() call is required, when "clp_npids" is * equal to "clp_pidlistsz". */ clpids[cid].clp_pidlist = (pid_t *)NULL; clpids[cid].clp_pidlistsz = 0; clpids[cid].clp_npids = 0; } /* * Build the pidlist. */ ids2pids(idtype, idlist, nids, clpids, nclass); /* * No need for special privileges any more. * Set the effective UID back to the real UID. */ if (setuid(getuid()) == -1) fatalerr("%s: Can't set effective UID back to real UID\n", cmdpath); pidexists = 0; for (cid = 1; cid < nclass; cid++) { if (clpids[cid].clp_npids == 0) continue; pidexists = 1; if (snprintf(subcmd, sizeof (subcmd), "%s/%s/%s%s -d", CLASSPATH, clpids[cid].clp_clname, clpids[cid].clp_clname, basenm) >= sizeof (subcmd)) { (void) fprintf(stderr, "Can't generate %s specific subcommand\n", clpids[cid].clp_clname); error = 1; free(clpids[cid].clp_pidlist); continue; } if ((pipe_to_subcmd = popen(subcmd, "w")) == NULL) { (void) printf("%s\n", clpids[cid].clp_clname); (void) fprintf(stderr, "Can't execute %s specific subcommand\n", clpids[cid].clp_clname); error = 1; free(clpids[cid].clp_pidlist); continue; } (void) fwrite(clpids[cid].clp_pidlist, sizeof (pid_t), clpids[cid].clp_npids, pipe_to_subcmd); if (pclose(pipe_to_subcmd)) error = 1; free(clpids[cid].clp_pidlist); } free(clpids); if (pidexists == 0) fatalerr("%s: Process(es) not found.\n", cmdpath); return (error); } /* * Execute the appropriate class specific sub-command with the arguments * pointed to by subcmdargv. If the user specified a class we simply * exec the sub-command for that class. If no class was specified we * verify that the processes in the set specified by idtype/idargv are * all in the same class and then execute the sub-command for that class. */ static void set_procs(clname, idtype, idargc, idargv, subcmdargv) char *clname; idtype_t idtype; int idargc; char **idargv; char **subcmdargv; { char idstr[PC_IDTYPNMSZ]; char myidstr[PC_IDTYPNMSZ]; char clnmbuf[PC_CLNMSZ]; pcinfo_t pcinfo; static psinfo_t prinfo; static prcred_t prcred; DIR *dirp; struct dirent *dentp; static char pname[100]; char *fname; int procfd; int saverr; static char subcmdpath[128]; boolean_t procinset; id_t id; size_t len; if (clname == NULL && idtype == P_PID && idargc <= 1) { /* * No class specified by user but only one process * in specified set. Get the class the easy way. */ if (idargc == 0) { if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL, PC_KY_CLNAME, clnmbuf, 0) == -1) if (errno == ESRCH) fatalerr("%s: Process not found.\n", cmdpath); else fatalerr("%s: Can't get class of" " current process\npriocntl" " system call failed with" " errno %d\n", cmdpath, errno); } else { /* idargc == 1 */ id = (id_t)str2num(idargv[0], INT_MIN, INT_MAX); if (errno) fatalerr("%s: Invalid id \"%s\"\n", cmdpath, idargv[0]); if (priocntl(P_PID, id, PC_GETXPARMS, NULL, PC_KY_CLNAME, clnmbuf, 0) == -1) if (errno == ESRCH) fatalerr("%s: Process not found.\n", cmdpath); else fatalerr("%s: Can't get class of " " specified process\npriocntl" " system call failed with" " errno %d\n", cmdpath, errno); } clname = clnmbuf; } else if (clname == NULL) { /* * No class specified by user and potentially more * than one process in specified set. Verify that * all procs in set are in the same class. */ if (idargc == 0 && idtype != P_ALL) { /* * No ids supplied by user; use current id. */ if (getmyidstr(idtype, myidstr) == -1) fatalerr("%s: Can't get ID string for current" " process, idtype = %d\n", cmdpath, idtype); } if ((dirp = opendir(procdir)) == NULL) fatalerr("%s: Can't open PROC directory %s\n", cmdpath, procdir); while ((dentp = readdir(dirp)) != NULL) { if (dentp->d_name[0] == '.') /* skip . and .. */ continue; len = snprintf(pname, sizeof (pname), "%s/%s/", procdir, dentp->d_name); /* Really max(sizeof ("psinfo"), sizeof ("cred")) */ if (len + sizeof ("psinfo") > sizeof (pname)) { (void) fprintf(stderr, "%s: skipping %s, name too long.\n", cmdpath, dentp->d_name); continue; } fname = pname + len; retry: (void) strcpy(fname, "psinfo"); if ((procfd = open(pname, O_RDONLY)) < 0) continue; if (read(procfd, &prinfo, sizeof (prinfo)) != sizeof (prinfo)) { saverr = errno; (void) close(procfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) { (void) fprintf(stderr, "%s: Can't get process info for" " %s\n", cmdpath, pname); } continue; } (void) close(procfd); if (idtype == P_UID || idtype == P_GID) { (void) strcpy(fname, "cred"); if ((procfd = open(pname, O_RDONLY)) < 0 || read(procfd, &prcred, sizeof (prcred)) != sizeof (prcred)) { saverr = errno; if (procfd >= 0) (void) close(procfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) { (void) fprintf(stderr, "%s: Can't get process" " credentials for %s\n", cmdpath, pname); } continue; } (void) close(procfd); } if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0) continue; switch (idtype) { case P_PID: itoa((long)prinfo.pr_pid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_PPID: itoa((long)prinfo.pr_ppid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_PGID: itoa((long)prinfo.pr_pgid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_SID: itoa((long)prinfo.pr_sid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_CID: procinset = idmatch(prinfo.pr_lwp.pr_clname, myidstr, idargc, idargv); break; case P_UID: itoa((long)prcred.pr_euid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_GID: itoa((long)prcred.pr_egid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_PROJID: itoa((long)prinfo.pr_projid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_TASKID: itoa((long)prinfo.pr_taskid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_ZONEID: itoa((long)prinfo.pr_zoneid, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_CTID: itoa((long)prinfo.pr_contract, idstr); procinset = idmatch(idstr, myidstr, idargc, idargv); break; case P_ALL: procinset = B_TRUE; break; default: fatalerr("%s: Bad idtype %d in set_procs()\n", cmdpath, idtype); } if (procinset == B_TRUE) { if (clname == NULL) { /* * First proc found in set. */ (void) strcpy(clnmbuf, prinfo.pr_lwp.pr_clname); clname = clnmbuf; } else if (strcmp(clname, prinfo.pr_lwp.pr_clname) != 0) { fatalerr("%s: Specified processes" " from different classes.\n", cmdpath); } } } (void) closedir(dirp); if (clname == NULL) fatalerr("%s: Process(es) not found.\n", cmdpath); } else { /* * User specified class. Check it for validity. */ (void) strcpy(pcinfo.pc_clname, clname); if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) fatalerr("%s: Invalid or unconfigured class %s\n", cmdpath, clname); } /* * No need for special privileges any more. * Set the effective UID back to the real UID. */ if (setuid(getuid()) == -1) fatalerr("%s: Can't set effective UID back to real UID\n", cmdpath); if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s", CLASSPATH, clname, clname, basenm) >= sizeof (subcmdpath)) fatalerr("%s: can't generate %s specific subcommand\n", cmdpath, clname); subcmdargv[0] = subcmdpath; (void) execv(subcmdpath, subcmdargv); fatalerr("%s: Can't execute %s sub-command\n", cmdpath, clname); } /* * Execute the appropriate class specific sub-command with the arguments * pointed to by subcmdargv. If the user specified a class we simply * exec the sub-command for that class. If no class was specified we * execute the sub-command for our own current class. */ static void exec_cmd(clname, subcmdargv) char *clname; char **subcmdargv; { pcinfo_t pcinfo; char clnmbuf[PC_CLNMSZ]; char subcmdpath[128]; /* * No special privileges required for this operation. * Set the effective UID back to the real UID. */ if (setuid(getuid()) == -1) fatalerr("%s: Can't set effective UID back to real UID\n", cmdpath); if (clname == NULL) { if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL, PC_KY_CLNAME, clnmbuf, 0) == -1) fatalerr("%s: Can't get class name of current process\n" "priocntl system call failed with errno %d\n", cmdpath, errno); clname = clnmbuf; } else { /* * User specified class. Check it for validity. */ (void) strcpy(pcinfo.pc_clname, clname); if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1) fatalerr("%s: Invalid or unconfigured class %s\n", cmdpath, clname); } if (snprintf(subcmdpath, sizeof (subcmdpath), "%s/%s/%s%s", CLASSPATH, clname, clname, basenm) >= sizeof (subcmdpath)) fatalerr("%s: can't generate %s specific subcommand\n", cmdpath, clname); subcmdargv[0] = subcmdpath; (void) execv(subcmdpath, subcmdargv); fatalerr("%s: Can't execute %s sub-command\n", cmdpath, clname); } /* * Fill in the classpids structures in the array pointed to by clpids * with pids for the processes in the set specified by idtype/idlist. * We read the /proc//psinfo file to get the necessary process * information. */ static void ids2pids(idtype, idlist, nids, clpids, nclass) idtype_t idtype; id_t *idlist; int nids; classpids_t *clpids; int nclass; { static psinfo_t prinfo; static prcred_t prcred; DIR *dirp; struct dirent *dentp; char pname[100]; char *fname; int procfd; int saverr; int i; char *clname; size_t len; if ((dirp = opendir(procdir)) == NULL) fatalerr("%s: Can't open PROC directory %s\n", cmdpath, procdir); while ((dentp = readdir(dirp)) != NULL) { if (dentp->d_name[0] == '.') /* skip . and .. */ continue; len = snprintf(pname, sizeof (pname), "%s/%s/", procdir, dentp->d_name); /* Really max(sizeof ("psinfo"), sizeof ("cred")) */ if (len + sizeof ("psinfo") > sizeof (pname)) { (void) fprintf(stderr, "%s: skipping %s, name too long.\n", cmdpath, dentp->d_name); continue; } fname = pname + len; retry: (void) strcpy(fname, "psinfo"); if ((procfd = open(pname, O_RDONLY)) < 0) continue; if (read(procfd, &prinfo, sizeof (prinfo)) != sizeof (prinfo)) { saverr = errno; (void) close(procfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) { (void) fprintf(stderr, "%s: Can't get process info for %s\n", cmdpath, pname); } continue; } (void) close(procfd); if (idtype == P_UID || idtype == P_GID) { (void) strcpy(fname, "cred"); if ((procfd = open(pname, O_RDONLY)) < 0 || read(procfd, &prcred, sizeof (prcred)) != sizeof (prcred)) { saverr = errno; (void) close(procfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) { (void) fprintf(stderr, "%s: Can't get process credentials" " for %s\n", cmdpath, pname); } continue; } (void) close(procfd); } if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0) continue; switch (idtype) { case P_PID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_pid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_PPID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_ppid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_PGID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_pgid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_SID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_sid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_CID: for (i = 0; i < nids; i++) { clname = clpids[idlist[i]].clp_clname; if (strcmp(clname, prinfo.pr_lwp.pr_clname) == 0) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_UID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prcred.pr_euid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_GID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prcred.pr_egid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_PROJID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_projid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_TASKID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_taskid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_ZONEID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_zoneid) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_CTID: for (i = 0; i < nids; i++) { if (idlist[i] == (id_t)prinfo.pr_contract) add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); } break; case P_ALL: add_pid_tolist(clpids, nclass, prinfo.pr_lwp.pr_clname, prinfo.pr_pid); break; default: fatalerr("%s: Bad idtype %d in ids2pids()\n", cmdpath, idtype); } } (void) closedir(dirp); } /* * Search the array pointed to by clpids for the classpids * structure corresponding to clname and add pid to its * pidlist. */ static void add_pid_tolist(clpids, nclass, clname, pid) classpids_t *clpids; int nclass; char *clname; pid_t pid; { classpids_t *clp; for (clp = clpids; clp != &clpids[nclass]; clp++) { if (strcmp(clp->clp_clname, clname) == 0) { if (clp->clp_npids == clp->clp_pidlistsz) increase_pidlist(clp); (clp->clp_pidlist)[clp->clp_npids] = pid; clp->clp_npids++; return; } } } static void increase_pidlist(classpids_t *clp) { if ((clp->clp_pidlist = realloc(clp->clp_pidlist, (clp->clp_pidlistsz + NPIDS) * sizeof (pid_t))) == NULL) /* * The pidlist is filled up and we cannot increase the size. */ fatalerr("%s: Can't allocate memory for pidlist.\n", cmdpath); clp->clp_pidlistsz += NPIDS; } /* * Compare id strings for equality. If idargv contains ids * (idargc > 0) compare idstr to each id in idargv, otherwise * just compare to curidstr. */ static boolean_t idmatch(idstr, curidstr, idargc, idargv) char *idstr; char *curidstr; int idargc; char **idargv; { int i; if (idargc == 0) { if (strcmp(curidstr, idstr) == 0) return (B_TRUE); } else { for (i = 0; i < idargc; i++) { if (strcmp(idargv[i], idstr) == 0) return (B_TRUE); } } return (B_FALSE); } /* * This is a copy of the getopt() function found in libc:getopt.c. A separate * copy is required to fix the bug id #1114636. To fix the problem we need to * reset the _sp to 1. Since _sp in libc:getopt() is not exposed, a copy of * the getopt() is kept so that prio_sp can be reset to 1. */ static int prio_getopt(argc, argv, opts) int argc; #ifdef __STDC__ char *const *argv, *opts; #else char **argv, *opts; #endif { register char c; register char *cp; if (prio_sp == 1) if (prio_optind >= argc || argv[prio_optind][0] != '-' || argv[prio_optind][1] == '\0') return (EOF); else if (strcmp(argv[prio_optind], "--") == NULL) { prio_optind++; return (EOF); } prio_optopt = c = (unsigned char)argv[prio_optind][prio_sp]; if (c == ':' || (cp = strchr(opts, c)) == NULL) { if (argv[prio_optind][++prio_sp] == '\0') { prio_optind++; prio_sp = 1; } return ('?'); } if (*++cp == ':') { if (argv[prio_optind][prio_sp+1] != '\0') prio_optarg = &argv[prio_optind++][prio_sp+1]; else if (++prio_optind >= argc) { prio_sp = 1; return ('?'); } else prio_optarg = argv[prio_optind++]; prio_sp = 1; } else { if (argv[prio_optind][++prio_sp] == '\0') { prio_sp = 1; prio_optind++; } prio_optarg = NULL; } return (c); }