Index: parser.c =================================================================== RCS file: /cvsroot/src/bin/sh/parser.c,v retrieving revision 1.54 diff -u -u -r1.54 parser.c --- parser.c 2002/11/24 22:35:42 1.54 +++ parser.c 2003/01/18 10:38:58 @@ -46,6 +46,7 @@ #endif /* not lint */ #include +#include #include "shell.h" #include "parser.h" @@ -1608,21 +1609,89 @@ out2str(getprompt(NULL)); } +/* used by getprompt */ +#define STR_REALLOC(str,actual,add) \ + if (actual < strlen(str) + add) { \ + str = (char *) realloc(str, actual + add); \ + actual += add; \ + } + /* * called by editline -- any expansions to the prompt * should be added here. */ const char * getprompt(void *unused) - { +{ + const char *unexp; /* Unexpanded path */ + static char *exp = NULL; /* Expanded path */ + static int alloclen = 0; /* Allocated memory in exp */ + unsigned long pos = 0; /* Current position in exp */ + int err; + char hostname[MAXHOSTNAMELEN + 1]; + char *cwd; + + /* Set unexp to the requested prompt if it requires expansion, + * otherwise return its value directly. */ switch (whichprompt) { case 0: return ""; case 1: - return ps1val(); + unexp = ps1val(); + break; case 2: - return ps2val(); + unexp = ps2val(); + break; default: return ""; } + + if (alloclen == 0) { + alloclen = strlen(unexp) + 1; + exp = (char *) malloc(alloclen); + } + *exp = '\0'; + + while (*unexp != '\0') { + err = 0; + + if (*unexp == '\\') { + unexp++; /* Skip backslash */ + switch (*unexp) { + case 'm': /* Short hostname */ + gethostname(hostname, MAXHOSTNAMELEN); + STR_REALLOC(exp, alloclen, strlen(hostname)+1); + strcat(exp, hostname); + pos += strlen(hostname); + break; + case 'w': /* Current working directory */ + cwd = getcwd(NULL, 0); + if (cwd == NULL) { + err = 1; + cwd = ""; + } + STR_REALLOC(exp, alloclen, strlen(cwd)+1); + strcat(exp, cwd); + pos += strlen(cwd); + if (!err) + free(cwd); + break; + case '#': /* # for root, $ for user */ + if (geteuid()) + exp[pos++] = '$'; + else + exp[pos++] = '#'; + break; + default: + exp[pos++] = *unexp; + break; + } + } else + exp[pos++] = *unexp; + + unexp++; + exp[pos] = '\0'; + } + + return exp; } Index: sh.1 =================================================================== RCS file: /cvsroot/src/bin/sh/sh.1,v retrieving revision 1.55 diff -u -u -r1.55 sh.1 --- sh.1 2002/12/28 05:08:27 1.55 +++ sh.1 2003/01/18 10:38:58 @@ -1031,6 +1031,30 @@ patterns used for both Pathname Expansion and the .Ic case command. +.Ss Prompt expansion +Prompt variables, +.Va PS1 +and +.Va PS2 , +are subject to prompt expansion each time they are shown. +The following sequences are recognized, and can appear any number of +times inside prompt variables: +.Bl -tag -width indent +.It \em +Machine's hostname, up to the first dot. +.It \ew +Full path of the current working directory. +.It \e# +A +.Ql $ +sign if the shell is running as a regular user, or a +.Ql # +sign if running as root. +.El +.Pp +Note that backslashes must be quoted with another backslash, like +.Ql \e\e , +in order to avoid parsing of escape sequences. .Ss Shell Patterns A pattern consists of normal characters, which match themselves, and meta-characters.