mailing list of musl libc
 help / color / mirror / code / Atom feed
* Proposed getlogin[_r] replacement
@ 2015-06-22  6:22 Rich Felker
  0 siblings, 0 replies; only message in thread
From: Rich Felker @ 2015-06-22  6:22 UTC (permalink / raw)
  To: musl

[-- Attachment #1: Type: text/plain, Size: 440 bytes --]

The attached getlogin[_r] implementation (with simple test program)
fixes conformance issues with the current one, which uses the
environment rather than (as required by POSIX) the controlling tty to
determine the identity of the logged-in user. It's missing protection
against cancellation points but otherwise should be doing correct
error-checking. If no problems are seen I'd like to go ahead and
commit it in this release cycle.

Rich

[-- Attachment #2: new_getlogin_3.c --]
[-- Type: text/plain, Size: 1541 bytes --]

#include <stdio.h>
#include <pwd.h>
#include <limits.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/sysmacros.h>

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;
}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2015-06-22  6:22 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-22  6:22 Proposed getlogin[_r] replacement Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).