diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-11-04 19:20:08 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2004-11-04 19:20:08 +0000 |
commit | c08a5279dcb3dc35f6c5bb33e998c787b299153a (patch) | |
tree | c4dcb34e8afa1786375fcf53e67cfb3557c64d28 /bin/ksh | |
parent | 10ef9812b94b6ca4ad8539ed42d5bcf4da2f6420 (diff) |
do the variety-pack of bash-style \letter expansions on prompt variables.
a few issues remain with \ and $ and ! because of early variable expansion
done by incorrect eval/substitution, but this change is not responsible
for that. tested by djm, jmc, and many others
Diffstat (limited to 'bin/ksh')
-rw-r--r-- | bin/ksh/edit.c | 56 | ||||
-rw-r--r-- | bin/ksh/jobs.c | 24 | ||||
-rw-r--r-- | bin/ksh/lex.c | 268 | ||||
-rw-r--r-- | bin/ksh/proto.h | 3 |
4 files changed, 278 insertions, 73 deletions
diff --git a/bin/ksh/edit.c b/bin/ksh/edit.c index 97307266f69..4076ac2bf0a 100644 --- a/bin/ksh/edit.c +++ b/bin/ksh/edit.c @@ -1,4 +1,4 @@ -/* $OpenBSD: edit.c,v 1.18 2003/08/22 18:17:10 fgsch Exp $ */ +/* $OpenBSD: edit.c,v 1.19 2004/11/04 19:20:07 deraadt Exp $ */ /* * Command line editing - common code @@ -19,6 +19,7 @@ #endif /* OS_SCO */ #include <sys/ioctl.h> #include <ctype.h> +#include <libgen.h> #include "ksh_stat.h" @@ -318,59 +319,6 @@ x_mode(onoff) return prev; } -/* NAME: - * promptlen - calculate the length of PS1 etc. - * - * DESCRIPTION: - * This function is based on a fix from guy@demon.co.uk - * It fixes a bug in that if PS1 contains '!', the length - * given by strlen() is probably wrong. - * - * RETURN VALUE: - * length - */ -int -promptlen(cp, spp) - const char *cp; - const char **spp; -{ - int count = 0; - const char *sp = cp; - char delimiter = 0; - int indelimit = 0; - - /* Undocumented AT&T ksh feature: - * If the second char in the prompt string is \r then the first char - * is taken to be a non-printing delimiter and any chars between two - * instances of the delimiter are not considered to be part of the - * prompt length - */ - if (*cp && cp[1] == '\r') { - delimiter = *cp; - cp += 2; - } - - for (; *cp; cp++) { - if (indelimit && *cp != delimiter) - ; - else if (*cp == '\n' || *cp == '\r') { - count = 0; - sp = cp + 1; - } else if (*cp == '\t') { - count = (count | 7) + 1; - } else if (*cp == '\b') { - if (count > 0) - count--; - } else if (*cp == delimiter) - indelimit = !indelimit; - else - count++; - } - if (spp) - *spp = sp; - return count; -} - void set_editmode(ed) const char *ed; diff --git a/bin/ksh/jobs.c b/bin/ksh/jobs.c index f233efd0d26..f87eaf52f8c 100644 --- a/bin/ksh/jobs.c +++ b/bin/ksh/jobs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: jobs.c,v 1.21 2003/11/10 21:26:39 millert Exp $ */ +/* $OpenBSD: jobs.c,v 1.22 2004/11/04 19:20:07 deraadt Exp $ */ /* * Process and job control @@ -177,7 +177,7 @@ static Job *async_job; static pid_t async_pid; static int nzombie; /* # of zombies owned by this process */ -static INT32 njobs; /* # of jobs started */ +INT32 njobs; /* # of jobs started */ static int child_max; /* CHILD_MAX */ @@ -991,6 +991,26 @@ j_stopped_running() return 0; } +int +j_njobs(void) +{ + Job *j; + int nj = 0; +#ifdef JOB_SIGS + sigset_t omask; + + sigprocmask(SIG_BLOCK, &sm_sigchld, &omask); +#endif /* JOB_SIGS */ + for (j = job_list; j; j = j->next) + nj++; + +#ifdef JOB_SIGS + sigprocmask(SIG_SETMASK, &omask, (sigset_t *) 0); +#endif /* JOB_SIGS */ + return nj; +} + + /* list jobs for jobs built-in */ int j_jobs(cp, slp, nflag) diff --git a/bin/ksh/lex.c b/bin/ksh/lex.c index 53e72b5ab25..4fb9ea12cbb 100644 --- a/bin/ksh/lex.c +++ b/bin/ksh/lex.c @@ -1,10 +1,11 @@ -/* $OpenBSD: lex.c,v 1.18 2003/08/06 21:08:05 millert Exp $ */ +/* $OpenBSD: lex.c,v 1.19 2004/11/04 19:20:07 deraadt Exp $ */ /* * lexical analysis and source input */ #include "sh.h" +#include <libgen.h> #include <ctype.h> @@ -1164,27 +1165,240 @@ set_prompt(to, s) } } -/* See also related routine, promptlen() in edit.c */ -void -pprompt(cp, ntruncate) - const char *cp; +static int +dopprompt(sp, ntruncate, spp, doprint) + const char *sp; int ntruncate; + const char **spp; + int doprint; { -#if 0 - char nbuf[32]; - int c; + char strbuf[1024], tmpbuf[1024], *p, *str, nbuf[32], delimiter = '\0'; + int len, c, n, totlen = 0, indelimit = 0; + const char *cp = sp, *ccp; + extern INT32 njobs; + struct tm *tm; + time_t t; + + if (*cp && cp[1] == '\r') { + delimiter = *cp; + cp += 2; + } while (*cp != 0) { - if (*cp != '!') + if (indelimit && *cp != delimiter) + ; + else if (*cp == '\n' || *cp == '\r') { + totlen = 0; + sp = cp + 1; + } else if (*cp == '\t') + totlen = (totlen | 7) + 1; + else if (*cp == delimiter) + indelimit = !indelimit; + + if (*cp == '\\') { + cp++; + if (!*cp) + break; + if (Flag(FSH)) + snprintf(strbuf, sizeof strbuf, "\\%c", *cp); + else switch (*cp) { + case 'a': /* '\' 'a' bell */ + strbuf[0] = '\007'; + strbuf[1] = '\0'; + break; + case 'd': /* '\' 'd' Dow Mon DD */ + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, "%a %b %d", tm); + break; + case 'D': /* '\' 'D' '{' strftime format '}' */ + p = strchr(cp + 2, '}'); + if (cp[1] != '{' || p == NULL) { + snprintf(strbuf, sizeof strbuf, + "\\%c", *cp); + break; + } + strlcpy(tmpbuf, cp + 2, sizeof tmpbuf); + p = strchr(tmpbuf, '}'); + if (p) + *p = '\0'; + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, tmpbuf, tm); + cp = strchr(cp + 2, '}'); + break; + case 'e': /* '\' 'e' escape */ + strbuf[0] = '\033'; + strbuf[1] = '\0'; + break; + case 'h': /* '\' 'h' shortened hostname */ + gethostname(strbuf, sizeof strbuf); + p = strchr(strbuf, '.'); + if (p) + *p = '\0'; + break; + case 'H': /* '\' 'H' full hostname */ + gethostname(strbuf, sizeof strbuf); + break; + case 'j': /* '\' 'j' number of jobs */ + snprintf(strbuf, sizeof strbuf, "%d", + j_njobs()); + break; + case 'l': /* '\' 'l' basename of tty */ + p = ttyname(0); + if (p) + p = basename(p); + if (p) + strlcpy(strbuf, p, sizeof strbuf); + break; + case 'n': /* '\' 'n' newline */ + strbuf[0] = '\n'; + strbuf[1] = '\0'; + break; + case 'r': /* '\' 'r' return */ + strbuf[0] = '\r'; + strbuf[1] = '\0'; + break; + case 's': /* '\' 's' basename $0 */ + strlcpy(strbuf, kshname, sizeof strbuf); + break; + case 't': /* '\' 't' 24 hour HH:MM:SS */ + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, "%T", tm); + break; + case 'T': /* '\' 'T' 12 hour HH:MM:SS */ + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, "%l:%M:%S", tm); + break; + case '@': /* '\' '@' 12 hour am/pm format */ + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, "%r", tm); + break; + case 'A': /* '\' 'A' 24 hour HH:MM */ + time(&t); + tm = localtime(&t); + strftime(strbuf, sizeof strbuf, "%R", tm); + break; + case 'u': /* '\' 'u' username */ + p = getlogin(); + if (p) + strlcpy(strbuf, p, sizeof strbuf); + else + strbuf[0] = '\0'; + break; + case 'v': /* '\' 'v' version (short) */ + p = strchr(ksh_version, ' '); + if (p) + p = strchr(p + 1, ' '); + if (p) { + p++; + strlcpy(strbuf, p, sizeof strbuf); + p = strchr(strbuf, ' '); + if (p) + *p = '\0'; + } + break; + case 'V': /* '\' 'V' version (long) */ + strlcpy(strbuf, ksh_version, sizeof strbuf); + break; + case 'w': /* '\' 'w' cwd */ + p = str_val(global("PWD")); + if (strcmp(p, str_val(global("HOME"))) == 0) { + strbuf[0] = '~'; + strbuf[1] = '\0'; + } else + strlcpy(strbuf, p, sizeof strbuf); + break; + case 'W': /* '\' 'W' basename(cwd) */ + p = str_val(global("PWD")); + strlcpy(strbuf, basename(p), sizeof strbuf); + break; + case '!': /* '\' '!' history line number XXX busted */ + snprintf(strbuf, sizeof strbuf, "%d", + source->line + 1); + break; + case '#': /* '\' '#' command line number XXX busted */ + snprintf(strbuf, sizeof strbuf, "%d", + source->line + 1); + break; + case '$': /* '\' '$' $ or # XXX busted */ + strbuf[0] = ksheuid ? '$' : '#'; + strbuf[1] = '\0'; + break; + case '0': /* '\' '#' '#' ' #' octal numeric handling */ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + if ((cp[1] > '7' || cp[1] < '0') || + (cp[2] > '7' || cp[2] < '0')) { + snprintf(strbuf, sizeof strbuf, + "\\%c", *cp); + break; + } + n = cp[0] * 8 * 8 + cp[1] * 8 + cp[2]; + snprintf(strbuf, sizeof strbuf, "%c", n); + cp += 2; + break; + case '\\': /* '\' '\' */ + strbuf[0] = '\\'; + strbuf[1] = '\0'; + break; + case '[': /* '\' '[' text '\' ']' */ + ccp = ++cp; + while (ccp[0] != '\\' && ccp[1] != ']') { + if (ccp[0] == '\0') + break; + ccp++; + } + if (ccp[0] == '\0') { + snprintf(strbuf, sizeof strbuf, + "\\%c", *cp); + break; + } + n = ccp - cp; + strlcpy(strbuf, cp, sizeof strbuf); + if (n < sizeof strbuf) + strbuf[n] = '\0'; + cp = ccp + 1; + break; + + default: + snprintf(strbuf, sizeof strbuf, "\\%c", *cp); + break; + } + cp++; + + str = strbuf; + len = strlen(str); + if (ntruncate) { + if (ntruncate >= len) { + ntruncate -= len; + continue; + } + str += ntruncate; + len -= ntruncate; + ntruncate = 0; + } + if (doprint) + shf_write(str, len, shl_out); + totlen += len; + continue; + } else if (*cp != '!') c = *cp++; else if (*++cp == '!') c = *cp++; else { - int len; char *p; shf_snprintf(p = nbuf, sizeof(nbuf), "%d", - source->line + 1); + source->line + 1); len = strlen(nbuf); if (ntruncate) { if (ntruncate >= len) { @@ -1195,17 +1409,39 @@ pprompt(cp, ntruncate) len -= ntruncate; ntruncate = 0; } - shf_write(p, len, shl_out); + if (doprint) + shf_write(p, len, shl_out); + totlen += len; continue; } if (ntruncate) --ntruncate; - else + else if (doprint) { shf_putc(c, shl_out); + } + totlen++; } -#endif /* 0 */ - shf_puts(cp + ntruncate, shl_out); - shf_flush(shl_out); + if (doprint) + shf_flush(shl_out); + if (spp) + *spp = sp; + return (totlen); +} + +void +pprompt(cp, ntruncate) + const char *cp; + int ntruncate; +{ + dopprompt(cp, ntruncate, NULL, 1); +} + +int +promptlen(cp, spp) + const char *cp; + const char **spp; +{ + return dopprompt(cp, 0, spp, 0); } /* Read the variable part of a ${...} expression (ie, up to but not including diff --git a/bin/ksh/proto.h b/bin/ksh/proto.h index d0b7e8a4638..cd96b8776d1 100644 --- a/bin/ksh/proto.h +++ b/bin/ksh/proto.h @@ -1,4 +1,4 @@ -/* $OpenBSD: proto.h,v 1.11 2003/05/16 19:58:57 jsyn Exp $ */ +/* $OpenBSD: proto.h,v 1.12 2004/11/04 19:20:07 deraadt Exp $ */ /* * prototypes for PD-KSH @@ -148,6 +148,7 @@ int waitfor ARGS((const char *cp, int *sigp)); int j_kill ARGS((const char *cp, int sig)); int j_resume ARGS((const char *cp, int bg)); int j_jobs ARGS((const char *cp, int slp, int nflag)); +int j_njobs ARGS((void)); void j_notify ARGS((void)); pid_t j_async ARGS((void)); int j_stopped_running ARGS((void)); |