NetBSD Problem Report #16226

Received: (qmail 5200 invoked from network); 7 Apr 2002 14:15:11 -0000
Message-Id: <20020407141609.D181E263A@darkstar.local>
Date: Sun,  7 Apr 2002 16:16:09 +0200 (CEST)
From: slink@unixbsd.org
Reply-To: slink@unixbsd.org
To: gnats-bugs@gnats.netbsd.org
Subject: Prompt expansion for /bin/sh
X-Send-Pr-Version: 3.95

>Number:         16226
>Category:       bin
>Synopsis:       Prompt expansion for /bin/sh
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    kre
>State:          closed
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sun Apr 07 14:16:00 +0000 2002
>Closed-Date:    Fri Apr 13 07:42:32 +0000 2018
>Last-Modified:  Fri Apr 13 07:42:32 +0000 2018
>Originator:     Julio Merino
>Release:        NetBSD 1.5ZC
>Organization:
HispaBSD
>Environment:


System: NetBSD darkstar 1.5ZC NetBSD 1.5ZC (DARKSTAR) #3: Sat Apr 6 17:36:25 CEST 2002 root@darkstar:/home/archive/NetBSD/src/sys/arch/i386/compile/DARKSTAR i386
Architecture: i386
Machine: i386
>Description:
	I've added support to /bin/sh for macro expansion in the prompt.
	It recognizes some simple macros like '%m' or '%w' which are
	expanded to the hostname and working directory. The syntax is
	similar to the one found in the zsh shell.

	The attached patch adds this feature to sh's code and modifies the
	manpage with information about this new functionality.
>How-To-Repeat:

>Fix:
Index: parser.c
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/parser.c,v
retrieving revision 1.52
diff -u -u -r1.52 parser.c
--- parser.c	2002/02/20 21:42:35	1.52
+++ parser.c	2002/04/07 14:06:42
@@ -46,6 +46,9 @@
 #endif /* not lint */

 #include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>

 #include "shell.h"
 #include "parser.h"
@@ -121,6 +124,8 @@
 STATIC void synexpect __P((int)) __attribute__((noreturn));
 STATIC void synerror __P((const char *)) __attribute__((noreturn));
 STATIC void setprompt __P((int));
+STATIC const char *expandprompt __P((const char *));
+STATIC void strappend __P((char **, const char *));


 /*
@@ -1608,6 +1613,74 @@
 }

 /*
+ * Used by expandprompt, this function appends str2 to str1 doing
+ * a realloc of the first string to the total size.
+ */
+STATIC void strappend(char **str1, const char *str2)
+{
+	*str1 = (char*) realloc(*str1, strlen(*str1) + strlen(str2) + 1);
+	strcat(*str1, str2);
+}
+
+/*
+ * Search variables for expansion in the prompt, passed to the str
+ * variable. The prompt with variables expanded is returned by
+ * the function.
+ */
+STATIC const char *
+expandprompt(const char *str)
+{
+	/* Prompt to return */
+	char *ret;
+	/* Some temporary strings to do parsing */
+	char chartostr[2];
+	char hosttostr[MAXHOSTNAMELEN + 1];
+	char *tmp;
+
+	ret = (char*) malloc(1);
+	*ret = '\0';
+	chartostr[1] = '\0';
+
+	while (*str != '\0') {
+		switch (*str) {
+		case '%': /* Option parsing */
+			++str;
+			switch (*str) {
+			case 'w': /* Current working directory */
+				tmp = getcwd(NULL, 0);
+				strappend(&ret, tmp);
+				free(tmp);
+				break;
+			case 'm': /* Hostname, without domain */
+				gethostname(hosttostr, MAXHOSTNAMELEN);
+				strappend(&ret, hosttostr);
+				break;
+			case '#': /* % for user, # for root */
+				if (geteuid())
+					strappend(&ret, "%");
+				else
+					strappend(&ret, "#");
+				break;
+			default: /* Unknown options */
+				goto singlechar;
+				/* NOTREACHED */
+			}
+			break;
+
+		default:
+singlechar:
+			chartostr[0] = *str;
+			strappend(&ret, chartostr);
+			break;
+		}
+		++str;
+	}
+
+	ret[strlen(ret)] = '\0';
+	return ret;
+}
+
+/*
  * called by editline -- any expansions to the prompt
  *    should be added here.
  */
@@ -1618,9 +1691,9 @@
 	case 0:
 		return "";
 	case 1:
-		return ps1val();
+		return expandprompt(ps1val());
 	case 2:
-		return ps2val();
+		return expandprompt(ps2val());
 	default:
 		return "<internal prompt error>";
 	}
Index: sh.1
===================================================================
RCS file: /cvsroot/basesrc/bin/sh/sh.1,v
retrieving revision 1.46
diff -u -u -r1.46 sh.1
--- sh.1	2002/02/24 21:41:52	1.46
+++ sh.1	2002/04/07 14:06:50
@@ -960,6 +960,17 @@
 patterns used for both Pathname Expansion and the
 .Ic case
 command.
+.Ss Prompt Expansion
+Prompt variables are subject to a special expansion. The following macros
+are recognized and are replaced each time the prompt is shown.
+.Bl -tag -width 5n
+.It \fB%%\fP
+A `\fB%\fP'\&.
+.It \fB%w\fP
+Present working directory (\fB$PWD\fP)\&.
+.It \fB%m\fP
+The hostname up to the first `\fB\&.\fP'\&.
+.El
 .Ss Shell Patterns
 A pattern consists of normal characters, which match themselves,
 and meta-characters.   The meta-characters are
>Release-Note:
>Audit-Trail:

From: christos@zoulas.com (Christos Zoulas)
To: slink@unixbsd.org, gnats-admin@netbsd.org,
	gnats-bugs@gnats.netbsd.org
Cc:  
Subject: Re: bin/16226: Prompt expansion for /bin/sh
Date: Sun, 7 Apr 2002 13:54:17 -0400

 On Apr 7,  4:16pm, slink@unixbsd.org (slink@unixbsd.org) wrote:
 -- Subject: bin/16226: Prompt expansion for /bin/sh

 | 	I've added support to /bin/sh for macro expansion in the prompt.
 | 	It recognizes some simple macros like '%m' or '%w' which are
 | 	expanded to the hostname and working directory. The syntax is
 | 	similar to the one found in the zsh shell.
 | 
 | 	The attached patch adds this feature to sh's code and modifies the
 | 	manpage with information about this new functionality.

 This should probably be done in a bash compatible way. With \h meaning
 host instead of %h.

 christos

From: Julio Merino <slink@unixbsd.org>
To: Christos Zoulas <christos@zoulas.com>, gnats-admin@netbsd.org,
	gnats-bugs@gnats.netbsd.org
Cc:  
Subject: Re: bin/16226: Prompt expansion for /bin/sh
Date: Sun, 7 Apr 2002 21:25:10 +0200

 --AhhlLboLdkugWU4S
 Content-Type: text/plain; charset=us-ascii
 Content-Disposition: inline
 Content-Transfer-Encoding: quoted-printable

 On Sun, Apr 07, 2002 at 01:54:17PM -0400, Christos Zoulas wrote:
 > On Apr 7,  4:16pm, slink@unixbsd.org (slink@unixbsd.org) wrote:
 > -- Subject: bin/16226: Prompt expansion for /bin/sh
 >=20
 > This should probably be done in a bash compatible way. With \h meaning
 > host instead of %h.
 >=20
 > christos

 Ok, I've fixed it to follow bash style, as more people has asked me
 to go this way.

 New patch follows (sorry if I shouldn't paste it here):

 [---------- cut here ----------]
 Index: bin/sh/parser.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/basesrc/bin/sh/parser.c,v
 retrieving revision 1.52
 diff -u -u -r1.52 parser.c
 --- parser.c	2002/02/20 21:42:35	1.52
 +++ parser.c	2002/04/07 19:08:17
 @@ -46,6 +46,9 @@
  #endif /* not lint */
 =20
  #include <stdlib.h>
 +#include <string.h>
 +#include <unistd.h>
 +#include <sys/param.h>
 =20
  #include "shell.h"
  #include "parser.h"
 @@ -121,6 +124,8 @@
  STATIC void synexpect __P((int)) __attribute__((noreturn));
  STATIC void synerror __P((const char *)) __attribute__((noreturn));
  STATIC void setprompt __P((int));
 +STATIC const char *expandprompt __P((const char *));
 +STATIC void strappend __P((char **, const char *));
 =20
 =20
  /*
 @@ -1608,6 +1613,75 @@
  }
 =20
  /*
 + * Used by expandprompt, this function appends str2 to str1 doing
 + * a realloc of the first string to the total size.
 + */
 +STATIC void strappend(char **str1, const char *str2)
 +{
 +	*str1 =3D (char*) realloc(*str1, strlen(*str1) + strlen(str2) + 1);
 +	strcat(*str1, str2);
 +}
 +
 +/*
 + * Search variables for expansion in the prompt, passed to the str
 + * variable. The prompt with variables expanded is returned by
 + * the function.
 + */
 +STATIC const char *
 +expandprompt(const char *str)
 +{
 +	/* Prompt to return */
 +	char *ret;
 +	/* Some temporary strings to do parsing */
 +	char chartostr[2];
 +	char hosttostr[MAXHOSTNAMELEN + 1];
 +	char *tmp;
 +
 +	ret =3D (char*) malloc(1);
 +	*ret =3D '\0';
 +	chartostr[1] =3D '\0';
 +
 +	while (*str !=3D '\0') {
 +		switch (*str) {
 +		case '\\': /* Option parsing */
 +			++str;
 +			switch (*str) {
 +			case 'w': /* Current working directory */
 +				tmp =3D getcwd(NULL, 0);
 +				strappend(&ret, tmp);
 +				free(tmp);
 +				break;
 +			case 'h': /* Hostname, without domain */
 +				gethostname(hosttostr, MAXHOSTNAMELEN);
 +				strappend(&ret, hosttostr);
 +				break;
 +			case '$': /* $ for user, # for root */
 +				if (geteuid())
 +					strappend(&ret, "$");
 +				else
 +					strappend(&ret, "#");
 +				break;
 +			case '\\':=09
 +			default: /* Unknown options */
 +				goto singlechar;
 +				/* NOTREACHED */
 +			}
 +			break;
 +
 +		default:
 +singlechar:
 +			chartostr[0] =3D *str;
 +			strappend(&ret, chartostr);
 +			break;
 +		}
 +		++str;
 +	}
 +
 +	ret[strlen(ret)] =3D '\0';
 +	return ret;
 +}
 +
 +/*
   * called by editline -- any expansions to the prompt
   *    should be added here.
   */
 @@ -1618,9 +1692,9 @@
  	case 0:
  		return "";
  	case 1:
 -		return ps1val();
 +		return expandprompt(ps1val());
  	case 2:
 -		return ps2val();
 +		return expandprompt(ps2val());
  	default:
  		return "<internal prompt error>";
  	}
 Index: bin/sh/sh.1
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/basesrc/bin/sh/sh.1,v
 retrieving revision 1.46
 diff -u -u -r1.46 sh.1
 --- sh.1	2002/02/24 21:41:52	1.46
 +++ sh.1	2002/04/07 19:08:32
 @@ -960,6 +960,21 @@
  patterns used for both Pathname Expansion and the
  .Ic case
  command.
 +.Ss Prompt Expansion
 +Prompt variables are subject to a special expansion. The following macros
 +are recognized and are replaced each time the prompt is shown.
 +.Bl -tag -width 5n
 +.It \fB\e\e\fP
 +A `\fB\e\fP'\&.
 +.It \fB\eh\fP
 +The hostname up to the first `\fB\&.\fP'\&.
 +.It \fB\ew\fP
 +The current working directory (\fB$PWD\fP)\&.
 +.El
 +.Pp
 +Note that the backslash must always be quoted to be effective. If you do
 +not do it, the shell will try to parse it before interpreting these macros
 +and therefore prompt expansion will not work.
  .Ss Shell Patterns
  A pattern consists of normal characters, which match themselves,
  and meta-characters.   The meta-characters are
 [---------- cut here ----------]

 --=20
 Of course it runs NetBSD - http://www.netbsd.org
 Julio Merino <slink@unixbsd.org> #18961975

 --AhhlLboLdkugWU4S
 Content-Type: application/pgp-signature
 Content-Disposition: inline

 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.0.6 (NetBSD)
 Comment: For info see http://www.gnupg.org

 iD8DBQE8sJ0Wzz00ZOPKycwRAj2fAJ4mKXXHyQ8p8GhGBH6fqbf/GcDAzgCfXwPY
 hYfrz5iNPChYs1FpGGQaoGs=
 =QO9n
 -----END PGP SIGNATURE-----

 --AhhlLboLdkugWU4S--

From: woods@weird.com (Greg A. Woods)
To: slink@unixbsd.org
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: bin/16226: Prompt expansion for /bin/sh
Date: Sun,  7 Apr 2002 15:25:34 -0400 (EDT)

 [ On Sunday, April 7, 2002 at 16:16:09 (+0200), slink@unixbsd.org wrote: ]
 > Subject: bin/16226: Prompt expansion for /bin/sh
 >
 > 
 > +			case '#': /* % for user, # for root */
 > +				if (geteuid())
 > +					strappend(&ret, "%");
 > +				else
 > +					strappend(&ret, "#");

 I would think anyone using '%' for a prompt in a Bourne/POSIX shell is
 pretty disillusioned.....  :-)



 -- 
 								Greg A. Woods

 +1 416 218-0098;  <gwoods@acm.org>;  <g.a.woods@ieee.org>;  <woods@robohack.ca>
 Planix, Inc. <woods@planix.com>; VE3TCP; Secrets of the Weird <woods@weird.com>

From: Julio Merino <slink@unixbsd.org>
To: gnats-bugs@netbsd.org
Cc:  
Subject: Re: bin/16226
Date: Sun, 7 Apr 2002 22:05:00 +0200

 I've modified the patch to be more bash'ish. It now works with
 \* options and when using \$ it shows '$' for a user instead of
 a '%' as I did.

 Patch follows (sorry if I should have not pasted it again).

 [---------- cut here ----------]
 Index: bin/sh/parser.c
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/basesrc/bin/sh/parser.c,v
 retrieving revision 1.52
 diff -u -u -r1.52 parser.c
 --- parser.c	2002/02/20 21:42:35	1.52
 +++ parser.c	2002/04/07 19:08:17
 @@ -46,6 +46,9 @@
  #endif /* not lint */
 =20
  #include <stdlib.h>
 +#include <string.h>
 +#include <unistd.h>
 +#include <sys/param.h>
 =20
  #include "shell.h"
  #include "parser.h"
 @@ -121,6 +124,8 @@
  STATIC void synexpect __P((int)) __attribute__((noreturn));
  STATIC void synerror __P((const char *)) __attribute__((noreturn));
  STATIC void setprompt __P((int));
 +STATIC const char *expandprompt __P((const char *));
 +STATIC void strappend __P((char **, const char *));
 =20
 =20
  /*
 @@ -1608,6 +1613,75 @@
  }
 =20
  /*
 + * Used by expandprompt, this function appends str2 to str1 doing
 + * a realloc of the first string to the total size.
 + */
 +STATIC void strappend(char **str1, const char *str2)
 +{
 +	*str1 =3D (char*) realloc(*str1, strlen(*str1) + strlen(str2) + 1);
 +	strcat(*str1, str2);
 +}
 +
 +/*
 + * Search variables for expansion in the prompt, passed to the str
 + * variable. The prompt with variables expanded is returned by
 + * the function.
 + */
 +STATIC const char *
 +expandprompt(const char *str)
 +{
 +	/* Prompt to return */
 +	char *ret;
 +	/* Some temporary strings to do parsing */
 +	char chartostr[2];
 +	char hosttostr[MAXHOSTNAMELEN + 1];
 +	char *tmp;
 +
 +	ret =3D (char*) malloc(1);
 +	*ret =3D '\0';
 +	chartostr[1] =3D '\0';
 +
 +	while (*str !=3D '\0') {
 +		switch (*str) {
 +		case '\\': /* Option parsing */
 +			++str;
 +			switch (*str) {
 +			case 'w': /* Current working directory */
 +				tmp =3D getcwd(NULL, 0);
 +				strappend(&ret, tmp);
 +				free(tmp);
 +				break;
 +			case 'h': /* Hostname, without domain */
 +				gethostname(hosttostr, MAXHOSTNAMELEN);
 +				strappend(&ret, hosttostr);
 +				break;
 +			case '$': /* $ for user, # for root */
 +				if (geteuid())
 +					strappend(&ret, "$");
 +				else
 +					strappend(&ret, "#");
 +				break;
 +			case '\\':=09
 +			default: /* Unknown options */
 +				goto singlechar;
 +				/* NOTREACHED */
 +			}
 +			break;
 +
 +		default:
 +singlechar:
 +			chartostr[0] =3D *str;
 +			strappend(&ret, chartostr);
 +			break;
 +		}
 +		++str;
 +	}
 +
 +	ret[strlen(ret)] =3D '\0';
 +	return ret;
 +}
 +
 +/*
   * called by editline -- any expansions to the prompt
   *    should be added here.
   */
 @@ -1618,9 +1692,9 @@
  	case 0:
  		return "";
  	case 1:
 -		return ps1val();
 +		return expandprompt(ps1val());
  	case 2:
 -		return ps2val();
 +		return expandprompt(ps2val());
  	default:
  		return "<internal prompt error>";
  	}
 Index: bin/sh/sh.1
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 RCS file: /cvsroot/basesrc/bin/sh/sh.1,v
 retrieving revision 1.46
 diff -u -u -r1.46 sh.1
 --- sh.1	2002/02/24 21:41:52	1.46
 +++ sh.1	2002/04/07 19:08:32
 @@ -960,6 +960,21 @@
  patterns used for both Pathname Expansion and the
  .Ic case
  command.
 +.Ss Prompt Expansion
 +Prompt variables are subject to a special expansion. The following macros
 +are recognized and are replaced each time the prompt is shown.
 +.Bl -tag -width 5n
 +.It \fB\e\e\fP
 +A `\fB\e\fP'\&.
 +.It \fB\eh\fP
 +The hostname up to the first `\fB\&.\fP'\&.
 +.It \fB\ew\fP
 +The current working directory (\fB$PWD\fP)\&.
 +.El
 +.Pp
 +Note that the backslash must always be quoted to be effective. If you do
 +not do it, the shell will try to parse it before interpreting these macros
 +and therefore prompt expansion will not work.
  .Ss Shell Patterns
  A pattern consists of normal characters, which match themselves,
  and meta-characters.   The meta-characters are
 [---------- cut here ----------]

 --=20
 Of course it runs NetBSD - http://www.netbsd.org
 Julio Merino <slink@unixbsd.org> #18961975
State-Changed-From-To: open->suspended 
State-Changed-By: jmmv 
State-Changed-When: Mon Jan 13 02:29:52 PST 2003 
State-Changed-Why:  
The patch I submitted has some problems. I want to rewrite and improve it 
before it gets commited. 

From: Julio Merino <jmmv@menta.net>
To: tech-userlevel@netbsd.org
Cc: gnats-bugs@gnats.netbsd.org
Subject: Re: pkg/16226 (new patch for review)
Date: Sat, 18 Jan 2003 11:51:46 +0100

 Hello,

 here is a new patch to do the prompt expansion thing I submitted some time
 ago. It seems better to me (now memory is only allocated once, and realloc's
 are avoided when possible).

 The problem I see in it is that the memory allocated for the exp string is
 never free'd. Were could it be done? At sh's exit?

 Anyway here is the patch, what do you think?

 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 <stdlib.h>
 +#include <unistd.h>

  #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 "<internal prompt error>";
  	}
 +
 +	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 = "<cwd disappeared>";
 +				}
 +				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.


 Thanks

 -- 
 Julio M. Merino Vidal <jmmv@menta.net>
 The NetBSD Project - http://www.NetBSD.org/
State-Changed-From-To: suspended->open 
State-Changed-By: jmmv 
State-Changed-When: Sat Jan 18 02:50:32 PST 2003 
State-Changed-Why:  
New patch sent, should be reviewed now. 

From: David Laight <david@l8s.co.uk>
To: Julio Merino <jmmv@menta.net>
Cc: tech-userlevel@netbsd.org, gnats-bugs@gnats.netbsd.org
Subject: Re: pkg/16226 (new patch for review)
Date: Sat, 18 Jan 2003 20:09:02 +0000

 On Sat, Jan 18, 2003 at 11:51:46AM +0100, Julio Merino wrote:
 > Hello,
 > 
 > here is a new patch to do the prompt expansion thing I submitted some time
 > ago. It seems better to me (now memory is only allocated once, and realloc's
 > are avoided when possible).

 What you should have done it to read the posix spec, see that the
 shell should do parameter expansion on its prompt and raise a bug
 saying that it didn't, and so wasn't posix conformant :-)

 After:
 $ PS1='$PWD ! $ '
 /oldroot/usr/bsd-current/obj/bin/sh 3 $
 etc...

 /bin/sh is much more likely to move in the direction of ksh that
 bash since the posix spec mainly contains ksh features on top of
 the AT&T bourne shell.

 	David

 -- 
 David Laight: david@l8s.co.uk
Responsible-Changed-From-To: bin-bug-people->kre
Responsible-Changed-By: kre@NetBSD.org
Responsible-Changed-When: Thu, 25 May 2017 08:06:28 +0000
Responsible-Changed-Why:
I have an almost working prompt expansion (parameter expansion,
plus arithmetic, and (if enabled by an option) command substitution)
which is both what the standard expects, and more flexible than a
few fixed \X characters being expanded...

"almost working" means that it works, 99.9% of the time, but I have
one very rare error mode case (when something goes wrong with the
expansion, and the user needs to ^C to get control back) that sometimes
drives the shell totally insane (though even this usually works fine.)

Once I find what is happening with that one (hard, because it is so
rare, and so far I have not been able to deliberately provoke it into
happening), the suggestion in this PR can be considered obsolete I
think.

I am not planning (as in would actively resist) any attempt to add the
(current) posix specified (or semi-specified) magic ! handling for
PS1 however - if we really need access to history related values,
they should be exported in the form of regular sh variables,
which parameter expansion can then access.  That's clean and
consistent, and well defined, unlike the ! hack.


State-Changed-From-To: open->feedback
State-Changed-By: kre@NetBSD.org
State-Changed-When: Sat, 01 Jul 2017 00:05:27 +0000
State-Changed-Why:
It has been a mere 15 years (and a few months), but /bin/sh (in NetBSD current)
now has PS1 (and PS2, PS4) variable expansion (and a few ner variables to
assist with building prompts).

To get the hostname, use ${HOSTNAME} (for whatever gethostname(3) returns)
or ${HOSTNAME%%.*} for the short form.

For the current directory use ${PWD}, or ${PWD##*/} for only the last
component.   For smarter expansions, wrap a function around the cd
command, something like

	cd()
	{
		command cd "$@" || return

		PDIR=${PWD}
		case "${PDIR}/" in
		"${HOME}/")	PDIR='~'"${PDIR#${HOME}}" ;;
		esac

		# and any other modifications you want
	}

and then use $PDIR (any name you like) in PS1 (or elsewhere).

For the $/# expansion, use $PSc

Set PS1 with a '' string to avoid expanding the values at definition time.

See sh(1) (from NetBSD current, and maybe NetBSD 8 before it gets released)
for more information on what can be done.

Hopefully this is enough to satisfy the request in this PR.


State-Changed-From-To: feedback->closed
State-Changed-By: kre@NetBSD.org
State-Changed-When: Fri, 13 Apr 2018 07:42:32 +0000
State-Changed-Why:
feedback timeout and problem believed fixed


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.43 2018/01/16 07:36:43 maya Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2017 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.