1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 1994, by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 27 /* 28 * For SUNWnskit - version 1.1 29 * 30 * Based on: 31 * #pragma ident "%Z%%M% %I% %E% SMI" (SMI4.1 1.6) 32 */ 33 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <string.h> 37 #include <stdio.h> 38 #include <ctype.h> 39 #include <pwd.h> 40 #include <rpcsvc/ypclnt.h> 41 #include "util.h" 42 #include "table.h" 43 #include "getgroup.h" 44 45 #define MAXDOMAINLEN 256 46 #define MAXGROUPLEN 1024 47 48 /* 49 * Reverse the netgroup file. A flag of "-u" means reverse by username, 50 * one of "-h" means reverse by hostname. Each line in the output file 51 * will begin with a key formed by concatenating the host or user name 52 * with the domain name. The key will be followed by a tab, then the 53 * comma-separated, newline-terminated list of groups to which the 54 * user or host belongs. 55 * 56 * Exception: Groups to which everyone belongs (universal groups) will 57 * not be included in the list. The universal groups will be listed under 58 * the special name "*". 59 * 60 * Thus to find out all the groups that user "foo" of domain "bar" is in, 61 * lookup the groups under foo.bar, foo.*, *.bar and *.*. 62 * 63 */ 64 65 66 67 /* Stores a list of strings */ 68 typedef struct stringnode *stringlist; 69 struct stringnode { 70 char *str; 71 stringlist next; 72 }; 73 typedef struct stringnode stringnode; 74 75 76 77 /* Stores a list of (name,list-of-groups) */ 78 typedef struct groupentrynode *groupentrylist; 79 struct groupentrynode { 80 char *name; 81 stringlist groups; 82 groupentrylist next; 83 }; 84 typedef struct groupentrynode groupentrynode; 85 86 stringtable ngtable; 87 88 static groupentrylist grouptable[TABLESIZE]; 89 90 static char *nextgroup(void); 91 static void storegroup(char *group, struct grouplist *glist, int byuser); 92 static void enter(char *name, char *group); 93 static void appendgroup(groupentrylist grlist, char *group); 94 static groupentrylist newentry(char *name, char *group); 95 static void loadtable(FILE *nf); 96 static void dumptable(void); 97 98 int 99 main(argc, argv) 100 int argc; 101 char *argv[]; 102 { 103 char *group; 104 struct grouplist *glist; 105 int byuser; 106 107 loadtable(stdin); 108 if (argc == 2 && argv[1][0] == '-' && 109 (argv[1][1] == 'u' || argv[1][1] == 'h')) { 110 byuser = (argv[1][1] == 'u'); 111 } else { 112 (void) fprintf(stderr, 113 "usage: %s -h (by host), %s -u (by user)\n", 114 argv[0], argv[0]); 115 exit(1); 116 } 117 118 while (group = nextgroup()) { 119 glist = my_getgroup(group); 120 storegroup(group, glist, byuser); 121 } 122 dumptable(); 123 124 return (0); 125 } 126 127 /* 128 * Get the next netgroup from /etc/netgroup 129 */ 130 static char * 131 nextgroup(void) 132 { 133 static int index = -1; 134 static tablelist cur = NULL; 135 char *group; 136 137 while (cur == NULL) { 138 if (++index == TABLESIZE) { 139 return (NULL); 140 } 141 cur = ngtable[index]; 142 } 143 group = cur->key; 144 cur = cur->next; 145 return (group); 146 } 147 148 149 150 /* 151 * Dump out all of the stored info into a file 152 */ 153 static void 154 dumptable(void) 155 { 156 int i; 157 groupentrylist entry; 158 stringlist groups; 159 160 for (i = 0; i < TABLESIZE; i++) { 161 if (entry = grouptable[i]) { 162 while (entry) { 163 fputs(entry->name, stdout); 164 putc('\t', stdout); 165 for (groups = entry->groups; groups; 166 groups = groups->next) { 167 fputs(groups->str, stdout); 168 if (groups->next) { 169 putc(',', stdout); 170 } 171 } 172 putc('\n', stdout); 173 entry = entry->next; 174 } 175 } 176 } 177 } 178 179 180 181 182 /* 183 * Add a netgroup to a user's list of netgroups 184 */ 185 static void 186 storegroup(char *group, struct grouplist *glist, int byuser) 187 { 188 char *name; /* username or hostname */ 189 char *domain; 190 char *key; 191 static char *universal = "*"; 192 193 for (; glist; glist = glist->gl_nxt) { 194 name = byuser ? glist->gl_name : glist->gl_machine; 195 if (!name) { 196 name = universal; 197 } else if (!isalnum(*name) && *name != '_') { 198 continue; 199 } 200 domain = glist->gl_domain; 201 if (!domain) { 202 domain = universal; 203 } 204 key = malloc((unsigned) (strlen(name)+strlen(domain)+2)); 205 (void) sprintf(key, "%s.%s", name, domain); 206 enter(key, group); 207 } 208 } 209 210 211 212 static groupentrylist 213 newentry(char *name, char *group) 214 { 215 groupentrylist new; 216 217 new = MALLOC(groupentrynode); 218 219 STRCPY(new->name, name); 220 221 new->groups = MALLOC(stringnode); 222 new->groups->str = group; 223 new->groups->next = NULL; 224 225 new->next = NULL; 226 return (new); 227 } 228 229 static void 230 appendgroup(groupentrylist grlist, char *group) 231 { 232 stringlist cur, prev; 233 234 for (cur = grlist->groups; cur; prev = cur, cur = cur->next) { 235 if (strcmp(group, cur->str) == 0) { 236 return; 237 } 238 } 239 prev->next = MALLOC(stringnode); 240 cur = prev->next; 241 cur->str = group; 242 cur->next = NULL; 243 } 244 245 static void 246 enter(char *name, char *group) 247 { 248 int key; 249 groupentrylist gel; 250 groupentrylist gelprev; 251 252 key = tablekey(name); 253 if (grouptable[key] == NULL) { 254 grouptable[key] = newentry(name, group); 255 } else { 256 gel = grouptable[key]; 257 while (gel && strcmp(gel->name, name)) { 258 gelprev = gel; 259 gel = gel->next; 260 } 261 if (gel) { 262 appendgroup(gel, group); 263 } else { 264 gelprev->next = newentry(name, group); 265 } 266 } 267 } 268 269 /* 270 * Load up a hash table with the info in /etc/netgroup 271 */ 272 static void 273 loadtable(FILE *nf) 274 { 275 char buf[MAXGROUPLEN]; 276 char *p; 277 char *group; 278 char *line; 279 280 while (getline(buf, MAXGROUPLEN, nf)) { 281 for (p = buf; *p && isspace((int)*p); p++) 282 ; /* skip leading blanks */ 283 for (; *p && *p != '#' && *p != ' ' && *p != '\t'; p++) 284 ; 285 if (*p == EOS || *p == '#') 286 continue; 287 *p++ = EOS; 288 289 while (*p == ' ' || *p == '\t') { 290 p++; 291 } 292 if (*p == EOS || *p == '#') 293 continue; 294 295 STRCPY(group, buf); 296 STRCPY(line, p); 297 store(ngtable, group, line); 298 } 299 } 300