]> andersk Git - moira.git/blob - gen/nfs.pc
don't free(groups) at end of do_everyone, because you might need it
[moira.git] / gen / nfs.pc
1 /* $Header$
2  *
3  * This generates the files necessary to load an nfs server.
4  *
5  *  (c) Copyright 1988, 1990 by the Massachusetts Institute of Technology.
6  *  For copying and distribution information, please see the file
7  *  <mit-copyright.h>.
8  */
9
10 #include <mit-copyright.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include <moira.h>
14 #include <moira_site.h>
15 #include <sys/types.h>
16 #include <sys/stat.h>
17 #include <sys/time.h>
18 EXEC SQL INCLUDE sqlca;
19
20
21 #define min(x,y)        ((x) < (y) ? (x) : (y))
22
23 char *whoami = "nfs.gen";
24 char *db = "moira/moira";
25 char *malloc(), *strsave();
26 char nfs_dir[64];
27 struct hash *users, *groups;
28
29
30 main(argc, argv)
31 int argc;
32 char **argv;
33 {
34     char cmd[64];
35     struct stat sb;
36     int changed = 0;
37
38     if (argc > 2) {
39         fprintf(stderr, "usage: %s [outfile]\n", argv[0]);
40         exit(MR_ARGS);
41     }
42
43     initialize_sms_error_table();
44     sprintf(nfs_dir, "%s/nfs", DCM_DIR);
45
46     EXEC SQL CONNECT :db;
47
48     changed = do_nfs();
49
50     EXEC SQL COMMIT;
51
52     if (!changed) {
53         fprintf(stderr, "No files updated.\n");
54         if (argc == 2 && stat(argv[1], &sb) == 0)
55           exit(MR_NO_CHANGE);
56     }
57
58     if (argc == 2) {
59         sprintf(cmd, "cd %s; cp %s/nfs/* .; tar cf %s .",
60                 nfs_dir, SMS_DIR, argv[1]);
61         if (system(cmd))
62           exit(MR_TAR_FAIL);
63     }
64
65     exit(MR_SUCCESS);
66 }
67
68
69 /* Generate the files.  Returns zero if nothing changed, non-zero otherwise. */
70
71 int do_nfs()
72 {
73     EXEC SQL BEGIN DECLARE SECTION;
74     char machname[41], listname[33];
75     EXEC SQL END DECLARE SECTION;
76     struct save_queue *machs, *lists;
77     int changed;
78
79     machs = sq_create();
80     lists = sq_create();
81
82     /* The following is declarative, not executed,
83      * and so is dependent on where it is in the file,
84      * not in the order of execution of statements.
85      */
86     EXEC SQL WHENEVER SQLERROR GOTO sqlerr;
87
88     EXEC SQL DECLARE s_cursor CURSOR FOR
89       SELECT m.name, s.value3
90       FROM machine m, serverhosts s
91       WHERE m.mach_id = s.mach_id AND s.service = 'NFS' AND s.enable != 0;
92     EXEC SQL OPEN s_cursor;
93     while (1) {
94         EXEC SQL FETCH s_cursor INTO :machname, :listname;
95         if (sqlca.sqlcode != 0) break;
96         sq_save_unique_string(machs, strsave(strtrim(machname)));
97         sq_save_unique_string(lists, strsave(strtrim(listname)));
98       }
99     EXEC SQL CLOSE s_cursor;
100
101     changed = do_lists(lists);
102     EXEC SQL COMMIT;
103     changed += do_machs(machs);
104     return(changed);
105  sqlerr:
106     db_error(sqlca.sqlcode);
107     exit(MR_DBMS_ERR);
108 }
109
110
111 /* Make all of the credentials lists that will be needed.  Returns 0 if
112  * no files were actually changed 
113  */
114
115 int do_lists(lists)
116 struct save_queue *lists;
117 {
118     char file[64], *u;
119     struct stat sb;
120     FILE *fd;
121     EXEC SQL BEGIN DECLARE SECTION;
122     char *listname, *lsname, lname[33], uname[9];
123     int uid, id, flag1, flag2, flag3, flag4;
124     EXEC SQL END DECLARE SECTION;
125
126     sprintf(file, "%s/list-", nfs_dir);
127     /*
128     if (stat(file, &sb) == 0) {
129         if ((ModDiff (&flag1, "users", sb.st_mtime)) ||
130             (ModDiff (&flag2, "list", sb.st_mtime)) ||
131             (ModDiff (&flag3, "imembers", sb.st_mtime)) ||
132             (ModDiff (&flag4, "serverhosts", sb.st_mtime))) exit (MR_DATE);
133         if (flag1 < 0 && flag2 < 0 && flag3 < 0 && flag4 < 0) {
134             fprintf(stderr, "The lists do not need to be rebuilt.\n");
135             return(0);
136         }
137     }
138     */
139
140
141     /* build the list of everyone, and store it in a file whose name
142      * corresponds to the empty list.
143      */
144     do_everyone();
145
146     fprintf(stderr, "Building specific lists\n");
147     /* now do each of the lists used by an NFS server */
148
149     while (sq_get_data(lists, &listname)) {
150         if (strlen(listname) == 0)
151           continue;
152         sprintf(file, "%s/list-%s", nfs_dir, listname);
153         fd = fopen(file, "w");
154         if (!fd) {
155             fprintf(stderr, "cannot open %s for output\n", file);
156             exit(MR_OCONFIG);
157         }
158
159         EXEC SQL DECLARE m_cursor CURSOR FOR
160           SELECT m.member_id
161           FROM imembers m, list l
162           WHERE m.list_id=l.list_id AND l.name = :listname AND
163             m.member_type='USER'
164           ORDER BY member_id;
165         EXEC SQL OPEN m_cursor;
166         while (1) {
167             EXEC SQL FETCH m_cursor INTO :id;
168             if (sqlca.sqlcode != 0) break;
169             if (u = hash_lookup(users, id))
170               fprintf(fd, "%s\n", u);
171         }
172         EXEC SQL CLOSE m_cursor;
173         if (fclose(fd) == EOF) {
174             fprintf(stderr, "error closing %s\n", file);
175             exit(MR_CCONFIG);
176         }
177     }
178 /* don't free here either
179     sq_destroy(lists);
180  */
181     return(1);
182  sqlerr:
183     db_error(sqlca.sqlcode);
184     exit(MR_DBMS_ERR);
185 }
186
187
188 /*  Build the list of everybody. */
189 struct grp {
190     struct grp *next;
191     char *lid;
192 };
193 struct user {
194     char name[9];
195     int uid;
196     struct grp *lists;
197 };
198
199
200 do_everyone()
201 {
202     char buf[BUFSIZ], *l;
203     struct user *u;
204     struct grp *g;
205     struct bucket *b, **p;
206     EXEC SQL BEGIN DECLARE SECTION;
207     char name[33];
208     int gid, id, lid, maxid, uid;
209     EXEC SQL END DECLARE SECTION;
210     FILE *fd;
211     int i;
212     struct save_queue *sq;
213
214     fprintf(stderr, "Building the list of everybody\n");
215     sprintf(buf, "%s/list-", nfs_dir);
216     fd = fopen(buf, "w");
217     if (!fd) {
218         fprintf(stderr, "cannot open %s for output\n", buf);
219         exit(MR_OCONFIG);
220     }
221
222     /* make space for group list */
223     groups = create_hash(15000);
224
225     /* retrieve simple groups */
226     EXEC SQL DECLARE l_cursor CURSOR FOR
227      SELECT gid, list_id
228      FROM list
229      WHERE grouplist != 0 AND active != 0
230      ORDER BY list_id;
231     EXEC SQL OPEN l_cursor;
232     while (1) {
233         EXEC SQL FETCH l_cursor INTO :gid, :lid;
234         if (sqlca.sqlcode != 0) break;
235         sprintf(buf, ":%d", gid);
236         hash_store(groups, lid, strsave(buf));
237       }
238     EXEC SQL CLOSE l_cursor;
239
240     /* now do grplists */
241     users = create_hash(10000);
242     EXEC SQL DECLARE u_cursor CURSOR FOR
243       SELECT users_id, login, unix_uid
244       FROM users
245       WHERE status = 1
246       ORDER BY users_id;
247     EXEC SQL OPEN u_cursor;
248     while (1) {
249         EXEC SQL FETCH u_cursor INTO :id, :name, :uid;
250         if (sqlca.sqlcode != 0) break;
251         u = (struct user *) malloc(sizeof(struct user));
252         strcpy(u->name, strtrim(name));
253         u->uid = uid;
254         u->lists = NULL;
255         hash_store(users, id, u);
256       }
257     EXEC SQL CLOSE u_cursor;
258
259     EXEC SQL DECLARE m_cursor2 CURSOR FOR
260       SELECT list_id, member_id
261       FROM imembers
262       WHERE member_type = 'USER'
263       ORDER BY list_id;
264     EXEC SQL OPEN m_cursor2;
265     while (1) {
266         EXEC SQL FETCH m_cursor2 INTO :lid, :id;
267         if (sqlca.sqlcode != 0) break;
268         if ((u = (struct user *) hash_lookup(users, id)) &&
269             ((l = hash_lookup(groups, lid)) != NULL)) {
270             g = (struct grp *) malloc(sizeof(struct grp));
271             g->next = u->lists;
272             u->lists = g;
273             g->lid = l;
274           }
275       }
276     EXEC SQL CLOSE m_cursor2;
277
278     for (p = &(users->data[users->size - 1]); p >= users->data; p--) {
279         for (b = *p; b; b = b->next) {
280             u = (struct user *)b->data;
281             sprintf(buf, "%s:%d", u->name, u->uid);
282             for (g = u->lists; g; g = g->next)
283               strcat(buf, g->lid);
284             b->data = strsave(buf);
285             fprintf(fd, "%s\n", buf);
286         }
287     }
288
289     fclose(fd);
290     return(1);
291  sqlerr:
292     db_error(sqlca.sqlcode);
293     exit(MR_DBMS_ERR);
294 }
295
296
297 /* Now do each of the servers, linking the credentials list file and 
298  * compiling the quota and dirs files.
299  */
300
301 int do_machs(machs)
302 struct save_queue *machs;
303 {
304     EXEC SQL BEGIN DECLARE SECTION;
305     char *machname, listname[33], dev[33], dir[81], fstype[9];
306     int uid, quota, id, gid, flag1, flag2, flag3, flag4;
307     EXEC SQL END DECLARE SECTION;
308     char file[64], f1[64], f2[64], *cp;
309     int prevuid, quotasum, olddev, oldmach;
310     FILE *fd;
311     struct hash *machines;
312
313     fprintf(stderr, "Building machine files\n");
314
315
316     machines = create_hash(100);
317     while (sq_get_data(machs, &machname)) {
318         EXEC SQL SELECT s.value3, m.mach_id
319           INTO :listname, :id
320           FROM serverhosts s, machine m
321           WHERE s.mach_id = m.mach_id AND m.name = :machname AND 
322             s.service = 'NFS';
323         strtrim(machname);
324         sprintf(f1, "%s/list-%s", nfs_dir, strtrim(listname));
325         sprintf(f2, "%s/%s.cred", nfs_dir, machname);
326         unlink(f2); /* ignore errors on this unlink */
327         if (link(f1, f2)) {
328             fprintf(stderr, "Cannot link %s to %s\n", f1, f2);
329             exit(MR_OCONFIG);
330         }
331         hash_store(machines, id, machname);
332     }
333
334
335     olddev = oldmach = -1;
336     fd = stdin;
337
338     EXEC SQL DECLARE q_cursor CURSOR FOR
339       SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id 
340       FROM quota q, nfsphys n
341       WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
342         n.status < 16 AND q.type = 'USER'
343       ORDER BY n.mach_id, q.phys_id, q.entity_id;
344     EXEC SQL OPEN q_cursor;
345     while (1) {
346         EXEC SQL FETCH q_cursor INTO :quota, :uid, :flag1, :dev, :flag2;
347         if (sqlca.sqlcode != 0) break;
348         if (flag1 != olddev || flag2 != oldmach) {
349             if (quotasum)
350               fprintf(fd, "%d %d\n", prevuid, quotasum);
351             if (flag2 == 0 || !hash_lookup(machines, flag2))
352               continue;
353             if (fd != stdin)
354               fclose(fd);
355             olddev = flag1;
356             oldmach = flag2;
357             while (cp = strchr(dev, '/')) *cp = '@';
358             sprintf(file, "%s/%s.%s.quotas", nfs_dir,
359                     hash_lookup(machines, flag2), strtrim(dev));
360             fd = fopen(file, "w");
361             if (!fd) {
362                 fprintf(stderr, "cannot open %s for output\n", file);
363                 exit(MR_OCONFIG);
364             }
365             prevuid = -1;
366             quotasum = 0;
367         }
368         if (uid != prevuid) {
369             if ((cp = hash_lookup(users, prevuid)) &&
370                 (cp = strchr(cp, ':')))
371               prevuid = atoi(cp+1);
372             if (quotasum)
373               fprintf(fd, "%d %d\n", prevuid, quotasum);
374             prevuid = uid;
375             quotasum = quota;
376         } else {
377             quotasum += quota;
378         }
379     }
380     EXEC SQL CLOSE q_cursor;
381     if ((cp = hash_lookup(users, prevuid)) &&
382         (cp = strchr(cp, ':')))
383       prevuid = atoi(cp+1);
384     if (quotasum)
385       fprintf(fd, "%d %d\n", prevuid, quotasum);
386     if (fd != stdin && fclose(fd) == EOF) {
387         fprintf(stderr, "error closing %s", file);
388         exit(MR_CCONFIG);
389       }
390
391     olddev = oldmach = -1;
392     fd = stdin;
393     EXEC SQL DECLARE q_cursor2 CURSOR FOR
394       SELECT DISTINCT q.quota, q.entity_id, q.phys_id, n.device, n.mach_id,
395         n.status 
396       FROM quota q, nfsphys n
397       WHERE n.nfsphys_id = q.phys_id AND q.phys_id != 0 AND
398         n.status > 15 AND q.type = 'GROUP'
399       ORDER BY mach_id, phys_id, entity_id;
400     EXEC SQL OPEN q_cursor2;
401     while (1) {
402         EXEC SQL FETCH q_cursor2 INTO :quota, :gid, :flag1, :dev,
403                 :flag2, :flag3;
404         if (sqlca.sqlcode != 0) break;
405         if (flag1 != olddev || flag2 != oldmach) {
406             if (quotasum)
407               fprintf(fd, "%d %d\n", prevuid, quotasum);
408             if (flag2 == 0 || !hash_lookup(machines, flag2))
409               continue;
410             if (fd != stdin)
411               fclose(fd);
412             olddev = flag1;
413             oldmach = flag2;
414             while (cp = strchr(dev, '/')) *cp = '@';
415             sprintf(file, "%s/%s.%s.quotas", nfs_dir,
416                     hash_lookup(machines, flag2), strtrim(dev));
417             fd = fopen(file, "w");
418             if (!fd) {
419                 fprintf(stderr, "cannot open %s for output\n", file);
420                 exit(MR_OCONFIG);
421             }
422             prevuid = -1;
423             quotasum = 0;
424         }
425         if (gid != prevuid) {
426             if (cp = hash_lookup(groups, prevuid))
427               prevuid = atoi(cp + 1);
428             if (quotasum)
429               fprintf(fd, "%d %d\n", prevuid, quotasum);
430             prevuid = gid;
431             quotasum = quota;
432         } else {
433             quotasum += quota;
434         }
435     }
436     EXEC SQL CLOSE q_cursor2;
437     if (cp = hash_lookup(groups, prevuid))
438       prevuid = atoi(cp + 1);
439     if (quotasum)
440       fprintf(fd, "%d %d\n", prevuid, quotasum);
441     if (fd != stdin && fclose(fd) == EOF) {
442         fprintf(stderr, "error closing %s", file);
443         exit(MR_CCONFIG);
444       }
445
446     olddev = oldmach = -1;
447     fd = stdin;
448
449     EXEC SQL DECLARE q_cursor3 CURSOR FOR
450       SELECT DISTINCT f.name, f.lockertype, u.unix_uid, l.gid, f.phys_id, 
451                 f.mach_id, n.device 
452       FROM users u, list l, nfsphys n, filesys f
453       WHERE u.users_id = f.owner AND 
454               l.list_id = f.owners AND
455               f.createflg != 0 AND f.phys_id != 0 AND
456               f.type = 'NFS' AND 
457               f.phys_id = n.nfsphys_id
458       ORDER BY mach_id, phys_id;
459     EXEC SQL OPEN q_cursor3;
460     while (1) {
461         EXEC SQL FETCH q_cursor3 INTO :dir, :fstype, :uid, :gid, :flag1,
462                         :flag2, :dev;
463         if (sqlca.sqlcode != 0) break;
464         if ((flag1 != olddev || flag2 != oldmach) &&
465             hash_lookup(machines, flag2)) {
466             if (fd != stdin)
467               fclose(fd);
468             olddev = flag1;
469             oldmach = flag2;
470             while (cp = strchr(dev, '/')) *cp = '@';
471             sprintf(file, "%s/%s.%s.dirs", nfs_dir,
472                     hash_lookup(machines, flag2), strtrim(dev));
473             fd = fopen(file, "w");
474             if (!fd) {
475                 fprintf(stderr, "cannot open %s for output\n", file);
476                 exit(MR_OCONFIG);
477             }
478         }
479         fprintf(fd, "%s %d %d %s\n", strtrim(dir), uid, gid, strtrim(fstype));
480     }    
481     EXEC SQL CLOSE q_cursor3;
482     if (fclose(fd) == EOF) {
483         fprintf(stderr, "error closing %s", file);
484         exit(MR_CCONFIG);
485     }
486     return(1);
487  sqlerr:
488     db_error(sqlca.sqlcode);
489     exit(MR_DBMS_ERR);
490 }
This page took 0.078214 seconds and 5 git commands to generate.