From 50568f27d680f3a286fdcfaebb5e4f361c4c7e8b Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Wed, 10 Mar 2010 02:16:04 +0000 Subject: Create the altix project branch. The altix project will add support for the SGI Altix 350 to FreeBSD/ia64. The hardware used for porting is a two-module system, consisting of a base compute module and a CPU expansion module. SGI's NUMAFlex architecture can be an excellent platform to test CPU affinity and NUMA-aware features in FreeBSD. --- libutil/login_cap.c | 819 ---------------------------------------------------- 1 file changed, 819 deletions(-) delete mode 100644 libutil/login_cap.c (limited to 'libutil/login_cap.c') diff --git a/libutil/login_cap.c b/libutil/login_cap.c deleted file mode 100644 index 8fee760..0000000 --- a/libutil/login_cap.c +++ /dev/null @@ -1,819 +0,0 @@ -/*- - * Copyright (c) 1996 by - * Sean Eric Fagan - * David Nugent - * All rights reserved. - * - * Portions copyright (c) 1995,1997 - * Berkeley Software Design, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, is permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice immediately at the beginning of the file, without modification, - * this list of conditions, and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. This work was done expressly for inclusion into FreeBSD. Other use - * is permitted provided this notation is included. - * 4. Absolutely no warranty of function or purpose is made by the authors. - * 5. Modifications may be freely made to this file providing the above - * conditions are met. - * - * Low-level routines relating to the user capabilities database - */ - -#include -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * allocstr() - * Manage a single static pointer for handling a local char* buffer, - * resizing as necessary to contain the string. - * - * allocarray() - * Manage a static array for handling a group of strings, resizing - * when necessary. - */ - -static int lc_object_count = 0; - -static size_t internal_stringsz = 0; -static char * internal_string = NULL; -static size_t internal_arraysz = 0; -static const char ** internal_array = NULL; - -static char path_login_conf[] = _PATH_LOGIN_CONF; - -static char * -allocstr(const char *str) -{ - char *p; - - size_t sz = strlen(str) + 1; /* realloc() only if necessary */ - if (sz <= internal_stringsz) - p = strcpy(internal_string, str); - else if ((p = realloc(internal_string, sz)) != NULL) { - internal_stringsz = sz; - internal_string = strcpy(p, str); - } - return p; -} - - -static const char ** -allocarray(size_t sz) -{ - static const char **p; - - if (sz <= internal_arraysz) - p = internal_array; - else if ((p = realloc(internal_array, sz * sizeof(char*))) != NULL) { - internal_arraysz = sz; - internal_array = p; - } - return p; -} - - -/* - * arrayize() - * Turn a simple string separated by any of - * the set of into an array. The last element - * of the array will be NULL, as is proper. - * Free using freearraystr() - */ - -static const char ** -arrayize(const char *str, const char *chars, int *size) -{ - int i; - char *ptr; - const char *cptr; - const char **res = NULL; - - /* count the sub-strings */ - for (i = 0, cptr = str; *cptr; i++) { - int count = strcspn(cptr, chars); - cptr += count; - if (*cptr) - ++cptr; - } - - /* alloc the array */ - if ((ptr = allocstr(str)) != NULL) { - if ((res = allocarray(++i)) == NULL) - free((void *)(uintptr_t)(const void *)str); - else { - /* now split the string */ - i = 0; - while (*ptr) { - int count = strcspn(ptr, chars); - res[i++] = ptr; - ptr += count; - if (*ptr) - *ptr++ = '\0'; - } - res[i] = NULL; - } - } - - if (size) - *size = i; - - return res; -} - - -/* - * login_close() - * Frees up all resources relating to a login class - * - */ - -void -login_close(login_cap_t * lc) -{ - if (lc) { - free(lc->lc_style); - free(lc->lc_class); - free(lc->lc_cap); - free(lc); - if (--lc_object_count == 0) { - free(internal_string); - free(internal_array); - internal_array = NULL; - internal_arraysz = 0; - internal_string = NULL; - internal_stringsz = 0; - cgetclose(); - } - } -} - - -/* - * login_getclassbyname() - * Get the login class by its name. - * If the name given is NULL or empty, the default class - * LOGIN_DEFCLASS (i.e., "default") is fetched. - * If the name given is LOGIN_MECLASS and - * 'pwd' argument is non-NULL and contains an non-NULL - * dir entry, then the file _FILE_LOGIN_CONF is picked - * up from that directory and used before the system - * login database. In that case the system login database - * is looked up using LOGIN_MECLASS, too, which is a bug. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getclassbyname(char const *name, const struct passwd *pwd) -{ - login_cap_t *lc; - - if ((lc = malloc(sizeof(login_cap_t))) != NULL) { - int r, me, i = 0; - uid_t euid = 0; - gid_t egid = 0; - const char *msg = NULL; - const char *dir; - char userpath[MAXPATHLEN]; - - static char *login_dbarray[] = { NULL, NULL, NULL }; - - me = (name != NULL && strcmp(name, LOGIN_MECLASS) == 0); - dir = (!me || pwd == NULL) ? NULL : pwd->pw_dir; - /* - * Switch to user mode before checking/reading its ~/.login_conf - * - some NFSes have root read access disabled. - * - * XXX: This fails to configure additional groups. - */ - if (dir) { - euid = geteuid(); - egid = getegid(); - (void)setegid(pwd->pw_gid); - (void)seteuid(pwd->pw_uid); - } - - if (dir && snprintf(userpath, MAXPATHLEN, "%s/%s", dir, - _FILE_LOGIN_CONF) < MAXPATHLEN) { - if (_secure_path(userpath, pwd->pw_uid, pwd->pw_gid) != -1) - login_dbarray[i++] = userpath; - } - /* - * XXX: Why to add the system database if the class is `me'? - */ - if (_secure_path(path_login_conf, 0, 0) != -1) - login_dbarray[i++] = path_login_conf; - login_dbarray[i] = NULL; - - memset(lc, 0, sizeof(login_cap_t)); - lc->lc_cap = lc->lc_class = lc->lc_style = NULL; - - if (name == NULL || *name == '\0') - name = LOGIN_DEFCLASS; - - switch (cgetent(&lc->lc_cap, login_dbarray, name)) { - case -1: /* Failed, entry does not exist */ - if (me) - break; /* Don't retry default on 'me' */ - if (i == 0) - r = -1; - else if ((r = open(login_dbarray[0], O_RDONLY)) >= 0) - close(r); - /* - * If there's at least one login class database, - * and we aren't searching for a default class - * then complain about a non-existent class. - */ - if (r >= 0 || strcmp(name, LOGIN_DEFCLASS) != 0) - syslog(LOG_ERR, "login_getclass: unknown class '%s'", name); - /* fall-back to default class */ - name = LOGIN_DEFCLASS; - msg = "%s: no default/fallback class '%s'"; - if (cgetent(&lc->lc_cap, login_dbarray, name) != 0 && r >= 0) - break; - /* FALLTHROUGH - just return system defaults */ - case 0: /* success! */ - if ((lc->lc_class = strdup(name)) != NULL) { - if (dir) { - (void)seteuid(euid); - (void)setegid(egid); - } - ++lc_object_count; - return lc; - } - msg = "%s: strdup: %m"; - break; - case -2: - msg = "%s: retrieving class information: %m"; - break; - case -3: - msg = "%s: 'tc=' reference loop '%s'"; - break; - case 1: - msg = "couldn't resolve 'tc=' reference in '%s'"; - break; - default: - msg = "%s: unexpected cgetent() error '%s': %m"; - break; - } - if (dir) { - (void)seteuid(euid); - (void)setegid(egid); - } - if (msg != NULL) - syslog(LOG_ERR, msg, "login_getclass", name); - free(lc); - } - - return NULL; -} - - - -/* - * login_getclass() - * Get the login class for the system (only) login class database. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getclass(const char *cls) -{ - return login_getclassbyname(cls, NULL); -} - - -/* - * login_getpwclass() - * Get the login class for a given password entry from - * the system (only) login class database. - * If the password entry's class field is not set, or - * the class specified does not exist, then use the - * default of LOGIN_DEFCLASS (i.e., "default") for an unprivileged - * user or that of LOGIN_DEFROOTCLASS (i.e., "root") for a super-user. - * Return a filled-out login_cap_t structure, including - * class name, and the capability record buffer. - */ - -login_cap_t * -login_getpwclass(const struct passwd *pwd) -{ - const char *cls = NULL; - - if (pwd != NULL) { - cls = pwd->pw_class; - if (cls == NULL || *cls == '\0') - cls = (pwd->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; - } - /* - * XXX: pwd should be unused by login_getclassbyname() unless cls is `me', - * so NULL can be passed instead of pwd for more safety. - */ - return login_getclassbyname(cls, pwd); -} - - -/* - * login_getuserclass() - * Get the `me' login class, allowing user overrides via ~/.login_conf. - * Note that user overrides are allowed only in the `me' class. - */ - -login_cap_t * -login_getuserclass(const struct passwd *pwd) -{ - return login_getclassbyname(LOGIN_MECLASS, pwd); -} - - -/* - * login_getcapstr() - * Given a login_cap entry, and a capability name, return the - * value defined for that capability, a default if not found, or - * an error string on error. - */ - -const char * -login_getcapstr(login_cap_t *lc, const char *cap, const char *def, const char *error) -{ - char *res; - int ret; - - if (lc == NULL || cap == NULL || lc->lc_cap == NULL || *cap == '\0') - return def; - - if ((ret = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - return (ret >= 0) ? res : error; -} - - -/* - * login_getcaplist() - * Given a login_cap entry, and a capability name, return the - * value defined for that capability split into an array of - * strings. - */ - -const char ** -login_getcaplist(login_cap_t *lc, const char *cap, const char *chars) -{ - const char *lstring; - - if (chars == NULL) - chars = ", \t"; - if ((lstring = login_getcapstr(lc, cap, NULL, NULL)) != NULL) - return arrayize(lstring, chars, NULL); - return NULL; -} - - -/* - * login_getpath() - * From the login_cap_t , get the capability which is - * formatted as either a space or comma delimited list of paths - * and append them all into a string and separate by semicolons. - * If there is an error of any kind, return . - */ - -const char * -login_getpath(login_cap_t *lc, const char *cap, const char *error) -{ - const char *str; - char *ptr; - int count; - - str = login_getcapstr(lc, cap, NULL, NULL); - if (str == NULL) - return error; - ptr = __DECONST(char *, str); /* XXXX Yes, very dodgy */ - while (*ptr) { - count = strcspn(ptr, ", \t"); - ptr += count; - if (*ptr) - *ptr++ = ':'; - } - return str; -} - - -static int -isinfinite(const char *s) -{ - static const char *infs[] = { - "infinity", - "inf", - "unlimited", - "unlimit", - "-1", - NULL - }; - const char **i = &infs[0]; - - while (*i != NULL) { - if (strcasecmp(s, *i) == 0) - return 1; - ++i; - } - return 0; -} - - -static u_quad_t -rmultiply(u_quad_t n1, u_quad_t n2) -{ - u_quad_t m, r; - int b1, b2; - - static int bpw = 0; - - /* Handle simple cases */ - if (n1 == 0 || n2 == 0) - return 0; - if (n1 == 1) - return n2; - if (n2 == 1) - return n1; - - /* - * sizeof() returns number of bytes needed for storage. - * This may be different from the actual number of useful bits. - */ - if (!bpw) { - bpw = sizeof(u_quad_t) * 8; - while (((u_quad_t)1 << (bpw-1)) == 0) - --bpw; - } - - /* - * First check the magnitude of each number. If the sum of the - * magnatude is way to high, reject the number. (If this test - * is not done then the first multiply below may overflow.) - */ - for (b1 = bpw; (((u_quad_t)1 << (b1-1)) & n1) == 0; --b1) - ; - for (b2 = bpw; (((u_quad_t)1 << (b2-1)) & n2) == 0; --b2) - ; - if (b1 + b2 - 2 > bpw) { - errno = ERANGE; - return (UQUAD_MAX); - } - - /* - * Decompose the multiplication to be: - * h1 = n1 & ~1 - * h2 = n2 & ~1 - * l1 = n1 & 1 - * l2 = n2 & 1 - * (h1 + l1) * (h2 + l2) - * (h1 * h2) + (h1 * l2) + (l1 * h2) + (l1 * l2) - * - * Since h1 && h2 do not have the low bit set, we can then say: - * - * (h1>>1 * h2>>1 * 4) + ... - * - * So if (h1>>1 * h2>>1) > (1<<(bpw - 2)) then the result will - * overflow. - * - * Finally, if MAX - ((h1 * l2) + (l1 * h2) + (l1 * l2)) < (h1*h2) - * then adding in residual amout will cause an overflow. - */ - - m = (n1 >> 1) * (n2 >> 1); - if (m >= ((u_quad_t)1 << (bpw-2))) { - errno = ERANGE; - return (UQUAD_MAX); - } - m *= 4; - - r = (n1 & n2 & 1) - + (n2 & 1) * (n1 & ~(u_quad_t)1) - + (n1 & 1) * (n2 & ~(u_quad_t)1); - - if ((u_quad_t)(m + r) < m) { - errno = ERANGE; - return (UQUAD_MAX); - } - m += r; - - return (m); -} - - -/* - * login_getcaptime() - * From the login_cap_t , get the capability , which is - * formatted as a time (e.g., "=10h3m2s"). If is not - * present in , return ; if there is an error of some kind, - * return . - */ - -rlim_t -login_getcaptime(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *res, *ep, *oval; - int r; - rlim_t tot; - - errno = 0; - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * Look for in lc_cap. - * If it's not there (-1), return . - * If there's an error, return . - */ - - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - else if (r < 0) { - errno = ERANGE; - return error; - } - - /* "inf" and "infinity" are special cases */ - if (isinfinite(res)) - return RLIM_INFINITY; - - /* - * Now go through the string, turning something like 1h2m3s into - * an integral value. Whee. - */ - - errno = 0; - tot = 0; - oval = res; - while (*res) { - rlim_t tim = strtoq(res, &ep, 0); - rlim_t mult = 1; - - if (ep == NULL || ep == res || errno != 0) { - invalid: - syslog(LOG_WARNING, "login_getcaptime: class '%s' bad value %s=%s", - lc->lc_class, cap, oval); - errno = ERANGE; - return error; - } - /* Look for suffixes */ - switch (*ep++) { - case 0: - ep--; - break; /* end of string */ - case 's': case 'S': /* seconds */ - break; - case 'm': case 'M': /* minutes */ - mult = 60; - break; - case 'h': case 'H': /* hours */ - mult = 60L * 60L; - break; - case 'd': case 'D': /* days */ - mult = 60L * 60L * 24L; - break; - case 'w': case 'W': /* weeks */ - mult = 60L * 60L * 24L * 7L; - break; - case 'y': case 'Y': /* 365-day years */ - mult = 60L * 60L * 24L * 365L; - break; - default: - goto invalid; - } - res = ep; - tot += rmultiply(tim, mult); - if (errno) - goto invalid; - } - - return tot; -} - - -/* - * login_getcapnum() - * From the login_cap_t , extract the numerical value . - * If it is not present, return for a default, and return - * if there is an error. - * Like login_getcaptime(), only it only converts to a number, not - * to a time; "infinity" and "inf" are 'special.' - */ - -rlim_t -login_getcapnum(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *ep, *res; - int r; - rlim_t val; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - /* - * For BSDI compatibility, try for the tag= first - */ - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) { - long lval; - /* string capability not present, so try for tag# as numeric */ - if ((r = cgetnum(lc->lc_cap, cap, &lval)) == -1) - return def; /* Not there, so return default */ - else if (r >= 0) - return (rlim_t)lval; - } - - if (r < 0) { - errno = ERANGE; - return error; - } - - if (isinfinite(res)) - return RLIM_INFINITY; - - errno = 0; - val = strtoq(res, &ep, 0); - if (ep == NULL || ep == res || errno != 0) { - syslog(LOG_WARNING, "login_getcapnum: class '%s' bad value %s=%s", - lc->lc_class, cap, res); - errno = ERANGE; - return error; - } - - return val; -} - - - -/* - * login_getcapsize() - * From the login_cap_t , extract the capability , which is - * formatted as a size (e.g., "=10M"); it can also be "infinity". - * If not present, return , or if there is an error of - * some sort. - */ - -rlim_t -login_getcapsize(login_cap_t *lc, const char *cap, rlim_t def, rlim_t error) -{ - char *ep, *res, *oval; - int r; - rlim_t tot; - - if (lc == NULL || lc->lc_cap == NULL) - return def; - - if ((r = cgetstr(lc->lc_cap, cap, &res)) == -1) - return def; - else if (r < 0) { - errno = ERANGE; - return error; - } - - if (isinfinite(res)) - return RLIM_INFINITY; - - errno = 0; - tot = 0; - oval = res; - while (*res) { - rlim_t siz = strtoq(res, &ep, 0); - rlim_t mult = 1; - - if (ep == NULL || ep == res || errno != 0) { - invalid: - syslog(LOG_WARNING, "login_getcapsize: class '%s' bad value %s=%s", - lc->lc_class, cap, oval); - errno = ERANGE; - return error; - } - switch (*ep++) { - case 0: /* end of string */ - ep--; - break; - case 'b': case 'B': /* 512-byte blocks */ - mult = 512; - break; - case 'k': case 'K': /* 1024-byte Kilobytes */ - mult = 1024; - break; - case 'm': case 'M': /* 1024-k kbytes */ - mult = 1024 * 1024; - break; - case 'g': case 'G': /* 1Gbyte */ - mult = 1024 * 1024 * 1024; - break; - case 't': case 'T': /* 1TBte */ - mult = 1024LL * 1024LL * 1024LL * 1024LL; - break; - default: - goto invalid; - } - res = ep; - tot += rmultiply(siz, mult); - if (errno) - goto invalid; - } - - return tot; -} - - -/* - * login_getcapbool() - * From the login_cap_t , check for the existance of the capability - * of . Return if ->lc_cap is NULL, otherwise return - * the whether or not exists there. - */ - -int -login_getcapbool(login_cap_t *lc, const char *cap, int def) -{ - if (lc == NULL || lc->lc_cap == NULL) - return def; - return (cgetcap(lc->lc_cap, cap, ':') != NULL); -} - - -/* - * login_getstyle() - * Given a login_cap entry , and optionally a type of auth , - * and optionally a style