#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <wait.h>
#include <search.h>
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/param.h>
#include <sys/procset.h>
#include <sys/priocntl.h>
#include <procfs.h>
#include <macros.h>
#include <libgen.h>
#include <limits.h>
#include <errno.h>
#include "priocntl.h"
#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 **);
static int prio_getopt();
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) {
fatalerr(usage);
}
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);
}
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;
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);
}
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;
if (idtype == P_ALL) {
nids = 0;
} else if (idargc == 0) {
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;
}
}
(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);
clpids[cid].clp_pidlist = (pid_t *)NULL;
clpids[cid].clp_pidlistsz = 0;
clpids[cid].clp_npids = 0;
}
ids2pids(idtype, idlist, nids, clpids, nclass);
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);
}
static void
set_procs(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) {
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 {
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) {
if (idargc == 0 && idtype != P_ALL) {
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] == '.')
continue;
len = snprintf(pname, sizeof (pname), "%s/%s/",
procdir, dentp->d_name);
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) {
(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 {
(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 (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);
}
static void
exec_cmd(char *clname, char **subcmdargv)
{
pcinfo_t pcinfo;
char clnmbuf[PC_CLNMSZ];
char subcmdpath[128];
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 {
(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);
}
static void
ids2pids(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] == '.')
continue;
len = snprintf(pname, sizeof (pname), "%s/%s/",
procdir, dentp->d_name);
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);
}
static void
add_pid_tolist(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)
fatalerr("%s: Can't allocate memory for pidlist.\n", cmdpath);
clp->clp_pidlistsz += NPIDS;
}
static boolean_t
idmatch(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);
}
static int
prio_getopt(int argc, char * const *argv, char *opts)
{
char c;
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], "--") == 0) {
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);
}