I got a problem report from Mark Willson:

    "I recently installed mg (via the Debian package) under WSL on Windows
    I found that the 'backup-to-home-directory' option didn't work.

    The cause of this appears to be that getlogin under WSL returns NULL,
    probably due to my use of wsltty to invoke bash.  The patch below fixes
    the issue for me:"

-               if ((un = getlogin()) != NULL)
+               if ((un = getenv("LOGNAME")) != NULL)

Which put me onto the track of what was going on. I found the
following in the Linux manpage:

       Unfortunately, it is often rather easy to fool  getlogin().
       it  does not work at all, because some program messed up the utmp
       Often, it gives only the first 8 characters of  the  login  name.
       user  currently  logged  in  on the controlling terminal of our
       need not be the user who started it.  Avoid  getlogin()  for
       related purposes.

       Note  that glibc does not follow the POSIX specification and uses
       instead of /dev/tty.  A bug.  (Other recent systems, like SunOS 5.8
       HP-UX  11.11  and FreeBSD 4.8 all return the login name also when
       is redirected.)

       Nobody knows precisely what cuserid() does; avoid it in  portable
       grams.   Or  avoid  it  altogether: use getpwuid(geteuid()) instead,
       that is what you meant.  Do not use cuserid().

So I started looking at the code and rewrote it a bit, which I think
makes it more portable and removes a syscall in the process. I do
suspect this can be written even more elegantly, but didn't want to
rework the code too much.

I also took the liberty to remove some whitespace.

Index: fileio.c
RCS file: /cvs/src/usr.bin/mg/fileio.c,v
retrieving revision 1.104
@@ -703,7 +706,7 @@ expandtilde(const char *fn)
        struct stat      statbuf;
        const char      *cp;
        char             user[LOGIN_NAME_MAX], path[NFILEN];
-       char            *un, *ret;
+       char            *ret;
        size_t           ulen, plen;

        path[0] = '\0';
@@ -722,21 +725,21 @@ expandtilde(const char *fn)
                        return (NULL);
+       pw = getpwuid(geteuid());
        if (ulen == 0) { /* ~/ or ~ */
-               if ((un = getlogin()) != NULL)
-                       (void)strlcpy(user, un, sizeof(user));
+               if (pw != NULL)
+                       (void)strlcpy(user, pw->pw_name, sizeof(user));
                        user[0] = '\0';
        } else { /* ~user/ or ~user */
                memcpy(user, &fn[1], ulen);
                user[ulen] = '\0';
-       pw = getpwnam(user);
        if (pw != NULL) {
                plen = strlcpy(path, pw->pw_dir, sizeof(path));
                if (plen == 0 || path[plen - 1] != '/') {
                        if (strlcat(path, "/", sizeof(path)) >=
sizeof(path)) {
-                               dobeep();
+                               dobeep();
                                ewprintf("Path too long");
                                return (NULL);

Reply via email to