/* idvec string representation Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc. Written by Miles Bader This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include /* Return a string representation of the ids in IDVEC, each id separated by the string SEP (default ","). SHOW_VALUES and SHOW_NAMES reflect how each id is printed (if SHOW_NAMES is true values are used where names aren't available); if both are true, the `VALUE(NAME)' format is used. ID_NAME_FN is used to map each id to a name; it should return a malloced string, which will be freed here. The empty string is returned for an empty list, and 0 for an allocation error. */ char * idvec_rep (const struct idvec *idvec, int show_values, int show_names, char *(*id_name_fn) (uid_t id), const char *sep) { size_t sep_len; char *rep = 0; size_t rep_len = 0, rep_sz = 0; int ensure_room (size_t amount) { size_t end = rep_len + amount; if (end > rep_sz) { size_t new_sz = rep_sz + end; char *new_rep = realloc (rep, new_sz); if (new_rep) { rep = new_rep; rep_sz = new_sz; } else return 0; } return 1; } int add_id (uid_t val, char *name) { if (!name || show_values) { if (! ensure_room (10)) return 0; rep_len += snprintf (rep + rep_len, 10, "%d", val); } if (name) { size_t nlen = strlen (name) + 3; if (! ensure_room (nlen)) { free (name); return 0; } rep_len += snprintf (rep + rep_len, nlen, show_values ? "(%s)" : "%s", name); free (name); } return 1; } if (! sep) sep = ","; sep_len = strlen (sep); if (idvec->num > 0) { unsigned int i; for (i = 0; i < idvec->num; i++) { char *name = 0; uid_t val = idvec->ids[i]; if (i > 0) { if (ensure_room (sep_len)) { strcpy (rep + rep_len, sep); rep_len += sep_len; } else break; } if (show_names || !show_values) name = (*id_name_fn) (val); if (! add_id (val, name)) break; } if (i < idvec->num) { free (rep); return 0; } return rep; } return strdup (""); } /* Return a malloced string with the name of the user UID. */ static char * lookup_uid (uid_t uid) { char buf[1024]; struct passwd _pw, *pw; if (getpwuid_r (uid, &_pw, buf, sizeof buf, &pw) == 0) return strdup (pw->pw_name); else return 0; } /* Return a malloced string with the name of the group GID. */ static char * lookup_gid (gid_t gid) { char buf[1024]; struct group _gr, *gr; if (getgrgid_r (gid, &_gr, buf, sizeof buf, &gr) == 0) return strdup (gr->gr_name); else return 0; } /* Like idvec_rep, mapping ids to user names. */ char * idvec_uids_rep (const struct idvec *idvec, int show_values, int show_names, const char *sep) { return idvec_rep (idvec, show_values, show_names, lookup_uid, sep); } /* Like idvec_rep, mapping ids to group names. */ char * idvec_gids_rep (const struct idvec *idvec, int show_values, int show_names, const char *sep) { return idvec_rep (idvec, show_values, show_names, lookup_gid, sep); }