1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien * tc.prompt.c: Prompt printing stuff
3c80476e4SDavid E. O'Brien */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien * All rights reserved.
7c80476e4SDavid E. O'Brien *
8c80476e4SDavid E. O'Brien * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien * are met:
11c80476e4SDavid E. O'Brien * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien * notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien * documentation and/or other materials provided with the distribution.
1629301572SMark Peek * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien * may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien * without specific prior written permission.
19c80476e4SDavid E. O'Brien *
20c80476e4SDavid E. O'Brien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien #include "tw.h"
35c80476e4SDavid E. O'Brien
36c80476e4SDavid E. O'Brien /*
37c80476e4SDavid E. O'Brien * kfk 21oct1983 -- add @ (time) and / ($cwd) in prompt.
38c80476e4SDavid E. O'Brien * PWP 4/27/87 -- rearange for tcsh.
39c80476e4SDavid E. O'Brien * mrdch@com.tau.edu.il 6/26/89 - added ~, T and .# - rearanged to switch()
40c80476e4SDavid E. O'Brien * instead of if/elseif
41c80476e4SDavid E. O'Brien * Luke Mewburn, <lukem@cs.rmit.edu.au>
42c80476e4SDavid E. O'Brien * 6-Sep-91 changed date format
43c80476e4SDavid E. O'Brien * 16-Feb-94 rewrote directory prompt code, added $ellipsis
44c80476e4SDavid E. O'Brien * 29-Dec-96 added rprompt support
45c80476e4SDavid E. O'Brien */
46c80476e4SDavid E. O'Brien
4723338178SMark Peek static const char *month_list[12];
4823338178SMark Peek static const char *day_list[7];
49c80476e4SDavid E. O'Brien
50c80476e4SDavid E. O'Brien void
dateinit(void)5145e5710bSMark Peek dateinit(void)
52c80476e4SDavid E. O'Brien {
53c80476e4SDavid E. O'Brien #ifdef notyet
54c80476e4SDavid E. O'Brien int i;
55c80476e4SDavid E. O'Brien
56c80476e4SDavid E. O'Brien setlocale(LC_TIME, "");
57c80476e4SDavid E. O'Brien
58c80476e4SDavid E. O'Brien for (i = 0; i < 12; i++)
59c80476e4SDavid E. O'Brien xfree((ptr_t) month_list[i]);
60c80476e4SDavid E. O'Brien month_list[0] = strsave(_time_info->abbrev_month[0]);
61c80476e4SDavid E. O'Brien month_list[1] = strsave(_time_info->abbrev_month[1]);
62c80476e4SDavid E. O'Brien month_list[2] = strsave(_time_info->abbrev_month[2]);
63c80476e4SDavid E. O'Brien month_list[3] = strsave(_time_info->abbrev_month[3]);
64c80476e4SDavid E. O'Brien month_list[4] = strsave(_time_info->abbrev_month[4]);
65c80476e4SDavid E. O'Brien month_list[5] = strsave(_time_info->abbrev_month[5]);
66c80476e4SDavid E. O'Brien month_list[6] = strsave(_time_info->abbrev_month[6]);
67c80476e4SDavid E. O'Brien month_list[7] = strsave(_time_info->abbrev_month[7]);
68c80476e4SDavid E. O'Brien month_list[8] = strsave(_time_info->abbrev_month[8]);
69c80476e4SDavid E. O'Brien month_list[9] = strsave(_time_info->abbrev_month[9]);
70c80476e4SDavid E. O'Brien month_list[10] = strsave(_time_info->abbrev_month[10]);
71c80476e4SDavid E. O'Brien month_list[11] = strsave(_time_info->abbrev_month[11]);
72c80476e4SDavid E. O'Brien
73c80476e4SDavid E. O'Brien for (i = 0; i < 7; i++)
74c80476e4SDavid E. O'Brien xfree((ptr_t) day_list[i]);
75c80476e4SDavid E. O'Brien day_list[0] = strsave(_time_info->abbrev_wkday[0]);
76c80476e4SDavid E. O'Brien day_list[1] = strsave(_time_info->abbrev_wkday[1]);
77c80476e4SDavid E. O'Brien day_list[2] = strsave(_time_info->abbrev_wkday[2]);
78c80476e4SDavid E. O'Brien day_list[3] = strsave(_time_info->abbrev_wkday[3]);
79c80476e4SDavid E. O'Brien day_list[4] = strsave(_time_info->abbrev_wkday[4]);
80c80476e4SDavid E. O'Brien day_list[5] = strsave(_time_info->abbrev_wkday[5]);
81c80476e4SDavid E. O'Brien day_list[6] = strsave(_time_info->abbrev_wkday[6]);
82c80476e4SDavid E. O'Brien #else
83c80476e4SDavid E. O'Brien month_list[0] = "Jan";
84c80476e4SDavid E. O'Brien month_list[1] = "Feb";
85c80476e4SDavid E. O'Brien month_list[2] = "Mar";
86c80476e4SDavid E. O'Brien month_list[3] = "Apr";
87c80476e4SDavid E. O'Brien month_list[4] = "May";
88c80476e4SDavid E. O'Brien month_list[5] = "Jun";
89c80476e4SDavid E. O'Brien month_list[6] = "Jul";
90c80476e4SDavid E. O'Brien month_list[7] = "Aug";
91c80476e4SDavid E. O'Brien month_list[8] = "Sep";
92c80476e4SDavid E. O'Brien month_list[9] = "Oct";
93c80476e4SDavid E. O'Brien month_list[10] = "Nov";
94c80476e4SDavid E. O'Brien month_list[11] = "Dec";
95c80476e4SDavid E. O'Brien
96c80476e4SDavid E. O'Brien day_list[0] = "Sun";
97c80476e4SDavid E. O'Brien day_list[1] = "Mon";
98c80476e4SDavid E. O'Brien day_list[2] = "Tue";
99c80476e4SDavid E. O'Brien day_list[3] = "Wed";
100c80476e4SDavid E. O'Brien day_list[4] = "Thu";
101c80476e4SDavid E. O'Brien day_list[5] = "Fri";
102c80476e4SDavid E. O'Brien day_list[6] = "Sat";
103c80476e4SDavid E. O'Brien #endif
104c80476e4SDavid E. O'Brien }
105c80476e4SDavid E. O'Brien
106c80476e4SDavid E. O'Brien void
printprompt(int promptno,const char * str)10745e5710bSMark Peek printprompt(int promptno, const char *str)
108c80476e4SDavid E. O'Brien {
10945e5710bSMark Peek static const Char *ocp = NULL;
11023338178SMark Peek static const char *ostr = NULL;
111c80476e4SDavid E. O'Brien time_t lclock = time(NULL);
11245e5710bSMark Peek const Char *cp;
113c80476e4SDavid E. O'Brien
114c80476e4SDavid E. O'Brien switch (promptno) {
115c80476e4SDavid E. O'Brien default:
116c80476e4SDavid E. O'Brien case 0:
117c80476e4SDavid E. O'Brien cp = varval(STRprompt);
118c80476e4SDavid E. O'Brien break;
119c80476e4SDavid E. O'Brien case 1:
120c80476e4SDavid E. O'Brien cp = varval(STRprompt2);
121c80476e4SDavid E. O'Brien break;
122c80476e4SDavid E. O'Brien case 2:
123c80476e4SDavid E. O'Brien cp = varval(STRprompt3);
124c80476e4SDavid E. O'Brien break;
125c80476e4SDavid E. O'Brien case 3:
126c80476e4SDavid E. O'Brien if (ocp != NULL) {
127c80476e4SDavid E. O'Brien cp = ocp;
128c80476e4SDavid E. O'Brien str = ostr;
129c80476e4SDavid E. O'Brien }
130c80476e4SDavid E. O'Brien else
131c80476e4SDavid E. O'Brien cp = varval(STRprompt);
132c80476e4SDavid E. O'Brien break;
133c80476e4SDavid E. O'Brien }
134c80476e4SDavid E. O'Brien
135c80476e4SDavid E. O'Brien if (promptno < 2) {
136c80476e4SDavid E. O'Brien ocp = cp;
137c80476e4SDavid E. O'Brien ostr = str;
138c80476e4SDavid E. O'Brien }
139c80476e4SDavid E. O'Brien
14045e5710bSMark Peek xfree(Prompt);
14145e5710bSMark Peek Prompt = NULL;
14245e5710bSMark Peek Prompt = tprintf(FMT_PROMPT, cp, str, lclock, NULL);
143c80476e4SDavid E. O'Brien if (!editing) {
14445e5710bSMark Peek for (cp = Prompt; *cp ; )
14523338178SMark Peek (void) putwraw(*cp++);
146c80476e4SDavid E. O'Brien SetAttributes(0);
147c80476e4SDavid E. O'Brien flush();
148c80476e4SDavid E. O'Brien }
149c80476e4SDavid E. O'Brien
15045e5710bSMark Peek xfree(RPrompt);
15145e5710bSMark Peek RPrompt = NULL;
152c80476e4SDavid E. O'Brien if (promptno == 0) { /* determine rprompt if using main prompt */
153c80476e4SDavid E. O'Brien cp = varval(STRrprompt);
15445e5710bSMark Peek RPrompt = tprintf(FMT_PROMPT, cp, NULL, lclock, NULL);
155c80476e4SDavid E. O'Brien /* if not editing, put rprompt after prompt */
15645e5710bSMark Peek if (!editing && RPrompt[0] != '\0') {
15745e5710bSMark Peek for (cp = RPrompt; *cp ; )
15823338178SMark Peek (void) putwraw(*cp++);
159c80476e4SDavid E. O'Brien SetAttributes(0);
160c80476e4SDavid E. O'Brien putraw(' ');
161c80476e4SDavid E. O'Brien flush();
162c80476e4SDavid E. O'Brien }
163c80476e4SDavid E. O'Brien }
164c80476e4SDavid E. O'Brien }
165c80476e4SDavid E. O'Brien
16645e5710bSMark Peek static void
tprintf_append_mbs(struct Strbuf * buf,const char * mbs,Char attributes)16745e5710bSMark Peek tprintf_append_mbs(struct Strbuf *buf, const char *mbs, Char attributes)
168c80476e4SDavid E. O'Brien {
16945e5710bSMark Peek while (*mbs != 0) {
17045e5710bSMark Peek Char wc;
17145e5710bSMark Peek
17245e5710bSMark Peek mbs += one_mbtowc(&wc, mbs, MB_LEN_MAX);
17345e5710bSMark Peek Strbuf_append1(buf, wc | attributes);
17445e5710bSMark Peek }
17545e5710bSMark Peek }
17645e5710bSMark Peek
17745e5710bSMark Peek Char *
tprintf(int what,const Char * fmt,const char * str,time_t tim,ptr_t info)17845e5710bSMark Peek tprintf(int what, const Char *fmt, const char *str, time_t tim, ptr_t info)
17945e5710bSMark Peek {
18045e5710bSMark Peek struct Strbuf buf = Strbuf_INIT;
181c80476e4SDavid E. O'Brien Char *z, *q;
182c80476e4SDavid E. O'Brien Char attributes = 0;
183c80476e4SDavid E. O'Brien static int print_prompt_did_ding = 0;
18445e5710bSMark Peek char *cz;
185c80476e4SDavid E. O'Brien
18645e5710bSMark Peek Char *p;
187c80476e4SDavid E. O'Brien const Char *cp = fmt;
188c80476e4SDavid E. O'Brien Char Scp;
189c80476e4SDavid E. O'Brien struct tm *t = localtime(&tim);
190c80476e4SDavid E. O'Brien
191c80476e4SDavid E. O'Brien /* prompt stuff */
19245e5710bSMark Peek static Char *olduser = NULL;
19329301572SMark Peek int updirs;
19445e5710bSMark Peek size_t pdirs;
195c80476e4SDavid E. O'Brien
19645e5710bSMark Peek cleanup_push(&buf, Strbuf_cleanup);
197c80476e4SDavid E. O'Brien for (; *cp; cp++) {
198c80476e4SDavid E. O'Brien if ((*cp == '%') && ! (cp[1] == '\0')) {
199c80476e4SDavid E. O'Brien cp++;
200c80476e4SDavid E. O'Brien switch (*cp) {
201c80476e4SDavid E. O'Brien case 'R':
20223338178SMark Peek if (what == FMT_HISTORY) {
20345e5710bSMark Peek cz = fmthist('R', info);
20445e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
20545e5710bSMark Peek xfree(cz);
20645e5710bSMark Peek } else {
20745e5710bSMark Peek if (str != NULL)
20845e5710bSMark Peek tprintf_append_mbs(&buf, str, attributes);
20923338178SMark Peek }
210c80476e4SDavid E. O'Brien break;
211c80476e4SDavid E. O'Brien case '#':
212*19d2e3deSDmitry Chagin #ifdef __CYGWIN__
213*19d2e3deSDmitry Chagin /* Check for being member of the Administrators group */
214*19d2e3deSDmitry Chagin {
215*19d2e3deSDmitry Chagin gid_t grps[NGROUPS_MAX];
216*19d2e3deSDmitry Chagin int grp, gcnt;
217*19d2e3deSDmitry Chagin
218*19d2e3deSDmitry Chagin gcnt = getgroups(NGROUPS_MAX, grps);
219*19d2e3deSDmitry Chagin # define DOMAIN_GROUP_RID_ADMINS 544
220*19d2e3deSDmitry Chagin for (grp = 0; grp < gcnt; ++grp)
221*19d2e3deSDmitry Chagin if (grps[grp] == DOMAIN_GROUP_RID_ADMINS)
222*19d2e3deSDmitry Chagin break;
223*19d2e3deSDmitry Chagin Scp = (grp < gcnt) ? PRCHROOT : PRCH;
224*19d2e3deSDmitry Chagin }
225*19d2e3deSDmitry Chagin #else
2269ccc37e3SMark Peek Scp = (uid == 0 || euid == 0) ? PRCHROOT : PRCH;
227*19d2e3deSDmitry Chagin #endif
2289ccc37e3SMark Peek if (Scp != '\0')
2299ccc37e3SMark Peek Strbuf_append1(&buf, attributes | Scp);
230c80476e4SDavid E. O'Brien break;
231c80476e4SDavid E. O'Brien case '!':
232c80476e4SDavid E. O'Brien case 'h':
233c80476e4SDavid E. O'Brien switch (what) {
234c80476e4SDavid E. O'Brien case FMT_HISTORY:
23545e5710bSMark Peek cz = fmthist('h', info);
236c80476e4SDavid E. O'Brien break;
237c80476e4SDavid E. O'Brien case FMT_SCHED:
23845e5710bSMark Peek cz = xasprintf("%d", *(int *)info);
239c80476e4SDavid E. O'Brien break;
240c80476e4SDavid E. O'Brien default:
24145e5710bSMark Peek cz = xasprintf("%d", eventno + 1);
242c80476e4SDavid E. O'Brien break;
243c80476e4SDavid E. O'Brien }
24445e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
24545e5710bSMark Peek xfree(cz);
246c80476e4SDavid E. O'Brien break;
247c80476e4SDavid E. O'Brien case 'T': /* 24 hour format */
248c80476e4SDavid E. O'Brien case '@':
249c80476e4SDavid E. O'Brien case 't': /* 12 hour am/pm format */
250c80476e4SDavid E. O'Brien case 'p': /* With seconds */
251c80476e4SDavid E. O'Brien case 'P':
252c80476e4SDavid E. O'Brien {
253c80476e4SDavid E. O'Brien char ampm = 'a';
254c80476e4SDavid E. O'Brien int hr = t->tm_hour;
255c80476e4SDavid E. O'Brien
256c80476e4SDavid E. O'Brien /* addition by Hans J. Albertsson */
257c80476e4SDavid E. O'Brien /* and another adapted from Justin Bur */
258c80476e4SDavid E. O'Brien if (adrof(STRampm) || (*cp != 'T' && *cp != 'P')) {
259c80476e4SDavid E. O'Brien if (hr >= 12) {
260c80476e4SDavid E. O'Brien if (hr > 12)
261c80476e4SDavid E. O'Brien hr -= 12;
262c80476e4SDavid E. O'Brien ampm = 'p';
263c80476e4SDavid E. O'Brien }
264c80476e4SDavid E. O'Brien else if (hr == 0)
265c80476e4SDavid E. O'Brien hr = 12;
266c80476e4SDavid E. O'Brien } /* else do a 24 hour clock */
267c80476e4SDavid E. O'Brien
268c80476e4SDavid E. O'Brien /* "DING!" stuff by Hans also */
269c80476e4SDavid E. O'Brien if (t->tm_min || print_prompt_did_ding ||
270c80476e4SDavid E. O'Brien what != FMT_PROMPT || adrof(STRnoding)) {
271c80476e4SDavid E. O'Brien if (t->tm_min)
272c80476e4SDavid E. O'Brien print_prompt_did_ding = 0;
27345e5710bSMark Peek /*
27445e5710bSMark Peek * Pad hour to 2 characters if padhour is set,
27545e5710bSMark Peek * by ADAM David Alan Martin
27645e5710bSMark Peek */
27745e5710bSMark Peek p = Itoa(hr, adrof(STRpadhour) ? 2 : 0, attributes);
27845e5710bSMark Peek Strbuf_append(&buf, p);
27945e5710bSMark Peek xfree(p);
28045e5710bSMark Peek Strbuf_append1(&buf, attributes | ':');
28145e5710bSMark Peek p = Itoa(t->tm_min, 2, attributes);
28245e5710bSMark Peek Strbuf_append(&buf, p);
28345e5710bSMark Peek xfree(p);
284c80476e4SDavid E. O'Brien if (*cp == 'p' || *cp == 'P') {
28545e5710bSMark Peek Strbuf_append1(&buf, attributes | ':');
28645e5710bSMark Peek p = Itoa(t->tm_sec, 2, attributes);
28745e5710bSMark Peek Strbuf_append(&buf, p);
28845e5710bSMark Peek xfree(p);
289c80476e4SDavid E. O'Brien }
290c80476e4SDavid E. O'Brien if (adrof(STRampm) || (*cp != 'T' && *cp != 'P')) {
29145e5710bSMark Peek Strbuf_append1(&buf, attributes | ampm);
29245e5710bSMark Peek Strbuf_append1(&buf, attributes | 'm');
293c80476e4SDavid E. O'Brien }
294c80476e4SDavid E. O'Brien }
295c80476e4SDavid E. O'Brien else { /* we need to ding */
29645e5710bSMark Peek size_t i;
297c80476e4SDavid E. O'Brien
29845e5710bSMark Peek for (i = 0; STRDING[i] != 0; i++)
29945e5710bSMark Peek Strbuf_append1(&buf, attributes | STRDING[i]);
300c80476e4SDavid E. O'Brien print_prompt_did_ding = 1;
301c80476e4SDavid E. O'Brien }
302c80476e4SDavid E. O'Brien }
303c80476e4SDavid E. O'Brien break;
304c80476e4SDavid E. O'Brien
305c80476e4SDavid E. O'Brien case 'M':
306c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
307c80476e4SDavid E. O'Brien if (what == FMT_WHO)
30845e5710bSMark Peek cz = who_info(info, 'M');
309c80476e4SDavid E. O'Brien else
310c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
31145e5710bSMark Peek cz = getenv("HOST");
312c80476e4SDavid E. O'Brien /*
313c80476e4SDavid E. O'Brien * Bug pointed out by Laurent Dami <dami@cui.unige.ch>: don't
314c80476e4SDavid E. O'Brien * derefrence that NULL (if HOST is not set)...
315c80476e4SDavid E. O'Brien */
316c80476e4SDavid E. O'Brien if (cz != NULL)
31745e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
31845e5710bSMark Peek if (what == FMT_WHO)
31945e5710bSMark Peek xfree(cz);
320c80476e4SDavid E. O'Brien break;
321c80476e4SDavid E. O'Brien
32245e5710bSMark Peek case 'm': {
32345e5710bSMark Peek char *scz = NULL;
324c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
325c80476e4SDavid E. O'Brien if (what == FMT_WHO)
32645e5710bSMark Peek scz = cz = who_info(info, 'm');
327c80476e4SDavid E. O'Brien else
328c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
32945e5710bSMark Peek cz = getenv("HOST");
330c80476e4SDavid E. O'Brien
331c80476e4SDavid E. O'Brien if (cz != NULL)
33245e5710bSMark Peek while (*cz != 0 && (what == FMT_WHO || *cz != '.')) {
33345e5710bSMark Peek Char wc;
33445e5710bSMark Peek
33545e5710bSMark Peek cz += one_mbtowc(&wc, cz, MB_LEN_MAX);
33645e5710bSMark Peek Strbuf_append1(&buf, wc | attributes);
33723338178SMark Peek }
33845e5710bSMark Peek if (scz)
33945e5710bSMark Peek xfree(scz);
340c80476e4SDavid E. O'Brien break;
34145e5710bSMark Peek }
342c80476e4SDavid E. O'Brien
343c80476e4SDavid E. O'Brien /* lukem: new directory prompt code */
344c80476e4SDavid E. O'Brien case '~':
345c80476e4SDavid E. O'Brien case '/':
346c80476e4SDavid E. O'Brien case '.':
347c80476e4SDavid E. O'Brien case 'c':
348c80476e4SDavid E. O'Brien case 'C':
349c80476e4SDavid E. O'Brien Scp = *cp;
350c80476e4SDavid E. O'Brien if (Scp == 'c') /* store format type (c == .) */
351c80476e4SDavid E. O'Brien Scp = '.';
352c80476e4SDavid E. O'Brien if ((z = varval(STRcwd)) == STRNULL)
353c80476e4SDavid E. O'Brien break; /* no cwd, so don't do anything */
354c80476e4SDavid E. O'Brien
355c80476e4SDavid E. O'Brien /* show ~ whenever possible - a la dirs */
356c80476e4SDavid E. O'Brien if (Scp == '~' || Scp == '.' ) {
35745e5710bSMark Peek static Char *olddir = NULL;
35845e5710bSMark Peek
359c80476e4SDavid E. O'Brien if (tlength == 0 || olddir != z) {
360c80476e4SDavid E. O'Brien olddir = z; /* have we changed dir? */
361c80476e4SDavid E. O'Brien olduser = getusername(&olddir);
362c80476e4SDavid E. O'Brien }
363c80476e4SDavid E. O'Brien if (olduser)
364c80476e4SDavid E. O'Brien z = olddir;
365c80476e4SDavid E. O'Brien }
366c80476e4SDavid E. O'Brien updirs = pdirs = 0;
367c80476e4SDavid E. O'Brien
368c80476e4SDavid E. O'Brien /* option to determine fixed # of dirs from path */
369c80476e4SDavid E. O'Brien if (Scp == '.' || Scp == 'C') {
370c80476e4SDavid E. O'Brien int skip;
3713b6eaa7bSAndrey A. Chernov #ifdef WINNT_NATIVE
37223338178SMark Peek Char *oldz = z;
373c80476e4SDavid E. O'Brien if (z[1] == ':') {
37445e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
37545e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
376c80476e4SDavid E. O'Brien }
377c80476e4SDavid E. O'Brien if (*z == '/' && z[1] == '/') {
37845e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
37945e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
380c80476e4SDavid E. O'Brien do {
38145e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
382c80476e4SDavid E. O'Brien } while (*z != '/');
383c80476e4SDavid E. O'Brien }
3843b6eaa7bSAndrey A. Chernov #endif /* WINNT_NATIVE */
385c80476e4SDavid E. O'Brien q = z;
386c80476e4SDavid E. O'Brien while (*z) /* calc # of /'s */
387c80476e4SDavid E. O'Brien if (*z++ == '/')
388c80476e4SDavid E. O'Brien updirs++;
38923338178SMark Peek
39023338178SMark Peek #ifdef WINNT_NATIVE
39123338178SMark Peek /*
39223338178SMark Peek * for format type c, prompt will be following...
39323338178SMark Peek * c:/path => c:/path
39423338178SMark Peek * c:/path/to => c:to
39523338178SMark Peek * //machine/share => //machine/share
39623338178SMark Peek * //machine/share/folder => //machine:folder
39723338178SMark Peek */
39823338178SMark Peek if (oldz[0] == '/' && oldz[1] == '/' && updirs > 1)
39945e5710bSMark Peek Strbuf_append1(&buf, attributes | ':');
40023338178SMark Peek #endif /* WINNT_NATIVE */
401c80476e4SDavid E. O'Brien if ((Scp == 'C' && *q != '/'))
402c80476e4SDavid E. O'Brien updirs++;
403c80476e4SDavid E. O'Brien
404c80476e4SDavid E. O'Brien if (cp[1] == '0') { /* print <x> or ... */
405c80476e4SDavid E. O'Brien pdirs = 1;
406c80476e4SDavid E. O'Brien cp++;
407c80476e4SDavid E. O'Brien }
408c80476e4SDavid E. O'Brien if (cp[1] >= '1' && cp[1] <= '9') { /* calc # to skip */
409c80476e4SDavid E. O'Brien skip = cp[1] - '0';
410c80476e4SDavid E. O'Brien cp++;
411c80476e4SDavid E. O'Brien }
412c80476e4SDavid E. O'Brien else
413c80476e4SDavid E. O'Brien skip = 1;
414c80476e4SDavid E. O'Brien
415c80476e4SDavid E. O'Brien updirs -= skip;
416c80476e4SDavid E. O'Brien while (skip-- > 0) {
417c80476e4SDavid E. O'Brien while ((z > q) && (*z != '/'))
418c80476e4SDavid E. O'Brien z--; /* back up */
419c80476e4SDavid E. O'Brien if (skip && z > q)
420c80476e4SDavid E. O'Brien z--;
421c80476e4SDavid E. O'Brien }
422c80476e4SDavid E. O'Brien if (*z == '/' && z != q)
423c80476e4SDavid E. O'Brien z++;
424c80476e4SDavid E. O'Brien } /* . || C */
425c80476e4SDavid E. O'Brien
426c80476e4SDavid E. O'Brien /* print ~[user] */
427c80476e4SDavid E. O'Brien if ((olduser) && ((Scp == '~') ||
428c80476e4SDavid E. O'Brien (Scp == '.' && (pdirs || (!pdirs && updirs <= 0))) )) {
42945e5710bSMark Peek Strbuf_append1(&buf, attributes | '~');
43045e5710bSMark Peek for (q = olduser; *q; q++)
43145e5710bSMark Peek Strbuf_append1(&buf, attributes | *q);
432c80476e4SDavid E. O'Brien }
433c80476e4SDavid E. O'Brien
434c80476e4SDavid E. O'Brien /* RWM - tell you how many dirs we've ignored */
435c80476e4SDavid E. O'Brien /* and add '/' at front of this */
436c80476e4SDavid E. O'Brien if (updirs > 0 && pdirs) {
437c80476e4SDavid E. O'Brien if (adrof(STRellipsis)) {
43845e5710bSMark Peek Strbuf_append1(&buf, attributes | '.');
43945e5710bSMark Peek Strbuf_append1(&buf, attributes | '.');
44045e5710bSMark Peek Strbuf_append1(&buf, attributes | '.');
441c80476e4SDavid E. O'Brien } else {
44245e5710bSMark Peek Strbuf_append1(&buf, attributes | '/');
44345e5710bSMark Peek Strbuf_append1(&buf, attributes | '<');
444c80476e4SDavid E. O'Brien if (updirs > 9) {
44545e5710bSMark Peek Strbuf_append1(&buf, attributes | '9');
44645e5710bSMark Peek Strbuf_append1(&buf, attributes | '+');
447c80476e4SDavid E. O'Brien } else
44845e5710bSMark Peek Strbuf_append1(&buf, attributes | ('0' + updirs));
44945e5710bSMark Peek Strbuf_append1(&buf, attributes | '>');
450c80476e4SDavid E. O'Brien }
451c80476e4SDavid E. O'Brien }
452c80476e4SDavid E. O'Brien
45345e5710bSMark Peek while (*z)
45445e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
455c80476e4SDavid E. O'Brien break;
456c80476e4SDavid E. O'Brien /* lukem: end of new directory prompt code */
457c80476e4SDavid E. O'Brien
458c80476e4SDavid E. O'Brien case 'n':
459c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
460c80476e4SDavid E. O'Brien if (what == FMT_WHO) {
46145e5710bSMark Peek cz = who_info(info, 'n');
46245e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
46345e5710bSMark Peek xfree(cz);
464c80476e4SDavid E. O'Brien }
465c80476e4SDavid E. O'Brien else
466c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
467c80476e4SDavid E. O'Brien {
468c80476e4SDavid E. O'Brien if ((z = varval(STRuser)) != STRNULL)
46945e5710bSMark Peek while (*z)
47045e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
471c80476e4SDavid E. O'Brien }
472c80476e4SDavid E. O'Brien break;
4739ccc37e3SMark Peek case 'N':
4749ccc37e3SMark Peek if ((z = varval(STReuser)) != STRNULL)
4759ccc37e3SMark Peek while (*z)
4769ccc37e3SMark Peek Strbuf_append1(&buf, attributes | *z++);
4779ccc37e3SMark Peek break;
478c80476e4SDavid E. O'Brien case 'l':
479c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
480c80476e4SDavid E. O'Brien if (what == FMT_WHO) {
48145e5710bSMark Peek cz = who_info(info, 'l');
48245e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
48345e5710bSMark Peek xfree(cz);
484c80476e4SDavid E. O'Brien }
485c80476e4SDavid E. O'Brien else
486c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
487c80476e4SDavid E. O'Brien {
488c80476e4SDavid E. O'Brien if ((z = varval(STRtty)) != STRNULL)
48945e5710bSMark Peek while (*z)
49045e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
491c80476e4SDavid E. O'Brien }
492c80476e4SDavid E. O'Brien break;
493c80476e4SDavid E. O'Brien case 'd':
49445e5710bSMark Peek tprintf_append_mbs(&buf, day_list[t->tm_wday], attributes);
495c80476e4SDavid E. O'Brien break;
496c80476e4SDavid E. O'Brien case 'D':
49745e5710bSMark Peek p = Itoa(t->tm_mday, 2, attributes);
49845e5710bSMark Peek Strbuf_append(&buf, p);
49945e5710bSMark Peek xfree(p);
500c80476e4SDavid E. O'Brien break;
501c80476e4SDavid E. O'Brien case 'w':
50245e5710bSMark Peek tprintf_append_mbs(&buf, month_list[t->tm_mon], attributes);
503c80476e4SDavid E. O'Brien break;
504c80476e4SDavid E. O'Brien case 'W':
50545e5710bSMark Peek p = Itoa(t->tm_mon + 1, 2, attributes);
50645e5710bSMark Peek Strbuf_append(&buf, p);
50745e5710bSMark Peek xfree(p);
508c80476e4SDavid E. O'Brien break;
509c80476e4SDavid E. O'Brien case 'y':
51045e5710bSMark Peek p = Itoa(t->tm_year % 100, 2, attributes);
51145e5710bSMark Peek Strbuf_append(&buf, p);
51245e5710bSMark Peek xfree(p);
513c80476e4SDavid E. O'Brien break;
514c80476e4SDavid E. O'Brien case 'Y':
51545e5710bSMark Peek p = Itoa(t->tm_year + 1900, 4, attributes);
51645e5710bSMark Peek Strbuf_append(&buf, p);
51745e5710bSMark Peek xfree(p);
518c80476e4SDavid E. O'Brien break;
519c80476e4SDavid E. O'Brien case 'S': /* start standout */
520c80476e4SDavid E. O'Brien attributes |= STANDOUT;
521c80476e4SDavid E. O'Brien break;
522c80476e4SDavid E. O'Brien case 'B': /* start bold */
523c80476e4SDavid E. O'Brien attributes |= BOLD;
524c80476e4SDavid E. O'Brien break;
525c80476e4SDavid E. O'Brien case 'U': /* start underline */
526c80476e4SDavid E. O'Brien attributes |= UNDER;
527c80476e4SDavid E. O'Brien break;
528c80476e4SDavid E. O'Brien case 's': /* end standout */
529c80476e4SDavid E. O'Brien attributes &= ~STANDOUT;
530c80476e4SDavid E. O'Brien break;
531c80476e4SDavid E. O'Brien case 'b': /* end bold */
532c80476e4SDavid E. O'Brien attributes &= ~BOLD;
533c80476e4SDavid E. O'Brien break;
534c80476e4SDavid E. O'Brien case 'u': /* end underline */
535c80476e4SDavid E. O'Brien attributes &= ~UNDER;
536c80476e4SDavid E. O'Brien break;
537c80476e4SDavid E. O'Brien case 'L':
538c80476e4SDavid E. O'Brien ClearToBottom();
539c80476e4SDavid E. O'Brien break;
54029301572SMark Peek
54129301572SMark Peek case 'j':
54229301572SMark Peek {
54329301572SMark Peek int njobs = -1;
54429301572SMark Peek struct process *pp;
54545e5710bSMark Peek
54629301572SMark Peek for (pp = proclist.p_next; pp; pp = pp->p_next)
54729301572SMark Peek njobs++;
5489ccc37e3SMark Peek if (njobs == -1)
5499ccc37e3SMark Peek njobs++;
55045e5710bSMark Peek p = Itoa(njobs, 1, attributes);
55145e5710bSMark Peek Strbuf_append(&buf, p);
55245e5710bSMark Peek xfree(p);
55329301572SMark Peek break;
55429301572SMark Peek }
555c80476e4SDavid E. O'Brien case '?':
556c80476e4SDavid E. O'Brien if ((z = varval(STRstatus)) != STRNULL)
55745e5710bSMark Peek while (*z)
55845e5710bSMark Peek Strbuf_append1(&buf, attributes | *z++);
559c80476e4SDavid E. O'Brien break;
560c80476e4SDavid E. O'Brien case '$':
56145e5710bSMark Peek expdollar(&buf, &cp, attributes);
56245e5710bSMark Peek /* cp should point the last char of current % sequence */
56329301572SMark Peek cp--;
564c80476e4SDavid E. O'Brien break;
565c80476e4SDavid E. O'Brien case '%':
56645e5710bSMark Peek Strbuf_append1(&buf, attributes | '%');
567c80476e4SDavid E. O'Brien break;
568c80476e4SDavid E. O'Brien case '{': /* literal characters start */
569c80476e4SDavid E. O'Brien #if LITERAL == 0
570c80476e4SDavid E. O'Brien /*
571c80476e4SDavid E. O'Brien * No literal capability, so skip all chars in the literal
572c80476e4SDavid E. O'Brien * string
573c80476e4SDavid E. O'Brien */
57445e5710bSMark Peek while (*cp != '\0' && (cp[-1] != '%' || *cp != '}'))
575c80476e4SDavid E. O'Brien cp++;
576c80476e4SDavid E. O'Brien #endif /* LITERAL == 0 */
577c80476e4SDavid E. O'Brien attributes |= LITERAL;
578c80476e4SDavid E. O'Brien break;
579c80476e4SDavid E. O'Brien case '}': /* literal characters end */
580c80476e4SDavid E. O'Brien attributes &= ~LITERAL;
581c80476e4SDavid E. O'Brien break;
582c80476e4SDavid E. O'Brien default:
583c80476e4SDavid E. O'Brien #ifndef HAVENOUTMP
584c80476e4SDavid E. O'Brien if (*cp == 'a' && what == FMT_WHO) {
58545e5710bSMark Peek cz = who_info(info, 'a');
58645e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
58745e5710bSMark Peek xfree(cz);
588c80476e4SDavid E. O'Brien }
589c80476e4SDavid E. O'Brien else
590c80476e4SDavid E. O'Brien #endif /* HAVENOUTMP */
591c80476e4SDavid E. O'Brien {
59245e5710bSMark Peek Strbuf_append1(&buf, attributes | '%');
59345e5710bSMark Peek Strbuf_append1(&buf, attributes | *cp);
594c80476e4SDavid E. O'Brien }
595c80476e4SDavid E. O'Brien break;
596c80476e4SDavid E. O'Brien }
597c80476e4SDavid E. O'Brien }
598c80476e4SDavid E. O'Brien else if (*cp == '\\' || *cp == '^')
59945e5710bSMark Peek Strbuf_append1(&buf, attributes | parseescape(&cp));
600c80476e4SDavid E. O'Brien else if (*cp == HIST) { /* EGS: handle '!'s in prompts */
601c80476e4SDavid E. O'Brien if (what == FMT_HISTORY)
60245e5710bSMark Peek cz = fmthist('h', info);
603c80476e4SDavid E. O'Brien else
60445e5710bSMark Peek cz = xasprintf("%d", eventno + 1);
60545e5710bSMark Peek tprintf_append_mbs(&buf, cz, attributes);
60645e5710bSMark Peek xfree(cz);
607c80476e4SDavid E. O'Brien }
608c80476e4SDavid E. O'Brien else
60945e5710bSMark Peek Strbuf_append1(&buf, attributes | *cp); /* normal character */
610c80476e4SDavid E. O'Brien }
61145e5710bSMark Peek cleanup_ignore(&buf);
61245e5710bSMark Peek cleanup_until(&buf);
61345e5710bSMark Peek return Strbuf_finish(&buf);
614c80476e4SDavid E. O'Brien }
615c80476e4SDavid E. O'Brien
61645e5710bSMark Peek int
expdollar(struct Strbuf * buf,const Char ** srcp,Char attr)61745e5710bSMark Peek expdollar(struct Strbuf *buf, const Char **srcp, Char attr)
618c80476e4SDavid E. O'Brien {
619c80476e4SDavid E. O'Brien struct varent *vp;
620c80476e4SDavid E. O'Brien const Char *src = *srcp;
62145e5710bSMark Peek Char *var, *val;
62245e5710bSMark Peek size_t i;
62345e5710bSMark Peek int curly = 0;
624c80476e4SDavid E. O'Brien
625c80476e4SDavid E. O'Brien /* found a variable, expand it */
62645e5710bSMark Peek var = xmalloc((Strlen(src) + 1) * sizeof (*var));
62745e5710bSMark Peek for (i = 0; ; i++) {
628c80476e4SDavid E. O'Brien var[i] = *++src & TRIM;
629c80476e4SDavid E. O'Brien if (i == 0 && var[i] == '{') {
630c80476e4SDavid E. O'Brien curly = 1;
631c80476e4SDavid E. O'Brien var[i] = *++src & TRIM;
632c80476e4SDavid E. O'Brien }
63345e5710bSMark Peek if (!alnum(var[i]) && var[i] != '_') {
634c80476e4SDavid E. O'Brien
635c80476e4SDavid E. O'Brien var[i] = '\0';
636c80476e4SDavid E. O'Brien break;
637c80476e4SDavid E. O'Brien }
638c80476e4SDavid E. O'Brien }
639c80476e4SDavid E. O'Brien if (curly && (*src & TRIM) == '}')
640c80476e4SDavid E. O'Brien src++;
641c80476e4SDavid E. O'Brien
642c80476e4SDavid E. O'Brien vp = adrof(var);
64329301572SMark Peek if (vp && vp->vec) {
644c80476e4SDavid E. O'Brien for (i = 0; vp->vec[i] != NULL; i++) {
64545e5710bSMark Peek for (val = vp->vec[i]; *val; val++)
64645e5710bSMark Peek if (*val != '\n' && *val != '\r')
64745e5710bSMark Peek Strbuf_append1(buf, *val | attr);
64845e5710bSMark Peek if (vp->vec[i+1])
64945e5710bSMark Peek Strbuf_append1(buf, ' ' | attr);
650c80476e4SDavid E. O'Brien }
651c80476e4SDavid E. O'Brien }
652c80476e4SDavid E. O'Brien else {
65345e5710bSMark Peek val = (!vp) ? tgetenv(var) : NULL;
65445e5710bSMark Peek if (val) {
65545e5710bSMark Peek for (; *val; val++)
65645e5710bSMark Peek if (*val != '\n' && *val != '\r')
65745e5710bSMark Peek Strbuf_append1(buf, *val | attr);
65845e5710bSMark Peek } else {
659c80476e4SDavid E. O'Brien *srcp = src;
66045e5710bSMark Peek xfree(var);
66145e5710bSMark Peek return 0;
662c80476e4SDavid E. O'Brien }
66345e5710bSMark Peek }
664c80476e4SDavid E. O'Brien
665c80476e4SDavid E. O'Brien *srcp = src;
66645e5710bSMark Peek xfree(var);
66745e5710bSMark Peek return 1;
668c80476e4SDavid E. O'Brien }
669