diff options
-rw-r--r-- | klibc_fixups.c | 37 | ||||
-rw-r--r-- | klibc_fixups.h | 47 | ||||
-rw-r--r-- | udev-add.c | 37 |
3 files changed, 119 insertions, 2 deletions
diff --git a/klibc_fixups.c b/klibc_fixups.c index 927f2f649a..1241eb7d10 100644 --- a/klibc_fixups.c +++ b/klibc_fixups.c @@ -25,6 +25,7 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <fcntl.h> #include <sys/types.h> #include "klibc_fixups.h" @@ -32,6 +33,8 @@ #define PW_FILE "/etc/passwd" #define GR_FILE "/etc/group" +#define UTMP_FILE "/var/run/utmp" + /* return the id of a passwd style line, selected by the users name */ static unsigned long get_id_by_name(const char *uname, const char *dbfile) @@ -107,4 +110,38 @@ struct group *getgrnam(const char *name) return &gr; } + +int ufd = -1; + +void setutent() +{ + if (ufd < 0) + ufd = open(UTMP_FILE, O_RDONLY); + fcntl(ufd, F_SETFD, FD_CLOEXEC); + lseek(ufd, 0, SEEK_SET); +} + +void endutent() { + if (ufd < 0) + return; + close(ufd); + ufd = -1; +} + +struct utmp *getutent(void) +{ + static struct utmp utmp; + int retval; + + if (ufd < 0) { + setutent(); + if (ufd < 0) + return NULL; + } + retval = read(ufd, &utmp, sizeof(struct utmp)); + if (retval < 1) + return NULL; + return &utmp; +} + #endif diff --git a/klibc_fixups.h b/klibc_fixups.h index 19bfd51caa..f6c91cdd94 100644 --- a/klibc_fixups.h +++ b/klibc_fixups.h @@ -1,7 +1,7 @@ #ifdef __KLIBC__ #ifndef KLIBC_FIXUPS_H -#define KLIBC_FIXUPS_H +#define KLIBC_FIXUPS_H struct passwd { char *pw_name; /* user name */ @@ -23,6 +23,49 @@ struct group { struct passwd *getpwnam(const char *name); struct group *getgrnam(const char *name); -#endif +#define UT_LINESIZE 32 +#define UT_NAMESIZE 32 +#define UT_HOSTSIZE 256 +#define USER_PROCESS 7 /* normal process */ +#define ut_time ut_tv.tv_sec + + +extern int ufd; + +struct exit_status { + short int e_termination; /* process termination status */ + short int e_exit; /* process exit status */ +}; + +struct utmp +{ + short int ut_type; /* type of login */ + pid_t ut_pid; /* pid of login process */ + char ut_line[UT_LINESIZE]; /* devicename */ + char ut_id[4]; /* Inittab id */ + char ut_user[UT_NAMESIZE]; /* username */ + char ut_host[UT_HOSTSIZE]; /* hostname for remote login */ + struct exit_status ut_exit; /* exit status of a process marked as DEAD_PROCESS */ + /* The ut_session and ut_tv fields must be the same size for 32 and 64-bit */ +#if __WORDSIZE == 64 && defined __WORDSIZE_COMPAT32 + int32_t ut_session; /* sid used for windowing */ + struct { + int32_t tv_sec; /* seconds */ + int32_t tv_usec; /* microseconds */ + } ut_tv; +#else + long int ut_session; + struct timeval ut_tv; #endif + int32_t ut_addr_v6[4]; /* internet address of remote host */ + char __unused[20]; /* reserved for future use */ +}; + +struct utmp *getutent(void); +void setutent(void); +void endutent(void); + + +#endif /* KLIBC_FIXUPS_H */ +#endif /* __KLIBC__ */ diff --git a/udev-add.c b/udev-add.c index 3a72c544b8..19196bec54 100644 --- a/udev-add.c +++ b/udev-add.c @@ -32,6 +32,7 @@ #include <grp.h> #ifndef __KLIBC__ #include <pwd.h> +#include <utmp.h> #endif #include "libsysfs/sysfs/libsysfs.h" @@ -44,6 +45,8 @@ #include "udevdb.h" #include "klibc_fixups.h" +#define LOCAL_USER "$local" + /* * Right now the major/minor of a device is stored in a file called * "dev" in sysfs. @@ -132,6 +135,37 @@ static int make_node(char *filename, int major, int minor, unsigned int mode, ui return 0; } +/* get the local logged in user */ +static void set_to_local_user(char *user) +{ + struct utmp *u; + time_t recent = 0; + + strnfieldcpy(user, default_owner_str, OWNER_SIZE); + setutent(); + while (1) { + u = getutent(); + if (u == NULL) + break; + + /* is this a user login ? */ + if (u->ut_type != USER_PROCESS) + continue; + + /* is this a local login ? */ + if (strcmp(u->ut_host, "")) + continue; + + if (u->ut_time > recent) { + recent = u->ut_time; + strfieldcpy(user, u->ut_user); + dbg("local user is '%s'", user); + break; + } + } + endutent(); +} + static int create_node(struct udevice *dev, int fake) { struct stat stats; @@ -175,6 +209,9 @@ static int create_node(struct udevice *dev, int fake) if (endptr[0] == '\0') uid = (uid_t) id; else { + if (strncmp(dev->owner, LOCAL_USER, sizeof(LOCAL_USER)) == 0) + set_to_local_user(dev->owner); + struct passwd *pw = getpwnam(dev->owner); if (pw == NULL) dbg("specified user unknown '%s'", dev->owner); |