#include <sys/types.h>
#include <stdio.h>
#include <netgroup.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "stringlist.h"
static const char _ngstar[] = "*";
static int getstring(char **, int, char **);
static struct netgroup *getnetgroup(char **);
struct stringlist *
_ng_sl_init(void)
{
struct stringlist *sl = malloc(sizeof(struct stringlist));
if (sl == NULL)
return NULL;
sl->sl_cur = 0;
sl->sl_max = 20;
sl->sl_str = calloc(sl->sl_max, sizeof(char *));
if (sl->sl_str == NULL) {
free(sl);
return NULL;
}
return sl;
}
int
_ng_sl_add(struct stringlist *sl, char *name)
{
if (sl->sl_cur == sl->sl_max - 1) {
char **slstr;
sl->sl_max += 20;
slstr = reallocarray(sl->sl_str, sl->sl_max, sizeof(char *));
if (slstr == NULL) {
free(sl->sl_str);
sl->sl_str = NULL;
return -1;
}
sl->sl_str = slstr;
}
sl->sl_str[sl->sl_cur++] = name;
return 0;
}
void
_ng_sl_free(struct stringlist *sl, int all)
{
size_t i;
if (all)
for (i = 0; i < sl->sl_cur; i++)
free(sl->sl_str[i]);
free(sl->sl_str);
free(sl);
}
char *
_ng_sl_find(struct stringlist *sl, char *name)
{
size_t i;
for (i = 0; i < sl->sl_cur; i++)
if (strcmp(sl->sl_str[i], name) == 0)
return sl->sl_str[i];
return NULL;
}
int
_ng_parse(char **p, char **name, struct netgroup **ng)
{
while (**p) {
if (**p == '#')
return _NG_NONE;
while (**p && _NG_ISSPACE(**p))
(*p)++;
if (**p == '(') {
if ((*ng = getnetgroup(p)) == NULL)
return _NG_ERROR;
return _NG_GROUP;
} else {
char *np;
int i;
for (np = *p; **p && !_NG_ISSPACE(**p); (*p)++)
continue;
if (np != *p) {
i = (*p - np) + 1;
*name = malloc(i);
if (*name == NULL)
return _NG_ERROR;
memcpy(*name, np, i);
(*name)[i - 1] = '\0';
return _NG_NAME;
}
}
}
return _NG_NONE;
}
char *
_ng_makekey(const char *s1, const char *s2, size_t len)
{
char *buf = malloc(len);
int ret;
if (buf == NULL)
return NULL;
ret = snprintf(buf, len, "%s.%s", _NG_STAR(s1), _NG_STAR(s2));
if (ret < 0 || ret >= len) {
free(buf);
return NULL;
}
return buf;
}
void
_ng_print(char *buf, size_t len, const struct netgroup *ng)
{
(void) snprintf(buf, len, "(%s,%s,%s)", _NG_EMPTY(ng->ng_host),
_NG_EMPTY(ng->ng_user), _NG_EMPTY(ng->ng_domain));
}
static struct netgroup *
getnetgroup(char **pp)
{
struct netgroup *ng = malloc(sizeof(struct netgroup));
if (ng == NULL)
return NULL;
(*pp)++;
if (!getstring(pp, ',', &ng->ng_host))
goto badhost;
if (!getstring(pp, ',', &ng->ng_user))
goto baduser;
if (!getstring(pp, ')', &ng->ng_domain))
goto baddomain;
#ifdef DEBUG_NG
{
char buf[1024];
_ng_print(buf, sizeof(buf), ng);
fprintf(stderr, "netgroup %s\n", buf);
}
#endif
return ng;
baddomain:
free(ng->ng_user);
baduser:
free(ng->ng_host);
badhost:
free(ng);
return NULL;
}
static int
getstring(char **pp, int del, char **str)
{
char *sp, *ep, *dp;
for (sp = *pp; *sp && _NG_ISSPACE(*sp); sp++)
continue;
for (ep = sp; *ep && *ep != del && !_NG_ISSPACE(*ep); ep++)
continue;
for (dp = ep; *dp && *dp != del && _NG_ISSPACE(*dp); dp++)
continue;
if (*dp != del) {
*str = NULL;
return 0;
}
*pp = ++dp;
del = (ep - sp) + 1;
if (del > 1) {
dp = malloc(del);
if (dp == NULL)
return 0;
memcpy(dp, sp, del);
dp[del - 1] = '\0';
} else
dp = NULL;
*str = dp;
return 1;
}