00001
00002
00003
00004
00005
00006 #define nil 0
00007 #define open _open
00008 #define fcntl _fcntl
00009 #define read _read
00010 #define close _close
00011 #include <sys/types.h>
00012 #include <grp.h>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 #include <unistd.h>
00016 #include <fcntl.h>
00017
00018 #define arraysize(a) (sizeof(a) / sizeof((a)[0]))
00019 #define arraylimit(a) ((a) + arraysize(a))
00020
00021 static char GROUP[]= "/etc/group";
00022 static const char *grfile;
00023
00024 static char buf[1024];
00025 static char grline[512];
00026 static struct group entry;
00027 static char *members[64];
00028 static int grfd= -1;
00029 static char *bufptr;
00030 static ssize_t buflen= 0;
00031 static char *lineptr;
00032
00033 void endgrent(void)
00034
00035 {
00036 if (grfd >= 0) {
00037 (void) close(grfd);
00038 grfd= -1;
00039 buflen= 0;
00040 }
00041 }
00042
00043 int setgrent(void)
00044
00045 {
00046 if (grfd >= 0) endgrent();
00047
00048 if (grfile == nil) grfile= GROUP;
00049
00050 if ((grfd= open(grfile, O_RDONLY)) < 0) return -1;
00051 (void) fcntl(grfd, F_SETFD, fcntl(grfd, F_GETFD) | FD_CLOEXEC);
00052 return 0;
00053 }
00054
00055 void setgrfile(const char *file)
00056
00057 {
00058 endgrent();
00059 grfile= file;
00060 }
00061
00062 static int getline(void)
00063
00064 {
00065 lineptr= grline;
00066
00067 do {
00068 if (buflen == 0) {
00069 if ((buflen= read(grfd, buf, sizeof(buf))) <= 0)
00070 return 0;
00071 bufptr= buf;
00072 }
00073
00074 if (lineptr == arraylimit(grline)) return 0;
00075 buflen--;
00076 } while ((*lineptr++ = *bufptr++) != '\n');
00077
00078 lineptr= grline;
00079 return 1;
00080 }
00081
00082 static char *scan_punct(int punct)
00083
00084 {
00085 char *field= lineptr;
00086 char *last;
00087
00088 for (;;) {
00089 last= lineptr;
00090 if (*lineptr == 0) return nil;
00091 if (*lineptr == '\n') break;
00092 if (*lineptr++ == punct) break;
00093 if (lineptr[-1] == ':') return nil;
00094 }
00095 *last= 0;
00096 return field;
00097 }
00098
00099 struct group *getgrent(void)
00100
00101 {
00102 char *p;
00103 char **mem;
00104
00105
00106 if (grfd < 0 && setgrent() < 0) return nil;
00107
00108
00109 for (;;) {
00110 if (!getline()) return nil;
00111
00112 if ((entry.gr_name= scan_punct(':')) == nil) continue;
00113 if ((entry.gr_passwd= scan_punct(':')) == nil) continue;
00114 if ((p= scan_punct(':')) == nil) continue;
00115 entry.gr_gid= strtol(p, nil, 0);
00116
00117 entry.gr_mem= mem= members;
00118 if (*lineptr != '\n') {
00119 do {
00120 if ((*mem= scan_punct(',')) == nil) goto again;
00121 if (mem < arraylimit(members) - 1) mem++;
00122 } while (*lineptr != 0);
00123 }
00124 *mem= nil;
00125 return &entry;
00126 again:;
00127 }
00128 }
00129
00130 struct group *getgrgid(_mnx_Gid_t gid)
00131
00132 {
00133 struct group *gr;
00134
00135 endgrent();
00136 while ((gr= getgrent()) != nil && gr->gr_gid != gid) {}
00137 endgrent();
00138 return gr;
00139 }
00140
00141 struct group *getgrnam(const char *name)
00142
00143 {
00144 struct group *gr;
00145
00146 endgrent();
00147 while ((gr= getgrent()) != nil && strcmp(gr->gr_name, name) != 0) {}
00148 endgrent();
00149 return gr;
00150 }