chiark / gitweb /
[PATCH] add $local user spport for permissions
authorkay.sievers@vrfy.org <kay.sievers@vrfy.org>
Tue, 2 Mar 2004 06:42:30 +0000 (22:42 -0800)
committerGreg KH <gregkh@suse.de>
Wed, 27 Apr 2005 04:35:06 +0000 (21:35 -0700)
klibc_fixups.c
klibc_fixups.h
udev-add.c

index 927f2f6..1241eb7 100644 (file)
@@ -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
index 19bfd51..f6c91cd 100644 (file)
@@ -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__ */
index 3a72c54..19196be 100644 (file)
@@ -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);