added -A and -U
[tridge/junkcode.git] / getgrent_replace.c
1 /*
2   a replacement for getgrent() on AIX that enumerates 
3   all user databases, not just /etc/group
4
5   Andrew Tridgell tridge@au.ibm.com
6   February 2004
7 */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <grp.h>
12 #include <usersec.h>
13 #include <sys/types.h>
14
15
16 static struct {
17         char *all_groups;
18         char *next;
19 } getgrent_state;
20
21
22 /*
23   free up any resources associated with getgrent() 
24 */
25 void endgrent(void)
26 {
27         if (getgrent_state.all_groups) {
28                 free(getgrent_state.all_groups);
29         }
30         getgrent_state.all_groups = NULL;
31         getgrent_state.next = NULL;
32 }
33
34
35 /*
36   reset the state to the start of the group database
37 */
38 void setgrent(void)
39 {
40         char *s;
41         endgrent();
42         /* getgroupattr returns a null separated list of groups,
43            with each group being of the form REGISTRY:GROUPNAME */
44         if (getgroupattr("ALL", "groups", &s, SEC_CHAR) == 0) {
45                 getgrent_state.all_groups = s;
46                 getgrent_state.next = getgrent_state.all_groups;
47         }
48         
49 }
50
51 /*
52   get the next group
53 */
54 struct group *getgrent(void)
55 {
56         char *group;
57         struct group *grp;
58         if (!getgrent_state.all_groups) {
59                 setgrent();
60                 if (!getgrent_state.all_groups) {
61                         return NULL;
62                 }
63         }
64         do {
65                 group = getgrent_state.next;
66                 if (!*group) {
67                         endgrent();
68                         return NULL;
69                 }
70                 group = strchr(group, ':');
71                 if (!group) {
72                         endgrent();
73                         return NULL;
74                 }
75                 grp = getgrnam(group+1);
76                 getgrent_state.next += strlen(getgrent_state.next)+1;
77         } while (!grp);
78
79         return grp;
80 }
81
82
83 #if TEST_PROGRAM
84 int main(void)
85 {
86         struct group *grp;
87
88         setgrent();
89
90         while ((grp = getgrent())) {
91                 printf("%s\n", grp->gr_name);
92         }
93         
94         endgrent();
95
96         return 0;
97 }
98 #endif