summaryrefslogtreecommitdiff
path: root/bin/ksh
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2004-11-04 19:20:08 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2004-11-04 19:20:08 +0000
commitc08a5279dcb3dc35f6c5bb33e998c787b299153a (patch)
treec4dcb34e8afa1786375fcf53e67cfb3557c64d28 /bin/ksh
parent10ef9812b94b6ca4ad8539ed42d5bcf4da2f6420 (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.c56
-rw-r--r--bin/ksh/jobs.c24
-rw-r--r--bin/ksh/lex.c268
-rw-r--r--bin/ksh/proto.h3
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));