tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

mail(1) - $USER == -u user



Hello once again,
i've stumbled over weird user handling in the nail codebase and
thought this should be improved.
The situation is rather identical in NetBSD mail(1), but even
worse :), since (a) $USER is documented and (b) the manual falsely
claims that '-u user' is equivalent to '-f mailbox-of-user';
i know this is what POSIX states for mailx(1), but in fact the
codebase uses the 'myname' for much more than just that.
What i've implemented for S-nail(1), and what the diff below does
for NetBSD mail(1), is that $USER becomes equivalent to '-u user';
an additional system call is always required (..terrible..), but
we gracefully detect incarnations as other users and (possibly)
save (multiple) system calls at other places because we do perform
caching for getuid() etc.  I think this approach is more sane than
what was present before.
(And note my repo hasn't been updated for about two months, i'm
behind GPRS most of the time, but i don't remember any mail
change?  On interest and otherwise i'll update and resend.)
Ciao,

--steffen

diff -Napru nmail/Makefile nmail.user/Makefile
--- nmail/Makefile      2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/Makefile 2013-12-09 20:34:20.000000000 +0100
@@ -23,7 +23,7 @@ CPPFLAGS+=    -DBROKEN_MAGIC                  # bad MIME t
 
 PROG=  mail
 SRCS=  version.c support.c cmd1.c cmd2.c cmd3.c cmd4.c cmdtab.c collect.c \
-       dotlock.c edit.c fio.c format.c getname.c head.c v7.local.c lex.c \
+       dotlock.c edit.c fio.c format.c head.c v7.local.c lex.c \
        list.c main.c names.c popen.c quit.c send.c sig.c strings.c temp.c \
        tty.c vars.c
 LINKS= ${BINDIR}/mail ${BINDIR}/Mail ${BINDIR}/mail ${BINDIR}/mailx
diff -Napru nmail/extern.h nmail.user/extern.h
--- nmail/extern.h      2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/extern.h 2013-12-09 20:34:10.000000000 +0100
@@ -169,12 +169,6 @@ FILE *     setinput(const struct message *);
 void   setptr(FILE *, off_t);
 
 /*
- * from getname.c
- */
-const char *getname(uid_t);
-int    getuserid(char []);
-
-/*
  * from head.c
  */
 int    ishead(const char []);
@@ -331,7 +325,6 @@ char *      vcopy(const char []);
  */
 void   demail(void);
 void   findmail(const char *, char *, size_t);
-const char *username(void);
 
 /*
  * from version.c
diff -Napru nmail/getname.c nmail.user/getname.c
--- nmail/getname.c     2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/getname.c        1970-01-01 01:00:00.000000000 +0100
@@ -1,71 +0,0 @@
-/*     $NetBSD: getname.c,v 1.11 2006/11/28 18:45:32 christos Exp $    */
-
-/*
- * Copyright (c) 1980, 1993
- *     The Regents of the University of California.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-#ifndef lint
-#if 0
-static char sccsid[] = "@(#)getname.c  8.1 (Berkeley) 6/6/93";
-#else
-__RCSID("$NetBSD: getname.c,v 1.11 2006/11/28 18:45:32 christos Exp $");
-#endif
-#endif /* not lint */
-
-#include "rcv.h"
-#include "extern.h"
-
-/* Getname / getuserid for those with hashed passwd data base). */
-
-/*
- * Search the passwd file for a uid.  Return name on success, NULL on failure
- */
-PUBLIC const char *
-getname(uid_t uid)
-{
-       struct passwd *pw;
-
-       if ((pw = getpwuid(uid)) == NULL)
-               return NULL;
-       return pw->pw_name;
-}
-
-/*
- * Convert the passed name to a user id and return it.  Return -1
- * on error.
- */
-PUBLIC int
-getuserid(char name[])
-{
-       struct passwd *pw;
-
-       if ((pw = getpwnam(name)) == NULL)
-               return -1;
-       return pw->pw_uid;
-}
diff -Napru nmail/glob.h nmail.user/glob.h
--- nmail/glob.h        2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/glob.h   2013-12-09 20:33:43.000000000 +0100
@@ -64,7 +64,9 @@ EXTERN char   prevfile[PATHSIZE];             /* Name
 EXTERN char    *tmpdir;                        /* Path name of temp directory 
*/
 EXTERN char    *homedir;                       /* Path name of home directory 
*/
 EXTERN char    *origdir;                       /* Path name of directory we 
started in */
-EXTERN char    *myname;                        /* My login name */
+EXTERN char    *myname;                        /* My login/-u user/$USER.. */
+EXTERN unsigned        myuid;                          /* It's UID */
+EXTERN unsigned        theuid;                         /* getuid() */
 EXTERN off_t   mailsize;                       /* Size of system mailbox */
 EXTERN struct  message *dot;                   /* Pointer to current message */
 EXTERN struct  var     *variables[HSHSIZE];    /* Pointer to active var list */
diff -Napru nmail/lex.c nmail.user/lex.c
--- nmail/lex.c 2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/lex.c    2013-12-09 20:34:05.000000000 +0100
@@ -206,7 +206,7 @@ setfile(const char *name)
        FILE *ibuf;
        int i, fd;
        struct stat stb;
-       char isedit = *name != '%' || getuserid(myname) != (int)getuid();
+       char isedit = *name != '%' || myuid != theuid;
        const char *who = name[1] ? name + 1 : myname;
        static int shudclob;
        char tempname[PATHSIZE];
diff -Napru nmail/mail.1 nmail.user/mail.1
--- nmail/mail.1        2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/mail.1   2013-12-09 20:21:02.000000000 +0100
@@ -133,7 +133,9 @@ Specify subject on command line
 flag is used as a subject; be careful to quote subjects
 containing spaces.)
 .It Fl u
-Is equivalent to:
+Pretend to be
+.Ar user
+in some aspects and also do the equivalent to:
 .Pp
 .Dl mail -f /var/mail/user
 .It Fl v
diff -Napru nmail/temp.c nmail.user/temp.c
--- nmail/temp.c        2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/temp.c   2013-12-09 20:46:17.000000000 +0100
@@ -54,6 +54,7 @@ tinit(void)
        char pathbuf[MAXPATHLEN];
        const char *cp;
        char *p;
+       struct passwd *pwuid, *pw;
 
        /*
         * It's okay to call savestr in here because main will
@@ -71,18 +72,25 @@ tinit(void)
                p--;
        }
 
-       if (myname != NULL) {
-               if (getuserid(myname) < 0)
-                       errx(EXIT_FAILURE, "`%s' is not a user of this system", 
myname);
-       }
+       cp = (myname == NULL) ? getenv("USER") : myname;
+       myuid = theuid = (unsigned)getuid();
+       if ((pwuid = getpwuid((uid_t)theuid)) == NULL) {
+               (void)printf("Cannot associate a name with uid %u\n", theuid);
+               if (mailmode == mm_receiving)
+                       errx(EXIT_FAILURE, "who am I receiving for?");
+               myname = __UNCONST("nobody");
+       } else if (cp == NULL)
+               myname = pwuid->pw_name;
+       else if ((pw = getpwnam(cp)) == NULL)
+               errx(EXIT_FAILURE, "`%s' is not a user of this system", cp);
        else {
-               if ((cp = username()) == NULL) {
-                       myname = savestr("nobody");
-                       if (mailmode == mm_receiving)
-                               errx(EXIT_FAILURE, "who am I receiving for?");
-               } else
-                       myname = savestr(cp);
+               myname = pw->pw_name;
+               myuid = (unsigned)pw->pw_uid;
+               if (myuid != theuid)
+                       (void)unsetenv("MAIL");
        }
+       myname = savestr(myname);
+
        if ((cp = getenv("HOME")) == NULL)
                cp = ".";
        homedir = savestr(cp);
diff -Napru nmail/v7.local.c nmail.user/v7.local.c
--- nmail/v7.local.c    2013-12-09 13:16:52.000000000 +0100
+++ nmail.user/v7.local.c       2013-12-09 20:21:22.000000000 +0100
@@ -81,20 +81,3 @@ demail(void)
                if ((fd = creat(mailname, 0600)) != -1)
                        (void)close(fd);
 }
-
-/*
- * Discover user login name.
- */
-PUBLIC const char *
-username(void)
-{
-       const char *np;
-       uid_t uid;
-
-       if ((np = getenv("USER")) != NULL)
-               return np;
-       if ((np = getname(uid = getuid())) != NULL)
-               return np;
-       (void)printf("Cannot associate a name with uid %u\n", (unsigned)uid);
-       return NULL;
-}


Home | Main Index | Thread Index | Old Index