#include #include #include #include #include #include #include #include #include #include int getlogin_r(char *buf, size_t size) { struct passwd pw, *ppw; char pw_buf[1024]; struct stat st; char tty_buf[TTY_NAME_MAX]; int i; dev_t dev; char procbuf[1024]; int fd = open("/proc/self/stat", O_RDONLY|O_CLOEXEC); if (fd < 0) switch (errno) { case EMFILE: case ENFILE: return errno; default: return ENOSYS; } int n = read(fd, procbuf, sizeof procbuf - 1); close(fd); if (n < 0) return ENOSYS; procbuf[n] = 0; char *s = strrchr(procbuf, ')'); if (!s) return ENOSYS; for (i=0; i<5 && *s; i+=(*s++==' ')); if (!*s) return ENOSYS; for (dev=0; isdigit(*s); s++) dev = 10*dev + (*s-'0'); if (!dev) return ENXIO; for (i=0; i<3; i++) if (!fstat(i, &st) && S_ISCHR(st.st_mode) && st.st_rdev == dev) break; snprintf(tty_buf, sizeof tty_buf, "/dev/pts/%u", (unsigned)minor(dev)); if (i<3 || (!stat(tty_buf, &st) && S_ISCHR(st.st_mode) && st.st_rdev == dev)) { getpwuid_r(st.st_uid, &pw, pw_buf, sizeof pw_buf, &ppw); size_t l = strlen(pw.pw_name); if (l >= LOGIN_NAME_MAX) return EOVERFLOW; if (l >= size) return ERANGE; memcpy(buf, pw.pw_name, l+1); return 0; } return ENOTTY; } char *getlogin() { static char buf[LOGIN_NAME_MAX]; int r = getlogin_r(buf, sizeof buf); if (r) { errno = r; return 0; } return buf; } int main() { printf("%s %m\n", getlogin()); return 0; }