#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pwd.h>
#include <string.h>
#include <deflt.h>
#include <libintl.h>
#include <locale.h>
#include <user_attr.h>
#include <prof_attr.h>
#include <auth_attr.h>
#define EXIT_OK 0
#define EXIT_FATAL 1
#define EXIT_NON_FATAL 2
#ifndef TEXT_DOMAIN
#define TEXT_DOMAIN "SYS_TEST"
#endif
#define INCRAUTHS 512
typedef struct cbs {
int auth_cnt;
int auth_max;
char **auths;
} cbs_t;
static int show_auths(char *, int);
static int add_auth(const char *, void *, void *);
static void free_auths(cbs_t *);
static void simplify(cbs_t *);
static char *progname = "auths";
int
main(int argc, char *argv[])
{
int status = EXIT_OK;
(void) setlocale(LC_ALL, "");
(void) textdomain(TEXT_DOMAIN);
switch (argc) {
case 1:
status = show_auths(NULL, 0);
break;
case 2:
status = show_auths(argv[argc-1], 0);
break;
default:
while (*++argv) {
status = show_auths(*argv, 1);
if (status == EXIT_FATAL) {
break;
}
}
break;
}
status = (status == EXIT_OK) ? status : EXIT_FATAL;
return (status);
}
static int
show_auths(char *username, int print_name)
{
int status = EXIT_OK;
struct passwd *pw;
int i;
cbs_t cbs = { 0, 0, NULL };
if (username == NULL) {
if ((pw = getpwuid(getuid())) == NULL) {
status = EXIT_NON_FATAL;
(void) fprintf(stderr, "%s: ", progname);
(void) fprintf(stderr, gettext("No passwd entry\n"));
return (status);
}
username = pw->pw_name;
} else if (getpwnam(username) == NULL) {
status = EXIT_NON_FATAL;
(void) fprintf(stderr, "%s: %s : ", progname, username);
(void) fprintf(stderr, gettext("No such user\n"));
return (status);
}
(void) _enum_auths(username, add_auth, NULL, &cbs);
if (cbs.auth_cnt == 0)
status = EXIT_NON_FATAL;
if (status == EXIT_NON_FATAL) {
(void) fprintf(stderr, "%s: %s: ", progname, username);
(void) fprintf(stderr, gettext("No authorizations\n"));
} else {
simplify(&cbs);
if (print_name)
(void) printf("%s: ", username);
for (i = 0; i < cbs.auth_cnt - 1; i++)
(void) printf("%s,", cbs.auths[i]);
(void) printf("%s\n", cbs.auths[cbs.auth_cnt - 1]);
free_auths(&cbs);
}
return (status);
}
static int
add_auth(const char *authname, void *ctxt, void *res)
{
cbs_t *cbs = res;
if (cbs->auth_cnt >= cbs->auth_max) {
cbs->auth_max += INCRAUTHS;
cbs->auths = realloc(cbs->auths,
cbs->auth_max * sizeof (char *));
if (cbs->auths == NULL) {
(void) fprintf(stderr, "%s: ", progname);
(void) fprintf(stderr, gettext("Out of memory\n"));
exit(1);
}
}
cbs->auths[cbs->auth_cnt] = strdup(authname);
cbs->auth_cnt++;
return (0);
}
static void
free_auths(cbs_t *cbs)
{
int i;
for (i = 0; i < cbs->auth_cnt; i++)
free(cbs->auths[i]);
free(cbs->auths);
}
static boolean_t
auth_match(const char *pattern, const char *auth)
{
size_t len = strlen(pattern);
if (pattern[len - 1] != KV_WILDCHAR)
return (B_FALSE);
return (strncmp(pattern, auth, len - 1) == 0);
}
static int
mstrptr(const void *a, const void *b)
{
char *const *ap = a;
char *const *bp = b;
return (strcmp(*ap, *bp));
}
static void
simplify(cbs_t *cbs)
{
int rem, i;
qsort(cbs->auths, cbs->auth_cnt, sizeof (cbs->auths[0]), mstrptr);
for (i = 0, rem = 0; i < cbs->auth_cnt - rem - 1; ) {
if (strcmp(cbs->auths[i], cbs->auths[i + rem + 1]) == 0 ||
strchr(cbs->auths[i], KV_WILDCHAR) != NULL &&
auth_match(cbs->auths[i], cbs->auths[i + rem + 1])) {
free(cbs->auths[i + rem + 1]);
rem++;
} else {
i++;
if (rem > 0)
cbs->auths[i] = cbs->auths[i + rem];
}
}
cbs->auth_cnt -= rem;
}