Changeset View
Standalone View
bin/sh/parser.c
Show All 34 Lines | |||||
#ifndef lint | #ifndef lint | ||||
#if 0 | #if 0 | ||||
static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; | static char sccsid[] = "@(#)parser.c 8.7 (Berkeley) 5/16/95"; | ||||
#endif | #endif | ||||
#endif /* not lint */ | #endif /* not lint */ | ||||
#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> | ||||
#include "shell.h" | #include "shell.h" | ||||
#include "parser.h" | #include "parser.h" | ||||
#include "nodes.h" | #include "nodes.h" | ||||
#include "expand.h" /* defines rmescapes() */ | #include "expand.h" /* defines rmescapes() */ | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | |||||
static int xxreadtoken(void); | static int xxreadtoken(void); | ||||
static int readtoken1(int, const char *, const char *, int); | static int readtoken1(int, const char *, const char *, int); | ||||
static int noexpand(char *); | static int noexpand(char *); | ||||
static void consumetoken(int); | static void consumetoken(int); | ||||
static void synexpect(int) __dead2; | 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 * | ||||
parser_temp_alloc(size_t len) | parser_temp_alloc(size_t len) | ||||
{ | { | ||||
struct parser_temp *t; | struct parser_temp *t; | ||||
INTOFF; | INTOFF; | ||||
▲ Show 20 Lines • Show All 1,823 Lines • ▼ Show 20 Lines | if (c == '\n') { | ||||
/* Allow the backslash to be pushed back. */ | /* Allow the backslash to be pushed back. */ | ||||
pushstring("\\", 1, NULL); | pushstring("\\", 1, NULL); | ||||
return (pgetc()); | return (pgetc()); | ||||
} | } | ||||
} | } | ||||
return (c); | return (c); | ||||
} | } | ||||
static void | |||||
getusername(char *name, size_t namelen) | |||||
{ | |||||
static char cached_name[MAXLOGNAME]; | |||||
struct passwd *pw; | |||||
uid_t uid; | |||||
if (cached_name[0] == '\0') { | |||||
imp: We have the LOGNAME variable that's set (from login(8)):
The login utility enters… | |||||
Not Done Inline ActionsI used to run a system where we had 4 different users map to the same UID, but have different home directories, so we found (and often fixed) programs that didn't grok LOGNAME properly... So it can and does happen. imp: I used to run a system where we had 4 different users map to the same UID, but have different… | |||||
Done Inline ActionsThere are two problems with LOGNAME - first, the user (or script) can change it, and it seems kind of wrong to display that instead of the actual login name. Second - LOGNAME seems to be unaffected by su(1), so after you su from your normal user to root, it will still return the name of the normal user and not 'root'. The latter problem also seems to apply to getlogin(2). So, both ways seem somewhat suboptimal, in different ways. As it is now, sh(1) just calls whoami(1), and that does pretty much the same as the code added here. trasz: There are two problems with LOGNAME - first, the user (or script) can change it, and it seems… | |||||
Not Done Inline ActionsMore "proper" way would be to getpwnam based on LOGNAME (or getlogin(2)?) and use that if the passwd's UID matches geteuid(); otherwise, use getpwuid as now. jilles: More "proper" way would be to `getpwnam` based on `LOGNAME` (or `getlogin(2)`?) and use that if… | |||||
uid = geteuid(); | |||||
pw = getpwuid(uid); | |||||
if (pw != NULL) { | |||||
strlcpy(cached_name, pw->pw_name, | |||||
sizeof(cached_name)); | |||||
} else { | |||||
snprintf(cached_name, sizeof(cached_name), | |||||
"%u", uid); | |||||
} | |||||
} | |||||
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. | ||||
*/ | */ | ||||
char * | char * | ||||
getprompt(void *unused __unused) | getprompt(void *unused __unused) | ||||
{ | { | ||||
static char ps[PROMPTLEN]; | static char ps[PROMPTLEN]; | ||||
Show All 39 Lines | if (*fmt == '\\') | ||||
ps[i] = '\0'; | ps[i] = '\0'; | ||||
gethostname(&ps[i], PROMPTLEN - i - 1); | gethostname(&ps[i], PROMPTLEN - i - 1); | ||||
ps[PROMPTLEN - 1] = '\0'; | ps[PROMPTLEN - 1] = '\0'; | ||||
/* Skip to end of hostname. */ | /* Skip to end of hostname. */ | ||||
trim = (*fmt == 'h') ? '.' : '\0'; | trim = (*fmt == 'h') ? '.' : '\0'; | ||||
while ((ps[i] != '\0') && (ps[i] != trim)) | while ((ps[i] != '\0') && (ps[i] != trim)) | ||||
i++; | i++; | ||||
--i; | --i; | ||||
break; | |||||
/* | |||||
* User name. | |||||
*/ | |||||
case 'u': | |||||
Not Done Inline ActionsCan you write a regression test for this too? imp: Can you write a regression test for this too?
| |||||
Done Inline ActionsHm, we don't seem to have any tests for the prompt, do we? trasz: Hm, we don't seem to have any tests for the prompt, do we?
| |||||
ps[i] = '\0'; | |||||
getusername(&ps[i], PROMPTLEN - i); | |||||
/* Skip to end of username. */ | |||||
while (ps[i + 1] != '\0') | |||||
i++; | |||||
break; | break; | ||||
/* | /* | ||||
* Working directory. | * Working directory. | ||||
* | * | ||||
* \W specifies just the final component, | * \W specifies just the final component, | ||||
* \w specifies the entire path. | * \w specifies the entire path. | ||||
*/ | */ | ||||
▲ Show 20 Lines • Show All 106 Lines • Show Last 20 Lines |
We have the LOGNAME variable that's set (from login(8)):
so maybe use that instead and fall back to this as a backup?