On 12/25/2016 05:12 PM, Wietse Venema wrote:
> John Fawcett:
>> for an inexistent user for strings up to 31 chars. From 32 chars onwards
>> instead of returning not found it retuns EINVAL (invalid argument).
>>
>> ./test AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>> Not found
>> ./test AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
>> getpwnam_r: Invalid argument
> Perhaps they want programs to call sysconf(_SC_LOGIN_NAME_MAX)
> (note that the result includes the null terminator).
>
> Wietse
>
> #include <pwd.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <unistd.h>
> #include <errno.h>
>
> int main(int argc, char *argv[])
> {
> struct passwd pwd;
> struct passwd *result;
> char *buf;
> size_t bufsize;
> int s;
>
> if (argc != 2) {
> fprintf(stderr, "Usage: %s username\n", argv[0]);
> exit(EXIT_FAILURE);
> }
> bufsize = sysconf(_SC_GETPW_R_SIZE_MAX);
> if (bufsize == -1) /* Value was indeterminate */
> bufsize = 16384; /* Should be more than enough
> */
>
> buf = malloc(bufsize);
> if (buf == NULL) {
> perror("malloc");
> exit(EXIT_FAILURE);
> }
> /* _SC_LOGIN_NAME_MAX includes the null terminator */
> if (strlen(argv[1]) >= sysconf(_SC_LOGIN_NAME_MAX)) {
> fprintf(stderr, "warning: name exceeds _SC_LOGIN_NAME_MAX\n");
> result = 0;
> s = 0;
> } else {
> s = getpwnam_r(argv[1], &pwd, buf, bufsize, &result);
> }
> if (result == NULL) {
> if (s == 0)
> printf("Not found\n");
> else {
> errno = s;
> perror("getpwnam_r");
> }
> exit(EXIT_FAILURE);
> }
> printf("Name: %s; UID: %ld\n", pwd.pw_gecos, (long) pwd.pw_uid);
> free(buf);
> exit(EXIT_SUCCESS);
> }
I tried that on archlinux. The above program still produces EINVAL for
login names between 32 and 255 inclusive.
_SC_LOGIN_NAME_MAX is 256 on that platform.
John