#include <locale.h>
#include <sys/zone.h>
#include "auditr.h"
struct obj_ent {
char *obj_str;
int obj_flag;
};
typedef struct obj_ent obj_ent_t;
static obj_ent_t obj_tbl[] = {
{ "file", OBJ_PATH },
{ "filegroup", OBJ_FGROUP },
{ "fileowner", OBJ_FOWNER },
{ "fmri", OBJ_FMRI },
{ "lp", OBJ_LP },
{ "msgqid", OBJ_MSG },
{ "msgqgroup", OBJ_MSGGROUP },
{ "msgqowner", OBJ_MSGOWNER },
{ "path", OBJ_PATH },
{ "pid", OBJ_PROC },
{ "procgroup", OBJ_PGROUP },
{ "procowner", OBJ_POWNER },
{ "semid", OBJ_SEM },
{ "semgroup", OBJ_SEMGROUP },
{ "semowner", OBJ_SEMOWNER },
{ "shmid", OBJ_SHM },
{ "shmgroup", OBJ_SHMGROUP },
{ "shmowner", OBJ_SHMOWNER },
{ "sock", OBJ_SOCK },
{ "user", OBJ_USER } };
extern int derive_date(char *, struct tm *);
extern int parse_time(char *, int);
extern char *re_comp2(char *);
extern time_t tm_to_secs(struct tm *);
static int a_isnum(char *, int);
static int check_file(audit_fcb_t *, int);
static int gather_dir(char *);
static audit_pcb_t *get_next_pcb(char *);
static obj_ent_t *obj_lkup(char *);
static int proc_class(char *);
static int proc_date(char *, int);
static int proc_file(char *, int);
static int process_fileopt(int, char *argv[], int);
static int proc_group(char *, gid_t *);
static int proc_id(char *, int);
static int proc_object(char *);
static void proc_pcb(audit_pcb_t *, char *, int);
static int proc_label(char *);
static int proc_subject(char *);
static int proc_sid(char *);
static int proc_type(char *);
static int proc_user(char *, uid_t *);
static int proc_zonename(char *);
static int proc_fmri(char *);
int
process_options(int argc, char **argv)
{
int opt;
int error = FALSE;
int error_combo = FALSE;
extern int optind;
extern char *optarg;
static char *options = "ACD:M:NQR:S:VO:"
"a:b:c:d:e:g:j:l:m:o:r:s:t:u:z:";
error_str = gettext("general error");
zonename = NULL;
start_over:
while ((opt = getopt(argc, argv, options)) != EOF) {
switch (opt) {
case 'A':
f_all = TRUE;
break;
case 'C':
f_complete = TRUE;
break;
case 'D':
f_all = f_complete = TRUE;
f_outfile = optarg;
f_delete = TRUE;
break;
case 'M':
f_machine = optarg;
break;
case 'N':
new_mode = TRUE;
break;
case 'Q':
f_quiet = TRUE;
break;
case 'R':
f_root = optarg;
break;
case 'S':
f_server = optarg;
break;
case 'V':
f_verbose = TRUE;
break;
case 'O':
f_outfile = optarg;
break;
case 'a':
case 'b':
case 'd':
if (proc_date(optarg, opt))
error = TRUE;
break;
case 'j':
if (proc_subject(optarg))
error = TRUE;
break;
case 'm':
if (proc_type(optarg))
error = TRUE;
break;
case 'o':
if (proc_object(optarg))
error = TRUE;
break;
case 'c':
if (proc_class(optarg))
error = TRUE;
break;
case 'u':
case 'e':
case 'r':
case 'f':
case 'g':
if (proc_id(optarg, opt))
error = TRUE;
break;
case 'l':
if (!is_system_labeled()) {
(void) fprintf(stderr,
gettext("%s option 'l' requires "
"Trusted Extensions.\n"), ar);
return (-1);
}
if (proc_label(optarg))
error = TRUE;
break;
case 's':
if (proc_sid(optarg))
error = TRUE;
break;
case 'z':
if (proc_zonename(optarg))
error = TRUE;
break;
case 't':
default:
return (-1);
}
if (error) {
(void) fprintf(stderr,
gettext("%s command line error - %s.\n"),
ar, error_str);
return (-1);
}
}
if (optind < argc) {
if (argv[optind][0] == '-' && argv[optind][1] == '\0') {
optind++;
f_stdin = TRUE;
goto start_over;
}
}
if (m_before == 0)
m_before = MAXLONG;
if ((f_machine || f_server || f_root) && (argc != optind)) {
error_str = gettext(
"no filenames allowed with 'M' or 'S' or 'R' options");
error_combo = TRUE;
}
if (m_after >= m_before) {
error_str =
gettext("'a' parameter must be before 'b' parameter");
error_combo = TRUE;
}
if (f_delete &&
(!f_complete || !f_all || !f_outfile)) {
error_str = gettext(
"'C', 'A', and 'O' must be specified with 'D'");
error_combo = TRUE;
}
if (f_stdin && (argc != optind)) {
error_str = gettext("no filenames allowed with '-' option");
error_combo = TRUE;
}
if (error_combo) {
(void) fprintf(stderr,
gettext("%s command line error - %s.\n"), ar, error_str);
return (-1);
}
if (f_root == NULL)
f_root = "/etc/security/audit";
return (process_fileopt(argc, argv, optind));
}
int
proc_subject(char *optarg)
{
if (flags & M_SUBJECT) {
error_str = gettext("'j' option specified multiple times");
return (-1);
}
flags |= M_SUBJECT;
subj_id = atol(optarg);
return (0);
}
int
proc_sid(char *optarg)
{
if (flags & M_SID) {
error_str = gettext("'s' option specified multiple times");
return (-1);
}
flags |= M_SID;
m_sid = (au_asid_t)atol(optarg);
return (0);
}
int
proc_object(char *optarg)
{
char *obj_str;
char *obj_val;
char *obj_arg;
int err;
obj_ent_t *oep;
struct hostent *he;
if (flags & M_OBJECT) {
error_str = gettext("'o' option specified multiple times");
return (-1);
}
flags |= M_OBJECT;
if ((obj_arg = strdup(optarg)) == (char *)0)
return (-1);
if ((obj_str = strtok(optarg, "=")) == (char *)0 ||
(oep = obj_lkup(obj_str)) == (obj_ent_t *)0 ||
(obj_val = strtok((char *)0, "=")) == (char *)0) {
(void) sprintf(errbuf, gettext("invalid object arg (%s)"),
obj_arg);
error_str = errbuf;
return (-1);
}
obj_flag = oep->obj_flag;
switch (obj_flag) {
case OBJ_PATH:
if ((error_str = re_comp2(obj_val)) != (char *)NULL) {
return (-1);
}
return (0);
case OBJ_SOCK:
if (!a_isnum(obj_val, TRUE)) {
obj_id = atol(obj_val);
socket_flag = SOCKFLG_PORT;
return (0);
}
if (*obj_val == '0') {
(void) sscanf(obj_val, "%x", (uint_t *)&obj_id);
socket_flag = SOCKFLG_PORT;
return (0);
}
he = getipnodebyname((const void *)obj_val, AF_INET6, 0, &err);
if (he == 0) {
he = getipnodebyname((const void *)obj_val, AF_INET,
0, &err);
if (he == 0) {
(void) sprintf(errbuf,
gettext("invalid machine name (%s)"),
obj_val);
error_str = errbuf;
return (-1);
}
}
if (he->h_addrtype == AF_INET6) {
if (IN6_IS_ADDR_V4MAPPED(
(in6_addr_t *)he->h_addr_list[0])) {
(void) memcpy(&obj_id,
he->h_addr_list[0] + 12, 4);
ip_type = AU_IPv4;
} else {
(void) memcpy(ip_ipv6, he->h_addr_list[0], 16);
ip_type = AU_IPv6;
}
} else {
(void) memcpy(&obj_id, he->h_addr_list[0], 4);
ip_type = AU_IPv4;
}
freehostent(he);
socket_flag = SOCKFLG_MACHINE;
return (0);
case OBJ_MSG:
case OBJ_SEM:
case OBJ_SHM:
case OBJ_PROC:
obj_id = atol(obj_val);
return (0);
case OBJ_FGROUP:
case OBJ_MSGGROUP:
case OBJ_SEMGROUP:
case OBJ_SHMGROUP:
case OBJ_PGROUP:
return (proc_group(obj_val, &obj_group));
case OBJ_FOWNER:
case OBJ_MSGOWNER:
case OBJ_SEMOWNER:
case OBJ_SHMOWNER:
case OBJ_POWNER:
return (proc_user(obj_val, &obj_owner));
case OBJ_FMRI:
return (proc_fmri(obj_val));
case OBJ_USER:
return (proc_user(obj_val, &obj_user));
case OBJ_LP:
default:
(void) sprintf(errbuf, gettext("invalid object type (%s)"),
obj_str);
error_str = errbuf;
return (-1);
}
}
obj_ent_t *
obj_lkup(char *obj_str)
{
int i;
for (i = 0; i < sizeof (obj_tbl) / sizeof (obj_ent_t); i++)
if (strcmp(obj_str, obj_tbl[i].obj_str) == 0)
return (&obj_tbl[i]);
return (NULL);
}
int
proc_type(char *optstr)
{
struct au_event_ent *aep;
if (flags & M_TYPE) {
error_str = gettext("'m' option specified multiple times");
return (-1);
}
flags |= M_TYPE;
m_type = 0;
if (a_isnum(optstr, TRUE)) {
if ((aep = getauevnam(optstr)) != NULL)
m_type = aep->ae_number;
} else {
if ((aep = getauevnum((au_event_t)atoi(optstr))) !=
(struct au_event_ent *)NULL)
m_type = aep->ae_number;
}
if ((m_type == 0)) {
(void) sprintf(errbuf, gettext("invalid event (%s)"), optstr);
error_str = errbuf;
return (-1);
}
return (0);
}
int
a_isnum(char *str, int leading)
{
char *strs;
if ((leading == TRUE) && (*str == '-' || *str == '+'))
strs = str + 1;
else
strs = str;
if (strlen(strs) == strspn(strs, "0123456789"))
return (0);
else
return (1);
}
int
proc_id(char *optstr, int opt)
{
switch (opt) {
case 'e':
if (flags & M_USERE) {
error_str = gettext(
"'e' option specified multiple times");
return (-1);
}
flags |= M_USERE;
return (proc_user(optstr, &m_usere));
case 'f':
if (flags & M_GROUPE) {
error_str = gettext(
"'f' option specified multiple times");
return (-1);
}
flags |= M_GROUPE;
return (proc_group(optstr, &m_groupe));
case 'r':
if (flags & M_USERR) {
error_str = gettext(
"'r' option specified multiple times");
return (-1);
}
flags |= M_USERR;
return (proc_user(optstr, &m_userr));
case 'u':
if (flags & M_USERA) {
error_str = gettext(
"'u' option specified multiple times");
return (-1);
}
flags |= M_USERA;
return (proc_user(optstr, &m_usera));
case 'g':
if (flags & M_GROUPR) {
error_str = gettext(
"'g' option specified multiple times");
return (-1);
}
flags |= M_GROUPR;
return (proc_group(optstr, &m_groupr));
default:
(void) sprintf(errbuf, gettext("'%c' unknown option"), opt);
error_str = errbuf;
return (-1);
}
}
int
proc_group(char *optstr, gid_t *gid)
{
struct group *grp;
if ((grp = getgrnam(optstr)) == NULL) {
if (!a_isnum(optstr, TRUE)) {
*gid = (gid_t)atoi(optstr);
return (0);
}
(void) sprintf(errbuf, gettext("group name invalid (%s)"),
optstr);
error_str = errbuf;
return (-1);
}
*gid = grp->gr_gid;
return (0);
}
int
proc_user(char *optstr, uid_t *uid)
{
struct passwd *usr;
if ((usr = getpwnam(optstr)) == NULL) {
if (!a_isnum(optstr, TRUE)) {
*uid = (uid_t)atoi(optstr);
return (0);
}
(void) sprintf(errbuf, gettext("user name invalid (%s)"),
optstr);
error_str = errbuf;
return (-1);
}
*uid = usr->pw_uid;
return (0);
}
int
proc_date(char *optstr, int opt)
{
static int m_day = FALSE;
if (opt == 'd') {
if (m_day == TRUE) {
error_str = gettext(
"'d' option may not be used with 'a' or 'b'");
return (-1);
}
m_day = TRUE;
}
if ((opt == 'd') && (m_before || m_after)) {
error_str = gettext(
"'d' option may not be used with 'a' or 'b'");
return (-1);
}
if ((opt == 'a' || opt == 'b') && m_day) {
error_str = gettext(
"'a' or 'b' option may not be used with 'd'");
return (-1);
}
if ((opt == 'a') && (m_after != 0)) {
error_str = gettext("'a' option specified multiple times");
return (-1);
}
if ((opt == 'b') && (m_before != 0)) {
error_str = gettext("'b' option specified multiple times");
return (-1);
}
if (parse_time(optstr, opt))
return (-1);
return (0);
}
int
proc_class(char *optstr)
{
if (flags & M_CLASS) {
error_str = gettext("'c' option specified multiple times");
return (-1);
}
flags |= M_CLASS;
if (getauditflagsbin(optstr, &mask) != 0) {
(void) sprintf(errbuf, gettext("unknown class (%s)"), optstr);
error_str = errbuf;
return (-1);
}
if (mask.am_success != mask.am_failure) {
flags |= M_SORF;
}
return (0);
}
int
process_fileopt(int argc, char **argv, int optindex)
{
int f_mode = FM_ALLDIR;
char f_dr[MAXNAMLEN+1];
char *f_dir = f_dr;
char *fname;
static char *std = "standard input";
audit_fcb_t *fcb;
DIR * dirp;
struct dirent *dp;
audit_pcb_t *pcb;
if (f_stdin) {
fcb = (audit_fcb_t *)a_calloc(1, sizeof (*fcb) + strlen(std));
(void) strcpy(fcb->fcb_file, std);
fcb->fcb_suffix = fcb->fcb_name = fcb->fcb_file;
fcb->fcb_next = NULL;
fcb->fcb_start = 0;
fcb->fcb_end = MAXLONG;
if ((pcb = get_next_pcb((char *)NULL)) == (audit_pcb_t *)NULL)
return (-1);
pcb->pcb_suffix = fcb->fcb_file;
pcb->pcb_dfirst = pcb->pcb_first = fcb;
pcb->pcb_dlast = pcb->pcb_last = fcb;
pcb->pcb_cur = fcb;
}
else if (argc == optindex) {
if (f_server) {
if (strchr(f_server, '/')) {
f_dir = f_server;
f_mode = FM_ALLFILE;
} else {
f_dir[0] = '\0';
(void) strcat(f_dir, f_root);
(void) strcat(f_dir, "/");
(void) strcat(f_dir, f_server);
f_mode = FM_ALLFILE;
}
}
if (f_mode == FM_ALLFILE) {
if (gather_dir(f_dir)) {
return (-1);
}
} else {
if ((dirp = opendir(f_root)) == NULL) {
(void) sprintf(errbuf, gettext(
"%s can't open directory %s"), ar, f_root);
perror(errbuf);
return (-1);
}
for (dp = readdir(dirp);
dp != NULL; dp = readdir(dirp)) {
if (dp->d_name[0] == '.')
continue;
f_dir[0] = '\0';
(void) strcat(f_dir, f_root);
(void) strcat(f_dir, "/");
(void) strcat(f_dir, dp->d_name);
if (gather_dir(f_dir))
return (-1);
}
(void) closedir(dirp);
}
} else {
f_cmdline = TRUE;
for (; optindex < argc; optindex++) {
fname = argv[optindex];
if (proc_file(fname, FALSE))
return (-1);
}
}
return (0);
}
int
gather_dir(char *dir)
{
char dname[MAXNAMLEN+1];
char fname[MAXNAMLEN+1];
DIR * dirp;
struct dirent *dp;
(void) snprintf(dname, sizeof (dname), "%s/files", dir);
if ((dirp = opendir(dname)) == NULL) {
if (errno != ENOTDIR) {
(void) sprintf(errbuf,
gettext("%s can't open directory - %s"), ar, dname);
perror(errbuf);
}
return (0);
}
for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
if (dp->d_name[0] == '.')
continue;
fname[0] = '\0';
(void) strcat(fname, dname);
(void) strcat(fname, "/");
(void) strcat(fname, dp->d_name);
if (proc_file(fname, TRUE))
return (-1);
}
(void) closedir(dirp);
return (0);
}
int
proc_file(char *fname, int mode)
{
int reject = FALSE;
size_t len;
struct stat stat_buf;
audit_fcb_t *fcb, *fcbp, *fcbprev;
audit_pcb_t *pcb;
if (stat(fname, &stat_buf)) {
return (0);
}
if (!S_ISREG(stat_buf.st_mode))
return (0);
len = sizeof (audit_fcb_t) + strlen(fname);
fcb = (audit_fcb_t *)a_calloc(1, len);
(void) strcpy(fcb->fcb_file, fname);
if (check_file(fcb, mode)) {
if (!f_quiet) {
(void) fprintf(stderr, "%s %s:\n %s.\n", ar,
error_str, fname);
}
reject = TRUE;
} else {
if (f_complete && (fcb->fcb_flags & FF_NOTTERM) && !f_cmdline)
reject = TRUE;
if (!f_all && (fcb->fcb_end < m_after))
reject = TRUE;
if (f_machine) {
if (strlen(fcb->fcb_suffix) != strlen(f_machine) ||
(strcmp(fcb->fcb_suffix, f_machine) != 0)) {
reject = TRUE;
}
}
}
if (reject == FALSE) {
filenum++;
fcb->fcb_next = NULL;
if ((pcb = get_next_pcb(fcb->fcb_suffix)) == NULL) {
return (-1);
}
fcbp = pcb->pcb_first;
fcbprev = NULL;
while (fcbp != NULL) {
if (fcb->fcb_start < fcbp->fcb_start) {
if (fcbprev)
fcbprev->fcb_next = fcb;
else
pcb->pcb_dfirst = pcb->pcb_first = fcb;
fcb->fcb_next = fcbp;
break;
}
fcbprev = fcbp;
fcbp = fcbp->fcb_next;
}
if (!fcb->fcb_next) {
if (pcb->pcb_first == NULL)
pcb->pcb_dfirst = pcb->pcb_first = fcb;
pcb->pcb_dlast = pcb->pcb_last = fcb;
if (fcbprev)
fcbprev->fcb_next = fcb;
}
} else {
free((char *)fcb);
}
return (0);
}
int
check_file(audit_fcb_t *fcb, int do_check)
{
int ret;
char *namep, *slp;
char errb[256];
struct tm tme;
errb[0] = '\0';
for (slp = namep = fcb->fcb_file; *namep; namep++) {
if (*namep == '/')
slp = namep + 1;
}
if (do_check == FALSE) {
fcb->fcb_end = MAXLONG;
fcb->fcb_suffix = NULL;
fcb->fcb_name = slp;
ret = 0;
} else {
ret = -1;
}
if ((int)strlen(slp) < 31) {
(void) sprintf(errbuf, gettext("filename too short (%d)"),
strlen(slp));
error_str = errbuf;
return (ret);
}
namep = (char *)a_calloc(1, strlen(slp) + 1);
(void) strcpy(namep, slp);
if (namep[14] != '.' || namep[29] != '.') {
(void) sprintf(errbuf,
gettext("invalid filename format (%c or %c)"), namep[14],
namep[29]);
error_str = errbuf;
free(namep);
return (ret);
}
namep[14] = '\0';
namep[29] = '\0';
if (derive_date(namep, &tme)) {
(void) strcat(errb, gettext("starting time-stamp invalid - "));
(void) strcat(errb, error_str);
(void) strcpy(errbuf, errb);
error_str = errbuf;
free(namep);
return (ret);
}
fcb->fcb_start = tm_to_secs(&tme);
if (strcmp(&namep[15], "not_terminated") == 0) {
fcb->fcb_end = MAXLONG;
if (do_check == TRUE)
fcb->fcb_flags |= FF_NOTTERM;
} else if (derive_date(&namep[15], &tme)) {
(void) strcat(errb, gettext("ending time-stamp invalid - "));
(void) strcat(errb, error_str);
(void) strcpy(errbuf, errb);
error_str = errbuf;
free(namep);
return (ret);
} else {
fcb->fcb_end = tm_to_secs(&tme);
}
fcb->fcb_name = slp;
fcb->fcb_suffix = &slp[30];
free(namep);
return (0);
}
audit_pcb_t *
get_next_pcb(char *suffix)
{
int i = 0;
int zerosize;
unsigned int size;
audit_pcb_t *pcb;
while (i < pcbsize) {
pcb = &audit_pcbs[i++];
if (pcb->pcb_first == NULL) {
proc_pcb(pcb, suffix, i);
return (pcb);
}
if (suffix) {
if (strcmp(pcb->pcb_suffix, suffix) == 0)
return (pcb);
}
}
pcbsize += PCB_INC;
size = pcbsize * sizeof (audit_pcb_t);
zerosize = size - ((pcbsize - PCB_INC) * sizeof (audit_pcb_t));
if ((audit_pcbs = (audit_pcb_t *)realloc((char *)audit_pcbs, size)) ==
NULL) {
(void) sprintf(errbuf,
gettext("%s memory reallocation failed (%d bytes)"), ar,
size);
perror(errbuf);
audit_stats();
return (NULL);
}
(void) memset((void *) & audit_pcbs[pcbsize-PCB_INC], 0,
(size_t)zerosize);
pcb = &audit_pcbs[pcbsize-PCB_INC];
proc_pcb(pcb, suffix, pcbsize - PCB_INC);
return (pcb);
}
void
proc_pcb(audit_pcb_t *pcb, char *suffix, int i)
{
if (suffix)
pcb->pcb_suffix = suffix;
pcbnum++;
pcb->pcb_size = AUDITBUFSIZE;
pcb->pcb_rec = (char *)a_calloc(1, AUDITBUFSIZE);
pcb->pcb_time = -1;
pcb->pcb_flags |= PF_USEFILE;
pcb->pcb_procno = i;
}
int
proc_label(char *optstr)
{
char *p;
int error;
if (flags & M_LABEL) {
error_str = gettext("'l' option specified multiple times");
return (-1);
}
flags |= M_LABEL;
if ((m_label = malloc(sizeof (m_range_t))) == NULL) {
return (-1);
}
m_label->lower_bound = NULL;
m_label->upper_bound = NULL;
p = strchr(optstr, ';');
if (p == NULL) {
if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
L_NO_CORRECTION, &error) == -1) {
(void) sprintf(errbuf,
gettext("invalid sensitivity label (%s) err %d"),
optstr, error);
error_str = errbuf;
goto errout;
}
m_label->upper_bound = m_label->lower_bound;
return (0);
}
if (p == optstr) {
if (str_to_label(ADMIN_LOW, &m_label->lower_bound, MAC_LABEL,
L_NO_CORRECTION, &error) == -1) {
goto errout;
}
p++;
if (*p == '\0') {
if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
goto errout;
}
} else {
if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
L_NO_CORRECTION, &error) == -1) {
(void) sprintf(errbuf, gettext(
"invalid sensitivity label (%s) err %d"),
p, error);
error_str = errbuf;
goto errout;
}
}
return (0);
}
*p++ = '\0';
if (str_to_label(optstr, &m_label->lower_bound, MAC_LABEL,
L_NO_CORRECTION, &error) == -1) {
(void) sprintf(errbuf,
gettext("invalid sensitivity label (%s) err %d"), optstr,
error);
error_str = errbuf;
goto errout;
}
if (*p == '\0') {
if (str_to_label(ADMIN_HIGH, &m_label->upper_bound,
MAC_LABEL, L_NO_CORRECTION, &error) == -1) {
goto errout;
}
} else {
if (str_to_label(p, &m_label->upper_bound, MAC_LABEL,
L_NO_CORRECTION, &error) == -1) {
(void) sprintf(errbuf,
gettext("invalid sensitivity label (%s) err %d"),
p, error);
error_str = errbuf;
goto errout;
}
}
if (!bldominates(m_label->upper_bound, m_label->lower_bound)) {
*--p = ';';
(void) sprintf(errbuf,
gettext("invalid sensitivity label range (%s)"), optstr);
error_str = errbuf;
goto errout;
}
return (0);
errout:
m_label_free(m_label->upper_bound);
m_label_free(m_label->lower_bound);
free(m_label);
return (-1);
}
static int
proc_zonename(char *optstr)
{
size_t length = strlen(optstr);
if ((length < 1) || (length > ZONENAME_MAX)) {
(void) sprintf(errbuf,
gettext("invalid zone name: %s"), optstr);
error_str = errbuf;
return (-1);
}
zonename = strdup(optstr);
flags |= M_ZONENAME;
return (0);
}
static int
proc_fmri(char *optstr)
{
if (strpbrk(optstr, "*?[") != NULL) {
fmri.sp_type = PATTERN_GLOB;
if (optstr[0] == '*' ||
(strlen(optstr) >= 4 && optstr[3] == ':')) {
fmri.sp_arg = strdup(optstr);
} else if ((fmri.sp_arg = malloc(strlen(optstr) + 6)) != NULL) {
(void) snprintf(fmri.sp_arg, strlen(optstr) + 6,
"svc:/%s", optstr);
}
} else {
fmri.sp_type = PATTERN_PARTIAL;
fmri.sp_arg = strdup(optstr);
}
if (fmri.sp_arg == NULL)
return (-1);
return (0);
}