#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <userdefs.h>
#include <user_attr.h>
#include <limits.h>
#include <stdlib.h>
#include <stddef.h>
#include <time.h>
#include <unistd.h>
#include "userdisp.h"
#include "funcs.h"
#include "messages.h"
#define PRINTNL() \
if (outcount > 40) { \
outcount = 0; \
(void) fprintf(fptr, "\n"); \
}
#define SKIPWS(ptr) while (*(ptr) == ' ' || *(ptr) == '\t') (ptr)++
static char *dup_to_nl(char *);
static struct userdefs defaults = {
DEFRID, DEFGROUP, DEFGNAME, DEFPARENT, DEFSKL,
DEFSHL, DEFINACT, DEFEXPIRE, DEFAUTH, DEFPROF,
DEFROLE, DEFPROJ, DEFPROJNAME, DEFLIMPRIV,
DEFDFLTPRIV, DEFLOCK_AFTER_RETRIES, DEFROLEAUTH
};
#define INT 0
#define STR 1
#define PROJID 2
#define DEFOFF(field) offsetof(struct userdefs, field)
#define FIELD(up, pe, type) (*(type *)((char *)(up) + (pe)->off))
typedef struct parsent {
const char *name;
const size_t nmsz;
const int type;
const ptrdiff_t off;
const char *uakey;
} parsent_t;
static const parsent_t tab[] = {
{ GIDSTR, sizeof (GIDSTR) - 1, INT, DEFOFF(defgroup) },
{ GNAMSTR, sizeof (GNAMSTR) - 1, STR, DEFOFF(defgname) },
{ PARSTR, sizeof (PARSTR) - 1, STR, DEFOFF(defparent) },
{ SKLSTR, sizeof (SKLSTR) - 1, STR, DEFOFF(defskel) },
{ SHELLSTR, sizeof (SHELLSTR) - 1, STR, DEFOFF(defshell) },
{ INACTSTR, sizeof (INACTSTR) - 1, INT, DEFOFF(definact) },
{ EXPIRESTR, sizeof (EXPIRESTR) - 1, STR, DEFOFF(defexpire) },
{ AUTHSTR, sizeof (AUTHSTR) - 1, STR, DEFOFF(defauth),
USERATTR_AUTHS_KW },
{ ROLESTR, sizeof (ROLESTR) - 1, STR, DEFOFF(defrole),
USERATTR_ROLES_KW },
{ PROFSTR, sizeof (PROFSTR) - 1, STR, DEFOFF(defprof),
USERATTR_PROFILES_KW },
{ PROJSTR, sizeof (PROJSTR) - 1, PROJID, DEFOFF(defproj) },
{ PROJNMSTR, sizeof (PROJNMSTR) - 1, STR, DEFOFF(defprojname) },
{ LIMPRSTR, sizeof (LIMPRSTR) - 1, STR, DEFOFF(deflimpriv),
USERATTR_LIMPRIV_KW },
{ DFLTPRSTR, sizeof (DFLTPRSTR) - 1, STR, DEFOFF(defdfltpriv),
USERATTR_DFLTPRIV_KW },
{ LOCK_AFTER_RETRIESSTR, sizeof (LOCK_AFTER_RETRIESSTR) - 1,
STR, DEFOFF(deflock_after_retries),
USERATTR_LOCK_AFTER_RETRIES_KW },
{ ROLEAUTHSTR, sizeof (ROLEAUTHSTR) - 1, STR, DEFOFF(defroleauth),
USERATTR_ROLEAUTH_KW },
};
#define NDEF (sizeof (tab) / sizeof (parsent_t))
FILE *defptr;
static const parsent_t *
scan(char **start_p)
{
static int ind = NDEF - 1;
char *cur_p = *start_p;
int lastind = ind;
if (!*cur_p || *cur_p == '\n' || *cur_p == '#')
return (NULL);
do {
ind++;
ind %= NDEF;
if (strncmp(cur_p, tab[ind].name, tab[ind].nmsz) == 0) {
*start_p = cur_p + tab[ind].nmsz;
return (&tab[ind]);
}
} while (ind != lastind);
return (NULL);
}
struct userdefs *
getusrdef(char *usertype)
{
char instr[512], *ptr;
const parsent_t *pe;
if (is_role(usertype)) {
if ((defptr = fopen(DEFROLEFILE, "r")) == NULL) {
defaults.defshell = DEFROLESHL;
defaults.defprof = DEFROLEPROF;
defaults.defroleauth = DEFROLEROLEAUTH;
return (&defaults);
}
} else {
if ((defptr = fopen(DEFFILE, "r")) == NULL)
return (&defaults);
}
while (fgets(instr, sizeof (instr), defptr) != NULL) {
ptr = instr;
SKIPWS(ptr);
if (*ptr == '#')
continue;
pe = scan(&ptr);
if (pe != NULL) {
switch (pe->type) {
case INT:
FIELD(&defaults, pe, int) =
(int)strtol(ptr, NULL, 10);
break;
case PROJID:
FIELD(&defaults, pe, projid_t) =
(projid_t)strtol(ptr, NULL, 10);
break;
case STR:
FIELD(&defaults, pe, char *) = dup_to_nl(ptr);
break;
}
}
}
(void) fclose(defptr);
return (&defaults);
}
static char *
dup_to_nl(char *from)
{
char *res = strdup(from);
char *p = strchr(res, '\n');
if (p)
*p = '\0';
return (res);
}
void
dispusrdef(FILE *fptr, unsigned flags, char *usertype)
{
struct userdefs *deflts = getusrdef(usertype);
int outcount = 0;
if (flags & D_GROUP) {
outcount += fprintf(fptr, "group=%s,%ld ",
deflts->defgname, deflts->defgroup);
PRINTNL();
}
if (flags & D_PROJ) {
outcount += fprintf(fptr, "project=%s,%ld ",
deflts->defprojname, deflts->defproj);
PRINTNL();
}
if (flags & D_BASEDIR) {
outcount += fprintf(fptr, "basedir=%s ", deflts->defparent);
PRINTNL();
}
if (flags & D_RID) {
outcount += fprintf(fptr, "rid=%ld ", deflts->defrid);
PRINTNL();
}
if (flags & D_SKEL) {
outcount += fprintf(fptr, "skel=%s ", deflts->defskel);
PRINTNL();
}
if (flags & D_SHELL) {
outcount += fprintf(fptr, "shell=%s ", deflts->defshell);
PRINTNL();
}
if (flags & D_INACT) {
outcount += fprintf(fptr, "inactive=%d ", deflts->definact);
PRINTNL();
}
if (flags & D_EXPIRE) {
outcount += fprintf(fptr, "expire=%s ", deflts->defexpire);
PRINTNL();
}
if (flags & D_AUTH) {
outcount += fprintf(fptr, "auths=%s ", deflts->defauth);
PRINTNL();
}
if (flags & D_PROF) {
outcount += fprintf(fptr, "profiles=%s ", deflts->defprof);
PRINTNL();
}
if ((flags & D_ROLE) &&
(!is_role(usertype))) {
outcount += fprintf(fptr, "roles=%s ", deflts->defrole);
PRINTNL();
}
if (flags & D_LPRIV) {
outcount += fprintf(fptr, "limitpriv=%s ", deflts->deflimpriv);
PRINTNL();
}
if (flags & D_DPRIV) {
outcount += fprintf(fptr, "defaultpriv=%s ",
deflts->defdfltpriv);
PRINTNL();
}
if (flags & D_LOCK) {
outcount += fprintf(fptr, "lock_after_retries=%s ",
deflts->deflock_after_retries);
PRINTNL();
}
if ((flags & D_ROLEAUTH) && is_role(usertype)) {
outcount += fprintf(fptr, "roleauth=%s ",
deflts->defroleauth);
}
if (outcount > 0)
(void) fprintf(fptr, "\n");
}
int
putusrdef(struct userdefs *defs, char *usertype)
{
time_t timeval;
int i;
ptrdiff_t skip;
char *hdr;
if (is_role(usertype)) {
if ((defptr = fopen(DEFROLEFILE, "w")) == NULL) {
errmsg(M_FAILED);
return (EX_UPDATE);
}
} else {
if ((defptr = fopen(DEFFILE, "w")) == NULL) {
errmsg(M_FAILED);
return (EX_UPDATE);
}
}
if (lockf(fileno(defptr), F_LOCK, 0) != 0) {
errmsg(M_UPDATE, "created");
return (EX_UPDATE);
}
if (is_role(usertype)) {
skip = DEFOFF(defrole);
hdr = FHEADER_ROLE;
} else {
skip = DEFOFF(defroleauth);
hdr = FHEADER;
}
timeval = time(NULL);
if (fprintf(defptr, "%s%s\n", hdr, ctime(&timeval)) <= 0) {
errmsg(M_UPDATE, "created");
return (EX_UPDATE);
}
for (i = 0; i < NDEF; i++) {
int res = 0;
if (tab[i].off == skip)
continue;
switch (tab[i].type) {
case INT:
res = fprintf(defptr, "%s%d\n", tab[i].name,
FIELD(defs, &tab[i], int));
break;
case STR:
res = fprintf(defptr, "%s%s\n", tab[i].name,
FIELD(defs, &tab[i], char *));
break;
case PROJID:
res = fprintf(defptr, "%s%d\n", tab[i].name,
(int)FIELD(defs, &tab[i], projid_t));
break;
}
if (res <= 0) {
errmsg(M_UPDATE, "created");
return (EX_UPDATE);
}
}
(void) lockf(fileno(defptr), F_ULOCK, 0);
(void) fclose(defptr);
return (EX_SUCCESS);
}
void
update_def(struct userdefs *ud)
{
int i;
for (i = 0; i < NDEF; i++) {
char *val;
if (tab[i].uakey != NULL &&
(val = getsetdefval(tab[i].uakey, NULL)) != NULL)
FIELD(ud, &tab[i], char *) = val;
}
}
void
import_def(struct userdefs *ud)
{
int i;
for (i = 0; i < NDEF; i++) {
if (tab[i].uakey != NULL && tab[i].type == STR) {
char *val = FIELD(ud, &tab[i], char *);
if (val == getsetdefval(tab[i].uakey, val))
nkeys ++;
}
}
}