#include #include #include #include #include #include #include #include /* Parts of a /etc/passwd line */ enum PasswordParts { PASSWD_USERNAME, PASSWD_PASSWORD, PASSWD_UID, PASSWD_GID, PASSWD_INFO, PASSWD_HOMEDIR, PASSWD_SHELL, }; static Passwd entry; static char entryUsername[33]; static char entryPassword[128]; static char entryInfo[1024]; static char entryHomeDir[PATH_MAX]; static char entryShell[PATH_MAX]; /* 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 Passwd */ static Passwd * line_to_passwd(char *line) { if (!*line) return NULL; char uidstr[8], gidstr[8]; get_part(line, PASSWD_USERNAME, entryUsername); get_part(line, PASSWD_PASSWORD, entryPassword); get_part(line, PASSWD_UID, uidstr); get_part(line, PASSWD_GID, gidstr); get_part(line, PASSWD_INFO, entryInfo); get_part(line, PASSWD_HOMEDIR, entryHomeDir); get_part(line, PASSWD_SHELL, entryShell); entry.pw_name = entryUsername; entry.pw_passwd = entryPassword; entry.pw_uid = number(uidstr); entry.pw_gid = number(gidstr); entry.pw_gecos = entryInfo; entry.pw_dir = entryHomeDir; entry.pw_shell = entryShell; return &entry; } /* Get password file entry by name */ Passwd * getpwnam(const char *username) { int fd = open("/etc/passwd", O_RDONLY); if (fd < 0) return (Passwd *) 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, PASSWD_USERNAME, tmp); if (!strcmp(username, tmp)) break; } Passwd *res = line_to_passwd(line); free(buf); return res; } /* Get password file entry by ID */ Passwd * getpwuid(uid_t uid) { int fd = open("/etc/passwd", O_RDONLY); if (fd < 0) return (Passwd *) 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]; uid_t uidLine; for (line = buf; *line; line = next_line(line)) { get_part(line, PASSWD_UID, tmp); uidLine = number(tmp); if (uid == uidLine) break; } Passwd *res = line_to_passwd(line); free(buf); return res; }