Index: b/usr/src/cmd/getent/Makefile =================================================================== --- a/usr/src/cmd/getent/Makefile +++ b/usr/src/cmd/getent/Makefile @@ -48,7 +48,7 @@ OBJECTS= \ SRCS= $(OBJECTS:.o=.c) -LDLIBS += -lsocket -lnsl -lproject +LDLIBS += -lsocket -lnsl # # for message catalog Index: b/usr/src/cmd/getent/dogetproject.c =================================================================== --- a/usr/src/cmd/getent/dogetproject.c +++ b/usr/src/cmd/getent/dogetproject.c @@ -29,9 +29,226 @@ #include #include #include -#include +#include #include "getent.h" +/* BEGIN: project.h */ +#define PROJF_PATH "/etc/project" /* pathname of the "project" file */ +#define PROJNAME_MAX 64 /* maximum project name size */ +#define PROJECT_BUFSZ 4096 /* default buffer size */ + +struct project { + char *pj_name; /* name of the project */ + projid_t pj_projid; /* numerical project id */ + char *pj_comment; /* project description */ + char **pj_users; /* vector of pointers to project user names */ + char **pj_groups; /* vector of pointers to project group names */ + char *pj_attr; /* project attributes string */ +}; +/* END: project.h */ + +/* BEGIN: usr/src/lib/libproject/common/getprojent.c */ +static DEFINE_NSS_DB_ROOT(db_root); +static DEFINE_NSS_GETENT(context); + +static void +_nss_initf_project(nss_db_params_t *p) +{ + p->name = NSS_DBNAM_PROJECT; + p->default_config = NSS_DEFCONF_PROJECT; +} + +static void +setprojent(void) +{ + nss_setent(&db_root, _nss_initf_project, &context); +} + +static void +endprojent(void) +{ + nss_endent(&db_root, _nss_initf_project, &context); + nss_delete(&db_root); +} + +static char * +gettok(char **nextpp, char sep) +{ + char *p = *nextpp; + char *q = p; + char c; + + if (p == NULL) + return (NULL); + while ((c = *q) != '\0' && c != sep) + q++; + if (c == '\0') + *nextpp = 0; + else { + *q++ = '\0'; + *nextpp = q; + } + return (p); +} + +/* + * Return values: 0 = success, 1 = parse error, 2 = erange ... + * The structure pointer passed in is a structure in the caller's space + * wherein the field pointers would be set to areas in the buffer if + * need be. instring and buffer should be separate areas. + */ +static int +str2project(const char *instr, int lenstr, void *ent, char *buffer, int buflen) +{ + struct project *project = ent; + char *p, *next; + char *users, *groups; + char **uglist; + char **limit; + + if (lenstr + 1 > buflen) + return (NSS_STR_PARSE_ERANGE); + /* + * We copy the input string into the output buffer and + * operate on it in place. + */ + (void) memcpy(buffer, instr, lenstr); + buffer[lenstr] = '\0'; + next = buffer; + + limit = (char **)ROUND_DOWN(buffer + buflen, sizeof (char *)); + + /* + * Parsers for passwd and group have always been pretty rigid; + * we wouldn't want to buck a Unix tradition + */ + p = gettok(&next, ':'); + if (p == NULL || *p == '\0' || strlen(p) > PROJNAME_MAX) { + /* + * empty or very long project names are not allowed + */ + return (NSS_STR_PARSE_ERANGE); + } + project->pj_name = p; + + p = gettok(&next, ':'); + if (p == NULL || *p == '\0') { + /* + * projid field shouldn't be empty + */ + return (NSS_STR_PARSE_PARSE); + } + project->pj_projid = (projid_t)strtol(p, NULL, 10); + if (project->pj_projid < 0) { + /* + * projids should be positive number + */ + project->pj_projid = 0; + return (NSS_STR_PARSE_PARSE); + } + + p = gettok(&next, ':'); + if (p == NULL) { + /* + * comment field can be empty but should not be last field + */ + return (NSS_STR_PARSE_PARSE); + } + project->pj_comment = p; + + if ((users = gettok(&next, ':')) == NULL) { + /* + * users field should not be last field + */ + return (NSS_STR_PARSE_PARSE); + } + + if ((groups = gettok(&next, ':')) == NULL) { + /* + * groups field should not be last field + */ + return (NSS_STR_PARSE_PARSE); + } + + if (next == NULL) { + /* + * attributes field should be last + */ + return (NSS_STR_PARSE_PARSE); + } + + project->pj_attr = next; + + uglist = (char **)ROUND_UP(buffer + lenstr + 1, sizeof (char *)); + *uglist = NULL; + project->pj_users = uglist; + while (uglist < limit) { + p = gettok(&users, ','); + if (p == NULL || *p == '\0') { + *uglist = 0; + break; + } + *uglist++ = p; + } + if (uglist >= limit) + return (NSS_STR_PARSE_ERANGE); + + uglist++; + *uglist = NULL; + project->pj_groups = uglist; + while (uglist < limit) { + p = gettok(&groups, ','); + if (p == NULL || *p == '\0') { + *uglist = 0; + break; + } + *uglist++ = p; + } + if (uglist >= limit) + return (NSS_STR_PARSE_ERANGE); + + return (NSS_STR_PARSE_SUCCESS); +} + +static struct project * +getprojent(struct project *result, void *buffer, size_t buflen) +{ + nss_XbyY_args_t arg; + + NSS_XbyY_INIT(&arg, result, buffer, buflen, str2project); + (void) nss_getent(&db_root, _nss_initf_project, &context, &arg); + return ((struct project *)NSS_XbyY_FINI(&arg)); +} + +struct project * +getprojbyname(const char *name, struct project *result, + void *buffer, size_t buflen) +{ + nss_XbyY_args_t arg; + NSS_XbyY_INIT(&arg, result, buffer, buflen, str2project); + arg.key.name = name; + (void) nss_search(&db_root, _nss_initf_project, + NSS_DBOP_PROJECT_BYNAME, &arg); + return ((struct project *)NSS_XbyY_FINI(&arg)); +} + +struct project * +getprojbyid(projid_t projid, struct project *result, + void *buffer, size_t buflen) +{ + nss_XbyY_args_t arg; + + NSS_XbyY_INIT(&arg, result, buffer, buflen, str2project); + arg.key.projid = projid; + (void) nss_search(&db_root, _nss_initf_project, + NSS_DBOP_PROJECT_BYID, &arg); + return ((struct project *)NSS_XbyY_FINI(&arg)); +} + + + +/* END: usr/src/lib/libproject/common/getprojent.c */ + static int putprojent(const struct project *proj, FILE *fp) {