8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ypcmd / mknetid / mknetid.c
blob1cc0d85057215c27eebf38d4c3dd97606d14bd41
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
23 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright (c) 2016 by Delphix. All rights reserved.
28 * Network name to unix credential database generator.
29 * Uses /etc/passwd, /etc/group, /etc/hosts and /etc/netid to
30 * create the database.
32 * If some user appears in passwd, they get an entry like:
33 * sun.<uid>@<domainname> <uid>:<gid1>,<gid2>,...
34 * If some host appears in hosts, it gets an entry like:
35 * sun.<hostname>@<domainname> 0:<hostname>
37 * The file /etc/netid is used to add other domains (possibly non-unix)
38 * to the database.
40 #include <stdio.h>
41 #include <pwd.h>
42 #include <limits.h>
43 #include <sys/param.h>
44 #include <rpc/rpc.h>
45 #include <rpc/key_prot.h>
48 #define MAXNAMELEN 256
49 #define MAXLINELEN 1024
50 #define MAXDOMAINLEN 32
52 #define GRPTABSIZE 256 /* size of group table */
53 #define PRNTABSIZE 4096 /* size of printed item table */
55 #define NUMGIDS (NGROUPS_MAX + 1) /* group-access-list + gid */
57 extern char **getaline();
58 extern char *malloc();
59 extern char *strcpy();
62 * The group list
63 * Store username and groups to which they belong
65 struct group_list {
66 char *user;
67 int group_len;
68 int groups[NUMGIDS];
69 struct group_list *next;
73 * General purpose list of strings
75 struct string_list {
76 char *str;
77 struct string_list *next;
80 static FILE *openfile();
81 static char *scanargs();
82 static int atoi();
84 static char *cmdname; /* name of this program */
85 static int quietmode; /* quiet mode: don't print error messages */
86 static char *curfile; /* name of file we are parsing */
87 static int curline; /* current line parsed in this file */
89 static struct group_list *groups[GRPTABSIZE]; /* group table */
90 static struct string_list *printed[PRNTABSIZE]; /* printed item table */
91 static char domain[MAXDOMAINLEN]; /* name of our domain */
93 static char PASSWD[] = "/etc/passwd"; /* default passwd database */
94 static char IDMAP[] = "/etc/idmap"; /* default net-id map database */
95 static char GROUP[] = "/etc/group"; /* default group database */
96 static char HOSTS[] = "/etc/hosts"; /* default hosts database */
98 static char *pwdfile = PASSWD; /* password file to parse */
99 static char *grpfile = GROUP; /* group file */
100 static char *hostfile = HOSTS; /* hosts file */
101 static char *mapfile = IDMAP; /* network id file */
104 * Various separaters
106 static char WHITE[] = "\t ";
107 static char COLON[] = ":";
108 static char COMMA[] = ",";
110 void domapfile(char *, FILE *);
111 void dogrpfile(char *, FILE *);
112 void dopwdfile(char *, FILE *);
113 void dohostfile(char *, FILE *);
114 static int Atoi(char *);
115 void check_getname(char **, char *, char *, char *, char *);
116 void multdef(char *);
117 static int wasprinted(char *);
118 void storegid(int, char *);
119 void printgroups(char *, int);
120 int parseargs(int, char *[]);
121 void put_s(char *);
122 void put_d(int);
126 main(argc, argv)
127 int argc;
128 char *argv[];
130 FILE *pf, *mf, *gf, *hf;
132 cmdname = argv[0];
133 if (!parseargs(argc, argv)) {
134 (void) fprintf(stderr,
135 "usage: %s [-q] [-pghm filename]\n", cmdname);
136 exit(1);
138 (void) getdomainname(domain, sizeof (domain));
140 pf = openfile(pwdfile);
141 gf = openfile(grpfile);
142 hf = openfile(hostfile);
143 mf = fopen(mapfile, "r");
146 if (mf != NULL) {
147 domapfile(mapfile, mf);
149 dogrpfile(grpfile, gf);
150 dopwdfile(pwdfile, pf);
151 dohostfile(hostfile, hf);
153 return (0);
154 /* NOTREACHED */
158 * Parse the network id mapping file
160 void
161 domapfile(mapfile, mf)
162 char *mapfile;
163 FILE *mf;
165 char **lp;
166 char line[MAXLINELEN];
167 char name[MAXNAMELEN];
168 int uid, gid;
170 curfile = mapfile;
171 curline = 0;
172 while (lp = getaline(line, sizeof (line), mf, &curline, "#")) {
173 check_getname(lp, name, WHITE, WHITE, "#");
174 if (wasprinted(name)) {
175 multdef(name);
176 continue;
178 put_s(name);
179 (void) putchar(' ');
180 check_getname(lp, name, WHITE, COLON, "#");
181 uid = Atoi(name);
182 put_d(uid);
183 (void) putchar(':');
184 if (uid == 0) {
185 check_getname(lp, name, WHITE, "\t\n ", "#");
186 put_s(name);
187 (void) putchar(' ');
188 } else {
189 check_getname(lp, name, WHITE, ",\n", "#");
190 gid = Atoi(name);
191 put_d(gid);
192 while (getname(name, sizeof (name), WHITE, ",\n", lp,
193 "#") >= 0) {
194 gid = Atoi(name);
195 (void) putchar(',');
196 put_d(gid);
199 (void) putchar('\n');
205 * Parse the groups file
207 void
208 dogrpfile(grpfile, gf)
209 char *grpfile;
210 FILE *gf;
212 char **lp;
213 char line[MAXLINELEN];
214 char name[MAXNAMELEN];
215 int gid;
217 curfile = grpfile;
218 curline = 0;
219 while (lp = getaline(line, sizeof (line), gf, &curline, "")) {
220 check_getname(lp, name, WHITE, COLON, "");
221 if (name[0] == '+') {
222 continue;
224 check_getname(lp, name, WHITE, COLON, ""); /* ignore passwd */
225 check_getname(lp, name, WHITE, COLON, "");
226 gid = Atoi(name);
227 while (getname(name, sizeof (name), WHITE, COMMA, lp,
228 "") >= 0) {
229 storegid(gid, name);
236 * Parse the password file
238 void
239 dopwdfile(pwdfile, pf)
240 char *pwdfile;
241 FILE *pf;
243 char **lp;
244 char line[MAXLINELEN];
245 char name[MAXNAMELEN];
246 char user[MAXNAMELEN];
247 int uid, gid;
249 curfile = pwdfile;
250 curline = 0;
252 while (lp = getaline(line, sizeof (line), pf, &curline, "")) {
253 check_getname(lp, user, WHITE, COLON, ""); /* username */
254 if (user[0] == '-' || user[0] == '+') {
255 continue; /* NIS entry */
257 check_getname(lp, name, WHITE, COLON, ""); /* ignore passwd */
258 check_getname(lp, name, WHITE, COLON, ""); /* but get uid */
259 uid = Atoi(name);
260 user2netname(name, uid, domain);
261 if (wasprinted(name)) {
262 multdef(name);
263 continue;
265 put_s(name);
266 (void) putchar(' ');
267 check_getname(lp, name, WHITE, COLON, "");
268 gid = Atoi(name);
269 put_d(uid);
270 (void) putchar(':');
271 printgroups(user, gid);
277 * Parse the hosts file
279 void
280 dohostfile(hostfile, hf)
281 char *hostfile;
282 FILE *hf;
284 char **lp;
285 char line[MAXLINELEN];
286 char name[MAXNAMELEN];
287 char netname[MAXNETNAMELEN];
289 curfile = hostfile;
290 curline = 0;
291 while (lp = getaline(line, sizeof (line), hf, &curline, "#")) {
292 check_getname(lp, name, WHITE, WHITE, "#");
293 if (getname(name, MAXNAMELEN, WHITE, WHITE, lp, "#") != 1) {
294 continue;
296 host2netname(netname, name, domain);
297 if (wasprinted(netname)) {
298 multdef(netname);
299 continue;
301 (void) printf("%s 0:%.*s\n", netname, sizeof (name), name);
306 * Open a file, exit on failure
308 static FILE *
309 openfile(fname)
310 char *fname;
312 FILE *f;
314 f = fopen(fname, "r");
315 if (f == NULL) {
316 (void) fprintf(stderr, "%s: can't open %s\n", cmdname, fname);
317 exit(1);
319 return (f);
323 * Print syntax error message, then exit
325 void
326 syntaxerror()
328 (void) fprintf(stderr, "%s: syntax error in file \"%s\", line %d\n",
329 cmdname, curfile, curline);
330 exit(1);
335 * an atoi() that prints a message and exits upong failure
337 static int
338 Atoi(str)
339 char *str;
341 int res;
343 if (!sscanf(str, "%d", &res)) {
344 syntaxerror();
346 return (res);
351 * Attempt to get a token from a file, print a message and exit upon failure
353 void
354 check_getname(lp, name, skip, term, com)
355 char **lp;
356 char *name;
357 char *skip;
358 char *term;
359 char *com;
361 if (getname(name, MAXNAMELEN, skip, term, lp, com) != 1) {
362 syntaxerror();
367 * Something was defined more than once
369 void
370 multdef(name)
371 char *name;
373 if (!quietmode) {
374 (void) fprintf(stderr,
375 "%s: %s multiply defined, other definitions ignored\n",
376 cmdname, name);
380 static int
381 hash(str, size)
382 unsigned char *str;
383 int size;
385 unsigned val;
386 int flip;
388 val = 0;
389 flip = 0;
390 while (*str) {
391 if (flip) {
392 val ^= (*str++ << 6);
393 } else {
394 val ^= *str++;
396 flip = !flip;
398 return (val % size);
403 * Check if an item has been printed
404 * If not, store the item into the printed item table
406 static int
407 wasprinted(name)
408 char *name;
410 struct string_list *s;
411 int val;
413 val = hash((unsigned char *) name, PRNTABSIZE);
414 for (s = printed[val]; s != NULL && strcmp(s->str, name); s = s->next)
416 if (s != NULL) {
417 return (1);
419 s = (struct string_list *)malloc(sizeof (struct string_list));
420 s->str = malloc((unsigned)strlen(name) + 1);
421 (void) strcpy(s->str, name);
422 s->next = printed[val];
423 printed[val] = s;
424 return (0);
428 * Add gid to the list of a user's groups
430 void
431 storegid(gid, user)
432 int gid;
433 char *user;
435 struct group_list *g;
436 int i;
437 int val;
439 val = hash((unsigned char *) user, GRPTABSIZE);
440 for (g = groups[val]; g != NULL && strcmp(g->user, user); g = g->next)
442 if (g == NULL) {
443 g = (struct group_list *)malloc(sizeof (struct group_list));
444 g->user = malloc((unsigned)strlen(user) + 1);
445 (void) strcpy(g->user, user);
446 g->group_len = 1;
447 g->groups[0] = gid;
448 g->next = groups[val];
449 groups[val] = g;
450 } else {
451 for (i = 0; i < g->group_len; i++) {
452 if (g->groups[i] == gid) {
453 return;
456 if (g->group_len >= NUMGIDS) {
457 (void) fprintf(stderr, "%s: %s's groups exceed %d\n",
458 cmdname, user, NGROUPS_MAX);
459 return;
461 g->groups[g->group_len++] = gid;
466 * print out a user's groups
468 void
469 printgroups(user, gid)
470 char *user;
471 int gid;
473 struct group_list *g;
474 int i;
475 int val;
477 val = hash((unsigned char *) user, GRPTABSIZE);
478 for (g = groups[val]; g != NULL && strcmp(g->user, user); g = g->next)
480 put_d(gid);
481 if (g != NULL) {
482 for (i = 0; i < g->group_len; i++) {
483 if (gid != g->groups[i]) {
484 (void) putchar(',');
485 put_d(g->groups[i]);
489 (void) putchar('\n');
494 * Parse command line arguments
497 parseargs(argc, argv)
498 int argc;
499 char *argv[];
501 int i;
502 int j;
503 static struct {
504 char letter;
505 char *standard;
506 char **filename;
507 } whattodo[] = {
508 { 'p', PASSWD, &pwdfile },
509 { 'g', GROUP, &grpfile },
510 { 'm', IDMAP, &mapfile },
511 { 'h', HOSTS, &hostfile }
514 #define TABSIZE sizeof (whattodo)/sizeof (whattodo[0])
516 for (i = 1; i < argc; i++) {
517 if (argv[i][0] == '-') {
518 if (argv[i][2] != 0) {
519 return (0);
521 if (argv[i][1] == 'q') {
522 quietmode = 1;
523 continue;
525 for (j = 0; j < TABSIZE; j++) {
526 if (whattodo[j].letter == argv[i][1]) {
527 if (*whattodo[j].filename !=
528 whattodo[j].standard) {
529 return (0);
531 if (++i == argc) {
532 return (0);
534 *whattodo[j].filename = argv[i];
535 break;
538 if (j == TABSIZE) {
539 return (0);
543 return (1);
547 * Print a string, quickly
549 void
550 put_s(s)
551 char *s;
553 (void) fwrite(s, strlen(s), 1, stdout);
557 * Print an integer, quickly
559 void
560 put_d(d)
561 int d;
563 char buf[20];
564 char *p;
566 if (d == 0) {
567 (void) putchar('0');
568 return;
570 if (d < 0) {
571 (void) putchar('-');
572 d = -d;
574 p = buf + sizeof (buf);
575 *--p = 0;
576 while (d > 0) {
577 *--p = (d % 10) + '0';
578 d /= 10;
580 put_s(p);