Make sh(1) support \u in PS1. This removes one fork/exec on interactive

shell startup.

Reviewed by:	0mp (man page), jilles
MFC after:	2 weeks
Sponsored by:	DARPA, AFRL
Differential Revision:	https://reviews.freebsd.org/D18790
This commit is contained in:
trasz 2019-01-24 11:59:46 +00:00
parent 312adcd942
commit 7ebd53a49f
3 changed files with 65 additions and 2 deletions

View File

@ -40,6 +40,8 @@ static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95";
#include <sys/cdefs.h> #include <sys/cdefs.h>
__FBSDID("$FreeBSD$"); __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <pwd.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
@ -130,6 +132,7 @@ static void synexpect(int) __dead2;
static void synerror(const char *) __dead2; static void synerror(const char *) __dead2;
static void setprompt(int); static void setprompt(int);
static int pgetc_linecont(void); static int pgetc_linecont(void);
static void getusername(char *, size_t);
static void * static void *
@ -1969,6 +1972,53 @@ pgetc_linecont(void)
return (c); return (c);
} }
static struct passwd *
getpwlogin(void)
{
const char *login;
login = getlogin();
if (login == NULL)
return (NULL);
return (getpwnam(login));
}
static void
getusername(char *name, size_t namelen)
{
static char cached_name[MAXLOGNAME];
struct passwd *pw;
uid_t euid;
if (cached_name[0] == '\0') {
euid = geteuid();
/*
* Handle the case when there is more than one
* login with the same UID, or when the login
* returned by getlogin(2) does no longer match
* the current UID.
*/
pw = getpwlogin();
if (pw == NULL || pw->pw_uid != euid)
pw = getpwuid(euid);
if (pw != NULL) {
strlcpy(cached_name, pw->pw_name,
sizeof(cached_name));
} else {
snprintf(cached_name, sizeof(cached_name),
"%u", euid);
}
}
strlcpy(name, cached_name, namelen);
}
/* /*
* called by editline -- any expansions to the prompt * called by editline -- any expansions to the prompt
* should be added here. * should be added here.
@ -2026,6 +2076,17 @@ getprompt(void *unused __unused)
--i; --i;
break; break;
/*
* User name.
*/
case 'u':
ps[i] = '\0';
getusername(&ps[i], PROMPTLEN - i);
/* Skip to end of username. */
while (ps[i + 1] != '\0')
i++;
break;
/* /*
* Working directory. * Working directory.
* *

View File

@ -32,7 +32,7 @@
.\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95 .\" from: @(#)sh.1 8.6 (Berkeley) 5/4/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd December 8, 2018 .Dd January 24, 2019
.Dt SH 1 .Dt SH 1
.Os .Os
.Sh NAME .Sh NAME
@ -1402,6 +1402,8 @@ which are replaced by the given information:
This system's fully-qualified hostname (FQDN). This system's fully-qualified hostname (FQDN).
.It Li \eh .It Li \eh
This system's hostname. This system's hostname.
.It Li \eu
User name.
.It Li \eW .It Li \eW
The final component of the current working directory. The final component of the current working directory.
.It Li \ew .It Li \ew

View File

@ -33,7 +33,7 @@ alias g='egrep -i'
# set prompt: ``username@hostname:directory $ '' # set prompt: ``username@hostname:directory $ ''
PS1="`whoami`@\h:\w \\$ " PS1="\u@\h:\w \\$ "
# search path for cd(1) # search path for cd(1)
# CDPATH=:$HOME # CDPATH=:$HOME