#include #include #include #include #include #include #include /* Parts of a /etc/group line */ enum GroupParts { GROUP_NAME, GROUP_GID, GROUP_USERS, }; static Group entry; static char entryName[33]; static char *entryMembers[64]; static char entryUsers[64 * 33]; /* Get part of a password line */ static char * get_part(char *line, int index, char *buf) { int i, len = 0; char *start; for (i = 0; i < index; i++) while (*line++ != ':'); start = line; while (*line != ':' && *line != '\n') { line++; len++; } memcpy(buf, start, len); buf[len] = '\0'; return buf; } /* Convert a string to a number */ static int number(char *str) { int num = 0, col = 1, len; for (len = 0; str[len] >= '0' && str[len] <= '9'; len++); while (len--) { num += (str[len] - '0') * col; col *= 10; } return num; } /* Move to next line */ static char * next_line(char *line) { while (*line++ != '\n'); return line; } /* Convert line to Grouop */ static Group * line_to_group(char *line) { if (!*line) return NULL; char gidstr[8]; get_part(line, GROUP_NAME, entryName); get_part(line, GROUP_GID, gidstr); get_part(line, GROUP_USERS, entryUsers); int i, j = 0; char *prev = entryUsers; for (i = 0; entryUsers[i]; i++) { if (entryUsers[i] != ' ') continue; entryUsers[i] = '\0'; entryMembers[j] = prev; prev = entryUsers + 1; j++; } entry.gr_name = entryName; entry.gr_gid = number(gidstr); entry.gr_mem = entryMembers; return &entry; } /* Get group file entry by name */ Group * getgrnam(const char *name) { int fd = open("/etc/group", O_RDONLY); if (fd < 0) return (Group *) fd; size_t sz = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); char *buf = malloc(sz); read(fd, buf, sz); close(fd); char *line, tmp[33]; for (line = buf; *line; line = next_line(line)) { get_part(line, GROUP_NAME, tmp); if (!strcmp(name, tmp)) break; } Group *res = line_to_group(line); free(buf); return res; } /* Get group file entry by ID */ Group * getgrgid(gid_t gid) { int fd = open("/etc/group", O_RDONLY); if (fd < 0) return (Group *) fd; size_t sz = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); char *buf = malloc(sz); read(fd, buf, sz); close(fd); char *line, tmp[8]; gid_t gidLine; for (line = buf; *line; line = next_line(line)) { get_part(line, GROUP_GID, tmp); gidLine = number(tmp); if (gid == gidLine) break; } Group *res = line_to_group(line); free(buf); return res; }