26763: fix problem on failed cd -s to relative path
[zsh.git] / Src / utils.c
blob9716e162ce0adf70c97798e01605446b2f4c198c
1 /*
2 * utils.c - miscellaneous utilities
4 * This file is part of zsh, the Z shell.
6 * Copyright (c) 1992-1997 Paul Falstad
7 * All rights reserved.
9 * Permission is hereby granted, without written agreement and without
10 * license or royalty fees, to use, copy, modify, and distribute this
11 * software and to distribute modified versions of this software for any
12 * purpose, provided that the above copyright notice and the following
13 * two paragraphs appear in all copies of this software.
15 * In no event shall Paul Falstad or the Zsh Development Group be liable
16 * to any party for direct, indirect, special, incidental, or consequential
17 * damages arising out of the use of this software and its documentation,
18 * even if Paul Falstad and the Zsh Development Group have been advised of
19 * the possibility of such damage.
21 * Paul Falstad and the Zsh Development Group specifically disclaim any
22 * warranties, including, but not limited to, the implied warranties of
23 * merchantability and fitness for a particular purpose. The software
24 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25 * Zsh Development Group have no obligation to provide maintenance,
26 * support, updates, enhancements, or modifications.
30 #include "zsh.mdh"
31 #include "utils.pro"
33 /* name of script being sourced */
35 /**/
36 mod_export char *scriptname; /* is sometimes a function name */
38 /* filename of script or other file containing code source e.g. autoload */
40 /**/
41 mod_export char *scriptfilename;
43 #ifdef MULTIBYTE_SUPPORT
44 struct widechar_array {
45 wchar_t *chars;
46 size_t len;
48 typedef struct widechar_array *Widechar_array;
51 * The wordchars variable turned into a wide character array.
52 * This is much more convenient for testing.
54 struct widechar_array wordchars_wide;
57 * The same for the separators (IFS) array.
59 struct widechar_array ifs_wide;
61 /* Function to set one of the above from the multibyte array */
63 static void
64 set_widearray(char *mb_array, Widechar_array wca)
66 if (wca->chars) {
67 free(wca->chars);
68 wca->chars = NULL;
70 wca->len = 0;
72 if (!isset(MULTIBYTE))
73 return;
75 if (mb_array) {
76 VARARR(wchar_t, tmpwcs, strlen(mb_array));
77 wchar_t *wcptr = tmpwcs;
78 wint_t wci;
80 mb_metacharinit();
81 while (*mb_array) {
82 int mblen = mb_metacharlenconv(mb_array, &wci);
84 if (!mblen)
85 break;
86 /* No good unless all characters are convertible */
87 if (wci == WEOF)
88 return;
89 *wcptr++ = (wchar_t)wci;
90 #ifdef DEBUG
92 * This generates a warning from the compiler (and is
93 * indeed useless) if chars are unsigned. It's
94 * extreme paranoia anyway.
96 if (wcptr[-1] < 0)
97 fprintf(stderr, "BUG: Bad cast to wchar_t\n");
98 #endif
99 mb_array += mblen;
102 wca->len = wcptr - tmpwcs;
103 wca->chars = (wchar_t *)zalloc(wca->len * sizeof(wchar_t));
104 wmemcpy(wca->chars, tmpwcs, wca->len);
107 #endif
110 /* Print an error */
112 static void
113 zwarning(const char *cmd, const char *fmt, va_list ap)
115 if (isatty(2))
116 zleentry(ZLE_CMD_TRASH);
118 if (cmd) {
119 if (unset(SHINSTDIN) || locallevel) {
120 nicezputs(scriptname ? scriptname : argzero, stderr);
121 fputc((unsigned char)':', stderr);
123 nicezputs(cmd, stderr);
124 fputc((unsigned char)':', stderr);
125 } else {
127 * scriptname is set when sourcing scripts, so that we get the
128 * correct name instead of the generic name of whatever
129 * program/script is running. It's also set in shell functions,
130 * so test locallevel, too.
132 nicezputs((isset(SHINSTDIN) && !locallevel) ? "zsh" :
133 scriptname ? scriptname : argzero, stderr);
134 fputc((unsigned char)':', stderr);
137 zerrmsg(stderr, fmt, ap);
141 /**/
142 mod_export void
143 zerr(VA_ALIST1(const char *fmt))
144 VA_DCL
146 va_list ap;
147 VA_DEF_ARG(const char *fmt);
149 if (errflag || noerrs) {
150 if (noerrs < 2)
151 errflag = 1;
152 return;
155 VA_START(ap, fmt);
156 VA_GET_ARG(ap, fmt, const char *);
157 zwarning(NULL, fmt, ap);
158 va_end(ap);
159 errflag = 1;
162 /**/
163 mod_export void
164 zerrnam(VA_ALIST2(const char *cmd, const char *fmt))
165 VA_DCL
167 va_list ap;
168 VA_DEF_ARG(const char *cmd);
169 VA_DEF_ARG(const char *fmt);
171 if (errflag || noerrs)
172 return;
174 VA_START(ap, fmt);
175 VA_GET_ARG(ap, cmd, const char *);
176 VA_GET_ARG(ap, fmt, const char *);
177 zwarning(cmd, fmt, ap);
178 va_end(ap);
179 errflag = 1;
182 /**/
183 mod_export void
184 zwarn(VA_ALIST1(const char *fmt))
185 VA_DCL
187 va_list ap;
188 VA_DEF_ARG(const char *fmt);
190 if (errflag || noerrs)
191 return;
193 VA_START(ap, fmt);
194 VA_GET_ARG(ap, fmt, const char *);
195 zwarning(NULL, fmt, ap);
196 va_end(ap);
199 /**/
200 mod_export void
201 zwarnnam(VA_ALIST2(const char *cmd, const char *fmt))
202 VA_DCL
204 va_list ap;
205 VA_DEF_ARG(const char *cmd);
206 VA_DEF_ARG(const char *fmt);
208 if (errflag || noerrs)
209 return;
211 VA_START(ap, fmt);
212 VA_GET_ARG(ap, cmd, const char *);
213 VA_GET_ARG(ap, fmt, const char *);
214 zwarning(cmd, fmt, ap);
215 va_end(ap);
219 #ifdef DEBUG
221 /**/
222 mod_export void
223 dputs(VA_ALIST1(const char *message))
224 VA_DCL
226 char *filename;
227 FILE *file;
228 va_list ap;
229 VA_DEF_ARG(const char *message);
231 VA_START(ap, message);
232 VA_GET_ARG(ap, message, const char *);
233 if ((filename = getsparam("ZSH_DEBUG_LOG")) != NULL &&
234 (file = fopen(filename, "a")) != NULL) {
235 zerrmsg(file, message, ap);
236 fclose(file);
237 } else
238 zerrmsg(stderr, message, ap);
239 va_end(ap);
242 #endif /* DEBUG */
244 #ifdef __CYGWIN__
246 * This works around an occasional problem with dllwrap on Cygwin, seen
247 * on at least two installations. It fails to find the last symbol
248 * exported in alphabetical order (in our case zwarnnam). Until this is
249 * properly categorised and fixed we add a dummy symbol at the end.
251 mod_export void
252 zz_plural_z_alpha(void)
255 #endif
257 /**/
258 void
259 zerrmsg(FILE *file, const char *fmt, va_list ap)
261 const char *str;
262 int num;
263 #ifdef DEBUG
264 long lnum;
265 #endif
266 #ifdef HAVE_STRERROR_R
267 #define ERRBUFSIZE (80)
268 int olderrno;
269 char errbuf[ERRBUFSIZE];
270 #endif
271 char *errmsg;
273 if ((unset(SHINSTDIN) || locallevel) && lineno)
274 fprintf(file, "%ld: ", (long)lineno);
275 else
276 fputc((unsigned char)' ', file);
278 while (*fmt)
279 if (*fmt == '%') {
280 fmt++;
281 switch (*fmt++) {
282 case 's':
283 str = va_arg(ap, const char *);
284 nicezputs(str, file);
285 break;
286 case 'l': {
287 char *s;
288 str = va_arg(ap, const char *);
289 num = va_arg(ap, int);
290 num = metalen(str, num);
291 s = zhalloc(num + 1);
292 memcpy(s, str, num);
293 s[num] = '\0';
294 nicezputs(s, file);
295 break;
297 #ifdef DEBUG
298 case 'L':
299 lnum = va_arg(ap, long);
300 fprintf(file, "%ld", lnum);
301 break;
302 #endif
303 case 'd':
304 num = va_arg(ap, int);
305 fprintf(file, "%d", num);
306 break;
307 case '%':
308 putc('%', file);
309 break;
310 case 'c':
311 num = va_arg(ap, int);
312 #ifdef MULTIBYTE_SUPPORT
313 mb_metacharinit();
314 zputs(wcs_nicechar(num, NULL, NULL), file);
315 #else
316 zputs(nicechar(num), file);
317 #endif
318 break;
319 case 'e':
320 /* print the corresponding message for this errno */
321 num = va_arg(ap, int);
322 if (num == EINTR) {
323 fputs("interrupt\n", file);
324 errflag = 1;
325 return;
327 errmsg = strerror(num);
328 /* If the message is not about I/O problems, it looks better *
329 * if we uncapitalize the first letter of the message */
330 if (num == EIO)
331 fputs(errmsg, file);
332 else {
333 fputc(tulower(errmsg[0]), file);
334 fputs(errmsg + 1, file);
336 break;
338 } else {
339 putc(*fmt == Meta ? *++fmt ^ 32 : *fmt, file);
340 fmt++;
342 putc('\n', file);
343 fflush(file);
346 /* Output a single character, for the termcap routines. *
347 * This is used instead of putchar since it can be a macro. */
349 /**/
350 mod_export int
351 putraw(int c)
353 putc(c, stdout);
354 return 0;
357 /* Output a single character, for the termcap routines. */
359 /**/
360 mod_export int
361 putshout(int c)
363 putc(c, shout);
364 return 0;
368 * Turn a character into a visible representation thereof. The visible
369 * string is put together in a static buffer, and this function returns
370 * a pointer to it. Printable characters stand for themselves, DEL is
371 * represented as "^?", newline and tab are represented as "\n" and
372 * "\t", and normal control characters are represented in "^C" form.
373 * Characters with bit 7 set, if unprintable, are represented as "\M-"
374 * followed by the visible representation of the character with bit 7
375 * stripped off. Tokens are interpreted, rather than being treated as
376 * literal characters.
378 * Note that the returned string is metafied, so that it must be
379 * treated like any other zsh internal string (and not, for example,
380 * output directly).
382 * This function is used even if MULTIBYTE_SUPPORT is defined: we
383 * use it as a fallback in case we couldn't identify a wide character
384 * in a multibyte string.
387 /**/
388 mod_export char *
389 nicechar(int c)
391 static char buf[6];
392 char *s = buf;
393 c &= 0xff;
394 if (isprint(c))
395 goto done;
396 if (c & 0x80) {
397 if (isset(PRINTEIGHTBIT))
398 goto done;
399 *s++ = '\\';
400 *s++ = 'M';
401 *s++ = '-';
402 c &= 0x7f;
403 if(isprint(c))
404 goto done;
406 if (c == 0x7f) {
407 *s++ = '^';
408 c = '?';
409 } else if (c == '\n') {
410 *s++ = '\\';
411 c = 'n';
412 } else if (c == '\t') {
413 *s++ = '\\';
414 c = 't';
415 } else if (c < 0x20) {
416 *s++ = '^';
417 c += 0x40;
419 done:
421 * The resulting string is still metafied, so check if
422 * we are returning a character in the range that needs metafication.
423 * This can't happen if the character is printed "nicely", so
424 * this results in a maximum of two bytes total (plus the null).
426 if (imeta(c)) {
427 *s++ = Meta;
428 *s++ = c ^ 32;
429 } else
430 *s++ = c;
431 *s = 0;
432 return buf;
435 /**/
436 #ifdef MULTIBYTE_SUPPORT
437 static mbstate_t mb_shiftstate;
440 * Initialise multibyte state: called before a sequence of
441 * wcs_nicechar() or mb_metacharlenconv().
444 /**/
445 mod_export void
446 mb_metacharinit(void)
448 memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
452 * The number of bytes we need to allocate for a "nice" representation
453 * of a multibyte character.
455 * We double MB_CUR_MAX to take account of the fact that
456 * we may need to metafy. In fact the representation probably
457 * doesn't allow every character to be in the meta range, but
458 * we don't need to be too pedantic.
460 * The 12 is for the output of a UCS-4 code; we don't actually
461 * need this at the same time as MB_CUR_MAX, but again it's
462 * not worth calculating more exactly.
464 #define NICECHAR_MAX (12 + 2*MB_CUR_MAX)
466 * Input a wide character. Output a printable representation,
467 * which is a metafied multibyte string. With widthp return
468 * the printing width.
470 * swide, if non-NULL, is used to help the completion code, which needs
471 * to know the printing width of the each part of the representation.
472 * *swide is set to the part of the returned string where the wide
473 * character starts. Any string up to that point is ASCII characters,
474 * so the width of it is (*swide - <return_value>). Anything left is
475 * a single wide character corresponding to the remaining width.
476 * Either the initial ASCII part or the wide character part may be empty
477 * (but not both). (Note the complication that the wide character
478 * part may contain metafied characters.)
480 * The caller needs to call mb_metacharinit() before the first call, to
481 * set up the multibyte shift state for a range of characters.
484 /**/
485 mod_export char *
486 wcs_nicechar(wchar_t c, size_t *widthp, char **swidep)
488 static char *buf;
489 static int bufalloc = 0, newalloc;
490 char *s, *mbptr;
491 int ret = 0;
492 VARARR(char, mbstr, MB_CUR_MAX);
495 * We want buf to persist beyond the return. MB_CUR_MAX and hence
496 * NICECHAR_MAX may not be constant, so we have to allocate this at
497 * run time. (We could probably get away with just allocating a
498 * large buffer, in practice.) For efficiency, only reallocate if
499 * we really need to, since this function will be called frequently.
501 newalloc = NICECHAR_MAX;
502 if (bufalloc != newalloc)
504 bufalloc = newalloc;
505 buf = (char *)zrealloc(buf, bufalloc);
508 s = buf;
509 if (!iswprint(c) && (c < 0x80 || !isset(PRINTEIGHTBIT))) {
510 if (c == 0x7f) {
511 *s++ = '^';
512 c = '?';
513 } else if (c == L'\n') {
514 *s++ = '\\';
515 c = 'n';
516 } else if (c == L'\t') {
517 *s++ = '\\';
518 c = 't';
519 } else if (c < 0x20) {
520 *s++ = '^';
521 c += 0x40;
522 } else if (c >= 0x80) {
523 ret = -1;
527 if (ret != -1)
528 ret = wcrtomb(mbstr, c, &mb_shiftstate);
530 if (ret == -1) {
531 memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
533 * Can't or don't want to convert character: use UCS-2 or
534 * UCS-4 code in print escape format.
536 * This comparison fails and generates a compiler warning
537 * if wchar_t is 16 bits, but the code is still correct.
539 if (c >= 0x10000) {
540 sprintf(buf, "\\U%.8x", (unsigned int)c);
541 if (widthp)
542 *widthp = 10;
543 } else if (c >= 0x100) {
544 sprintf(buf, "\\u%.4x", (unsigned int)c);
545 if (widthp)
546 *widthp = 6;
547 } else {
548 strcpy(buf, nicechar((int)c));
550 * There may be metafied characters from nicechar(),
551 * so compute width and end position independently.
553 if (widthp)
554 *widthp = ztrlen(buf);
555 if (swidep)
556 *swidep = buf + strlen(buf);
557 return buf;
559 if (swidep)
560 *swidep = buf + *widthp;
561 return buf;
564 if (widthp) {
565 int wcw = WCWIDTH(c);
566 *widthp = (s - buf);
567 if (wcw >= 0)
568 *widthp += wcw;
569 else
570 (*widthp)++;
572 if (swidep)
573 *swidep = s;
574 for (mbptr = mbstr; ret; s++, mbptr++, ret--) {
575 DPUTS(s >= buf + NICECHAR_MAX,
576 "BUG: buffer too small in wcs_nicechar");
577 if (imeta(*mbptr)) {
578 *s++ = Meta;
579 DPUTS(s >= buf + NICECHAR_MAX,
580 "BUG: buffer too small for metafied char in wcs_nicechar");
581 *s = *mbptr ^ 32;
582 } else {
583 *s = *mbptr;
586 *s = 0;
587 return buf;
590 /**/
591 mod_export int
592 zwcwidth(wint_t wc)
594 int wcw;
595 /* assume a single-byte character if not valid */
596 if (wc == WEOF || unset(MULTIBYTE))
597 return 1;
598 wcw = WCWIDTH(wc);
599 /* if not printable, assume width 1 */
600 if (wcw < 0)
601 return 1;
602 return wcw;
605 /**/
606 #endif /* MULTIBYTE_SUPPORT */
608 /* get a symlink-free pathname for s relative to PWD */
610 /**/
611 char *
612 findpwd(char *s)
614 char *t;
616 if (*s == '/')
617 return xsymlink(s);
618 s = tricat((pwd[1]) ? pwd : "", "/", s);
619 t = xsymlink(s);
620 zsfree(s);
621 return t;
624 /* Check whether a string contains the *
625 * name of the present directory. */
627 /**/
629 ispwd(char *s)
631 struct stat sbuf, tbuf;
633 if (stat(unmeta(s), &sbuf) == 0 && stat(".", &tbuf) == 0)
634 if (sbuf.st_dev == tbuf.st_dev && sbuf.st_ino == tbuf.st_ino)
635 return 1;
636 return 0;
639 static char xbuf[PATH_MAX*2];
641 /**/
642 static char **
643 slashsplit(char *s)
645 char *t, **r, **q;
646 int t0;
648 if (!*s)
649 return (char **) zshcalloc(sizeof(char **));
651 for (t = s, t0 = 0; *t; t++)
652 if (*t == '/')
653 t0++;
654 q = r = (char **) zalloc(sizeof(char **) * (t0 + 2));
656 while ((t = strchr(s, '/'))) {
657 *q++ = ztrduppfx(s, t - s);
658 while (*t == '/')
659 t++;
660 if (!*t) {
661 *q = NULL;
662 return r;
664 s = t;
666 *q++ = ztrdup(s);
667 *q = NULL;
668 return r;
671 /* expands symlinks and .. or . expressions */
672 /* if flag = 0, only expand .. and . expressions */
674 /**/
675 static int
676 xsymlinks(char *s)
678 char **pp, **opp;
679 char xbuf2[PATH_MAX*2], xbuf3[PATH_MAX*2];
680 int t0, ret = 0;
682 opp = pp = slashsplit(s);
683 for (; *pp; pp++) {
684 if (!strcmp(*pp, ".")) {
685 zsfree(*pp);
686 continue;
688 if (!strcmp(*pp, "..")) {
689 char *p;
691 zsfree(*pp);
692 if (!strcmp(xbuf, "/"))
693 continue;
694 p = xbuf + strlen(xbuf);
695 while (*--p != '/');
696 *p = '\0';
697 continue;
699 sprintf(xbuf2, "%s/%s", xbuf, *pp);
700 t0 = readlink(unmeta(xbuf2), xbuf3, PATH_MAX);
701 if (t0 == -1) {
702 strcat(xbuf, "/");
703 strcat(xbuf, *pp);
704 zsfree(*pp);
705 } else {
706 ret = 1;
707 metafy(xbuf3, t0, META_NOALLOC);
708 if (*xbuf3 == '/') {
709 strcpy(xbuf, "");
710 xsymlinks(xbuf3 + 1);
711 } else
712 xsymlinks(xbuf3);
713 zsfree(*pp);
716 free(opp);
717 return ret;
721 * expand symlinks in s, and remove other weird things:
722 * note that this always expands symlinks.
725 /**/
726 char *
727 xsymlink(char *s)
729 if (*s != '/')
730 return NULL;
731 *xbuf = '\0';
732 xsymlinks(s + 1);
733 if (!*xbuf)
734 return ztrdup("/");
735 return ztrdup(xbuf);
738 /**/
739 void
740 print_if_link(char *s)
742 if (*s == '/') {
743 *xbuf = '\0';
744 if (xsymlinks(s + 1))
745 printf(" -> "), zputs(*xbuf ? xbuf : "/", stdout);
749 /* print a directory */
751 /**/
752 void
753 fprintdir(char *s, FILE *f)
755 Nameddir d = finddir(s);
757 if (!d)
758 fputs(unmeta(s), f);
759 else {
760 putc('~', f);
761 fputs(unmeta(d->node.nam), f);
762 fputs(unmeta(s + strlen(d->dir)), f);
766 /* Returns the current username. It caches the username *
767 * and uid to try to avoid requerying the password files *
768 * or NIS/NIS+ database. */
770 /**/
771 uid_t cached_uid;
772 /**/
773 char *cached_username;
775 /**/
776 char *
777 get_username(void)
779 #ifdef HAVE_GETPWUID
780 struct passwd *pswd;
781 uid_t current_uid;
783 current_uid = getuid();
784 if (current_uid != cached_uid) {
785 cached_uid = current_uid;
786 zsfree(cached_username);
787 if ((pswd = getpwuid(current_uid)))
788 cached_username = ztrdup(pswd->pw_name);
789 else
790 cached_username = ztrdup("");
792 #else /* !HAVE_GETPWUID */
793 cached_uid = getuid();
794 #endif /* !HAVE_GETPWUID */
795 return cached_username;
798 /* static variables needed by finddir(). */
800 static char *finddir_full;
801 static Nameddir finddir_last;
802 static int finddir_best;
804 /* ScanFunc used by finddir(). */
806 /**/
807 static void
808 finddir_scan(HashNode hn, UNUSED(int flags))
810 Nameddir nd = (Nameddir) hn;
812 if(nd->diff > finddir_best && !dircmp(nd->dir, finddir_full)
813 && !(nd->node.flags & ND_NOABBREV)) {
814 finddir_last=nd;
815 finddir_best=nd->diff;
819 /* See if a path has a named directory as its prefix. *
820 * If passed a NULL argument, it will invalidate any *
821 * cached information. */
823 /**/
824 Nameddir
825 finddir(char *s)
827 static struct nameddir homenode = { {NULL, "", 0}, NULL, 0 };
828 static int ffsz;
829 Shfunc func = getshfunc("zsh_directory_name");
831 /* Invalidate directory cache if argument is NULL. This is called *
832 * whenever a node is added to or removed from the hash table, and *
833 * whenever the value of $HOME changes. (On startup, too.) */
834 if (!s) {
835 homenode.dir = home ? home : "";
836 homenode.diff = home ? strlen(home) : 0;
837 if(homenode.diff==1)
838 homenode.diff = 0;
839 if(!finddir_full)
840 finddir_full = zalloc(ffsz = PATH_MAX);
841 finddir_full[0] = 0;
842 return finddir_last = NULL;
845 /* It's not safe to use the cache while we have function transformations.*/
846 if(!func && !strcmp(s, finddir_full) && *finddir_full)
847 return finddir_last;
849 if ((int)strlen(s) >= ffsz) {
850 free(finddir_full);
851 finddir_full = zalloc(ffsz = strlen(s) * 2);
853 strcpy(finddir_full, s);
854 finddir_best=0;
855 finddir_last=NULL;
856 finddir_scan(&homenode.node, 0);
857 scanhashtable(nameddirtab, 0, 0, 0, finddir_scan, 0);
859 if (func) {
860 char *dir_meta = metafy(finddir_full, strlen(finddir_full),
861 META_ALLOC);
862 char **ares = subst_string_by_func(func, "d", dir_meta);
863 int len;
864 if (ares && arrlen(ares) >= 2 &&
865 (len = (int)zstrtol(ares[1], NULL, 10)) > finddir_best) {
866 /* better duplicate this string since it's come from REPLY */
867 finddir_last = (Nameddir)hcalloc(sizeof(struct nameddir));
868 finddir_last->node.nam = zhtricat("[", dupstring(ares[0]), "]");
869 finddir_last->dir = dupstrpfx(finddir_full, len);
870 finddir_last->diff = len - strlen(finddir_last->node.nam);
871 finddir_best = len;
873 if (dir_meta != finddir_full)
874 zsfree(dir_meta);
877 return finddir_last;
880 /* add a named directory */
882 /**/
883 mod_export void
884 adduserdir(char *s, char *t, int flags, int always)
886 Nameddir nd;
887 char *eptr;
889 /* We don't maintain a hash table in non-interactive shells. */
890 if (!interact)
891 return;
893 /* The ND_USERNAME flag means that this possible hash table *
894 * entry is derived from a passwd entry. Such entries are *
895 * subordinate to explicitly generated entries. */
896 if ((flags & ND_USERNAME) && nameddirtab->getnode2(nameddirtab, s))
897 return;
899 /* Normal parameter assignments generate calls to this function, *
900 * with always==0. Unless the AUTO_NAME_DIRS option is set, we *
901 * don't let such assignments actually create directory names. *
902 * Instead, a reference to the parameter as a directory name can *
903 * cause the actual creation of the hash table entry. */
904 if (!always && unset(AUTONAMEDIRS) &&
905 !nameddirtab->getnode2(nameddirtab, s))
906 return;
908 if (!t || *t != '/' || strlen(t) >= PATH_MAX) {
909 /* We can't use this value as a directory, so simply remove *
910 * the corresponding entry in the hash table, if any. */
911 HashNode hn = nameddirtab->removenode(nameddirtab, s);
913 if(hn)
914 nameddirtab->freenode(hn);
915 return;
918 /* add the name */
919 nd = (Nameddir) zshcalloc(sizeof *nd);
920 nd->node.flags = flags;
921 eptr = t + strlen(t);
922 while (eptr > t && eptr[-1] == '/')
923 eptr--;
924 if (eptr == t) {
926 * Don't abbreviate multiple slashes at the start of a
927 * named directory, since these are sometimes used for
928 * special purposes.
930 nd->dir = ztrdup(t);
931 } else
932 nd->dir = ztrduppfx(t, eptr - t);
933 /* The variables PWD and OLDPWD are not to be displayed as ~PWD etc. */
934 if (!strcmp(s, "PWD") || !strcmp(s, "OLDPWD"))
935 nd->node.flags |= ND_NOABBREV;
936 nameddirtab->addnode(nameddirtab, ztrdup(s), nd);
939 /* Get a named directory: this function can cause a directory name *
940 * to be added to the hash table, if it isn't there already. */
942 /**/
943 char *
944 getnameddir(char *name)
946 Param pm;
947 char *str;
948 Nameddir nd;
950 /* Check if it is already in the named directory table */
951 if ((nd = (Nameddir) nameddirtab->getnode(nameddirtab, name)))
952 return dupstring(nd->dir);
954 /* Check if there is a scalar parameter with this name whose value *
955 * begins with a `/'. If there is, add it to the hash table and *
956 * return the new value. */
957 if ((pm = (Param) paramtab->getnode(paramtab, name)) &&
958 (PM_TYPE(pm->node.flags) == PM_SCALAR) &&
959 (str = getsparam(name)) && *str == '/') {
960 pm->node.flags |= PM_NAMEDDIR;
961 adduserdir(name, str, 0, 1);
962 return str;
965 #ifdef HAVE_GETPWNAM
967 /* Retrieve an entry from the password table/database for this user. */
968 struct passwd *pw;
969 if ((pw = getpwnam(name))) {
970 char *dir = isset(CHASELINKS) ? xsymlink(pw->pw_dir)
971 : ztrdup(pw->pw_dir);
972 adduserdir(name, dir, ND_USERNAME, 1);
973 str = dupstring(dir);
974 zsfree(dir);
975 return str;
978 #endif /* HAVE_GETPWNAM */
980 /* There are no more possible sources of directory names, so give up. */
981 return NULL;
984 /**/
985 static int
986 dircmp(char *s, char *t)
988 if (s) {
989 for (; *s == *t; s++, t++)
990 if (!*s)
991 return 0;
992 if (!*s && *t == '/')
993 return 0;
995 return 1;
999 * Extra functions to call before displaying the prompt.
1000 * The data is a Prepromptfn.
1003 static LinkList prepromptfns;
1005 /* Add a function to the list of pre-prompt functions. */
1007 /**/
1008 mod_export void
1009 addprepromptfn(voidvoidfnptr_t func)
1011 Prepromptfn ppdat = (Prepromptfn)zalloc(sizeof(struct prepromptfn));
1012 ppdat->func = func;
1013 if (!prepromptfns)
1014 prepromptfns = znewlinklist();
1015 zaddlinknode(prepromptfns, ppdat);
1018 /* Remove a function from the list of pre-prompt functions. */
1020 /**/
1021 mod_export void
1022 delprepromptfn(voidvoidfnptr_t func)
1024 LinkNode ln;
1026 for (ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
1027 Prepromptfn ppdat = (Prepromptfn)getdata(ln);
1028 if (ppdat->func == func) {
1029 (void)remnode(prepromptfns, ln);
1030 zfree(ppdat, sizeof(struct prepromptfn));
1031 return;
1034 #ifdef DEBUG
1035 dputs("BUG: failed to delete node from prepromptfns");
1036 #endif
1040 * Functions to call at a particular time even if not at
1041 * the prompt. This is handled by zle. The data is a
1042 * Timedfn. The functions must be in time order, but this
1043 * is enforced by addtimedfn().
1045 * Note on debugging: the code in sched.c currently assumes it's
1046 * the only user of timedfns for the purposes of checking whether
1047 * there's a function on the list. If this becomes no longer the case,
1048 * the DPUTS() tests in sched.c need rewriting.
1051 /**/
1052 mod_export LinkList timedfns;
1054 /* Add a function to the list of timed functions. */
1056 /**/
1057 mod_export void
1058 addtimedfn(voidvoidfnptr_t func, time_t when)
1060 Timedfn tfdat = (Timedfn)zalloc(sizeof(struct timedfn));
1061 tfdat->func = func;
1062 tfdat->when = when;
1064 if (!timedfns) {
1065 timedfns = znewlinklist();
1066 zaddlinknode(timedfns, tfdat);
1067 } else {
1068 LinkNode ln = firstnode(timedfns);
1071 * Insert the new element in the linked list. We do
1072 * rather too much work here since the standard
1073 * functions insert after a given node, whereas we
1074 * want to insert the new data before the first element
1075 * with a greater time.
1077 * In practice, the only use of timed functions is
1078 * sched, which only adds the one function; so this
1079 * whole branch isn't used beyond the following block.
1081 if (!ln) {
1082 zaddlinknode(timedfns, tfdat);
1083 return;
1085 for (;;) {
1086 Timedfn tfdat2;
1087 LinkNode next = nextnode(ln);
1088 if (!next) {
1089 zaddlinknode(timedfns, tfdat);
1090 return;
1092 tfdat2 = (Timedfn)getdata(next);
1093 if (when < tfdat2->when) {
1094 zinsertlinknode(timedfns, ln, tfdat);
1095 return;
1097 ln = next;
1103 * Delete a function from the list of timed functions.
1104 * Note that if the function apperas multiple times only
1105 * the first occurrence will be removed.
1107 * Note also that when zle calls the function it does *not*
1108 * automatically delete the entry from the list. That must
1109 * be done by the function called. This is recommended as otherwise
1110 * the function will keep being called immediately. (It just so
1111 * happens this "feature" fits in well with the only current use
1112 * of timed functions.)
1115 /**/
1116 mod_export void
1117 deltimedfn(voidvoidfnptr_t func)
1119 LinkNode ln;
1121 for (ln = firstnode(timedfns); ln; ln = nextnode(ln)) {
1122 Timedfn ppdat = (Timedfn)getdata(ln);
1123 if (ppdat->func == func) {
1124 (void)remnode(timedfns, ln);
1125 zfree(ppdat, sizeof(struct timedfn));
1126 return;
1129 #ifdef DEBUG
1130 dputs("BUG: failed to delete node from timedfns");
1131 #endif
1134 /* the last time we checked mail */
1136 /**/
1137 time_t lastmailcheck;
1139 /* the last time we checked the people in the WATCH variable */
1141 /**/
1142 time_t lastwatch;
1145 * Call a function given by "name" with optional arguments
1146 * "lnklist". If these are present the first argument is the function name.
1148 * If "arrayp" is not zero, we also look through
1149 * the array "name"_functions and execute functions found there.
1151 * If "retval" is not NULL, the return value of the first hook function to
1152 * return non-zero is stored in *"retval". The return value is not otherwise
1153 * available as the calling context is restored.
1156 /**/
1157 mod_export int
1158 callhookfunc(char *name, LinkList lnklst, int arrayp, int *retval)
1160 Shfunc shfunc;
1162 * Save stopmsg, since user doesn't get a chance to respond
1163 * to a list of jobs generated in a hook.
1165 int osc = sfcontext, osm = stopmsg, stat = 1, ret = 0;
1167 sfcontext = SFC_HOOK;
1169 if ((shfunc = getshfunc(name))) {
1170 ret = doshfunc(shfunc, lnklst, 1);
1171 stat = 0;
1174 if (arrayp) {
1175 char **arrptr;
1176 int namlen = strlen(name);
1177 VARARR(char, arrnam, namlen + HOOK_SUFFIX_LEN);
1178 memcpy(arrnam, name, namlen);
1179 memcpy(arrnam + namlen, HOOK_SUFFIX, HOOK_SUFFIX_LEN);
1181 if ((arrptr = getaparam(arrnam))) {
1182 for (; *arrptr; arrptr++) {
1183 if ((shfunc = getshfunc(*arrptr))) {
1184 int newret = doshfunc(shfunc, lnklst, 1);
1185 if (!ret)
1186 ret = newret;
1187 stat = 0;
1193 sfcontext = osc;
1194 stopmsg = osm;
1196 if (retval)
1197 *retval = ret;
1198 return stat;
1201 /* do pre-prompt stuff */
1203 /**/
1204 void
1205 preprompt(void)
1207 static time_t lastperiodic;
1208 LinkNode ln;
1209 int period = getiparam("PERIOD");
1210 int mailcheck = getiparam("MAILCHECK");
1212 if (isset(PROMPTSP) && isset(PROMPTCR) && !use_exit_printed && shout) {
1213 /* The PROMPT_SP heuristic will move the prompt down to a new line
1214 * if there was any dangling output on the line (assuming the terminal
1215 * has automatic margins, but we try even if hasam isn't set).
1216 * Unfortunately it interacts badly with ZLE displaying message
1217 * when ^D has been pressed. So just disable PROMPT_SP logic in
1218 * this case */
1219 char *str;
1220 int percents = opts[PROMPTPERCENT];
1221 opts[PROMPTPERCENT] = 1;
1222 str = promptexpand("%B%S%#%s%b", 0, NULL, NULL, NULL);
1223 opts[PROMPTPERCENT] = percents;
1224 fprintf(shout, "%s%*s\r", str, (int)columns - 1 - !hasxn, "");
1225 free(str);
1228 /* If NOTIFY is not set, then check for completed *
1229 * jobs before we print the prompt. */
1230 if (unset(NOTIFY))
1231 scanjobs();
1232 if (errflag)
1233 return;
1235 /* If a shell function named "precmd" exists, *
1236 * then execute it. */
1237 callhookfunc("precmd", NULL, 1, NULL);
1238 if (errflag)
1239 return;
1241 /* If 1) the parameter PERIOD exists, 2) a hook function for *
1242 * "periodic" exists, 3) it's been greater than PERIOD since we *
1243 * executed any such hook, then execute it now. */
1244 if (period && (time(NULL) > lastperiodic + period) &&
1245 !callhookfunc("periodic", NULL, 1, NULL))
1246 lastperiodic = time(NULL);
1247 if (errflag)
1248 return;
1250 /* If WATCH is set, then check for the *
1251 * specified login/logout events. */
1252 if (watch) {
1253 if ((int) difftime(time(NULL), lastwatch) > getiparam("LOGCHECK")) {
1254 dowatch();
1255 lastwatch = time(NULL);
1258 if (errflag)
1259 return;
1261 /* Check mail */
1262 if (mailcheck && (int) difftime(time(NULL), lastmailcheck) > mailcheck) {
1263 char *mailfile;
1265 if (mailpath && *mailpath && **mailpath)
1266 checkmailpath(mailpath);
1267 else {
1268 queue_signals();
1269 if ((mailfile = getsparam("MAIL")) && *mailfile) {
1270 char *x[2];
1272 x[0] = mailfile;
1273 x[1] = NULL;
1274 checkmailpath(x);
1276 unqueue_signals();
1278 lastmailcheck = time(NULL);
1281 if (prepromptfns) {
1282 for(ln = firstnode(prepromptfns); ln; ln = nextnode(ln)) {
1283 Prepromptfn ppnode = (Prepromptfn)getdata(ln);
1284 ppnode->func();
1289 /**/
1290 static void
1291 checkmailpath(char **s)
1293 struct stat st;
1294 char *v, *u, c;
1296 while (*s) {
1297 for (v = *s; *v && *v != '?'; v++);
1298 c = *v;
1299 *v = '\0';
1300 if (c != '?')
1301 u = NULL;
1302 else
1303 u = v + 1;
1304 if (**s == 0) {
1305 *v = c;
1306 zerr("empty MAILPATH component: %s", *s);
1307 } else if (mailstat(unmeta(*s), &st) == -1) {
1308 if (errno != ENOENT)
1309 zerr("%e: %s", errno, *s);
1310 } else if (S_ISDIR(st.st_mode)) {
1311 LinkList l;
1312 DIR *lock = opendir(unmeta(*s));
1313 char buf[PATH_MAX * 2], **arr, **ap;
1314 int ct = 1;
1316 if (lock) {
1317 char *fn;
1319 pushheap();
1320 l = newlinklist();
1321 while ((fn = zreaddir(lock, 1)) && !errflag) {
1322 if (u)
1323 sprintf(buf, "%s/%s?%s", *s, fn, u);
1324 else
1325 sprintf(buf, "%s/%s", *s, fn);
1326 addlinknode(l, dupstring(buf));
1327 ct++;
1329 closedir(lock);
1330 ap = arr = (char **) zhalloc(ct * sizeof(char *));
1332 while ((*ap++ = (char *)ugetnode(l)));
1333 checkmailpath(arr);
1334 popheap();
1336 } else if (shout) {
1337 if (st.st_size && st.st_atime <= st.st_mtime &&
1338 st.st_mtime > lastmailcheck) {
1339 if (!u) {
1340 fprintf(shout, "You have new mail.\n");
1341 fflush(shout);
1342 } else {
1343 char *usav;
1344 int uusav = underscoreused;
1346 usav = zalloc(underscoreused);
1348 if (usav)
1349 memcpy(usav, underscore, underscoreused);
1351 setunderscore(*s);
1353 u = dupstring(u);
1354 if (! parsestr(u)) {
1355 singsub(&u);
1356 zputs(u, shout);
1357 fputc('\n', shout);
1358 fflush(shout);
1360 if (usav) {
1361 setunderscore(usav);
1362 zfree(usav, uusav);
1366 if (isset(MAILWARNING) && st.st_atime > st.st_mtime &&
1367 st.st_atime > lastmailcheck && st.st_size) {
1368 fprintf(shout, "The mail in %s has been read.\n", unmeta(*s));
1369 fflush(shout);
1372 *v = c;
1373 s++;
1377 /* This prints the XTRACE prompt. */
1379 /**/
1380 FILE *xtrerr = 0;
1382 /**/
1383 void
1384 printprompt4(void)
1386 if (!xtrerr)
1387 xtrerr = stderr;
1388 if (prompt4) {
1389 int l, t = opts[XTRACE];
1390 char *s = dupstring(prompt4);
1392 opts[XTRACE] = 0;
1393 unmetafy(s, &l);
1394 s = unmetafy(promptexpand(metafy(s, l, META_NOALLOC),
1395 0, NULL, NULL, NULL), &l);
1396 opts[XTRACE] = t;
1398 fprintf(xtrerr, "%s", s);
1399 free(s);
1403 /**/
1404 mod_export void
1405 freestr(void *a)
1407 zsfree(a);
1410 /**/
1411 mod_export void
1412 gettyinfo(struct ttyinfo *ti)
1414 if (SHTTY != -1) {
1415 #ifdef HAVE_TERMIOS_H
1416 # ifdef HAVE_TCGETATTR
1417 if (tcgetattr(SHTTY, &ti->tio) == -1)
1418 # else
1419 if (ioctl(SHTTY, TCGETS, &ti->tio) == -1)
1420 # endif
1421 zerr("bad tcgets: %e", errno);
1422 #else
1423 # ifdef HAVE_TERMIO_H
1424 ioctl(SHTTY, TCGETA, &ti->tio);
1425 # else
1426 ioctl(SHTTY, TIOCGETP, &ti->sgttyb);
1427 ioctl(SHTTY, TIOCLGET, &ti->lmodes);
1428 ioctl(SHTTY, TIOCGETC, &ti->tchars);
1429 ioctl(SHTTY, TIOCGLTC, &ti->ltchars);
1430 # endif
1431 #endif
1435 /**/
1436 mod_export void
1437 settyinfo(struct ttyinfo *ti)
1439 if (SHTTY != -1) {
1440 #ifdef HAVE_TERMIOS_H
1441 # ifdef HAVE_TCGETATTR
1442 # ifndef TCSADRAIN
1443 # define TCSADRAIN 1 /* XXX Princeton's include files are screwed up */
1444 # endif
1445 while (tcsetattr(SHTTY, TCSADRAIN, &ti->tio) == -1 && errno == EINTR)
1447 # else
1448 while (ioctl(SHTTY, TCSETS, &ti->tio) == -1 && errno == EINTR)
1450 # endif
1451 /* zerr("settyinfo: %e",errno);*/
1452 #else
1453 # ifdef HAVE_TERMIO_H
1454 ioctl(SHTTY, TCSETA, &ti->tio);
1455 # else
1456 ioctl(SHTTY, TIOCSETN, &ti->sgttyb);
1457 ioctl(SHTTY, TIOCLSET, &ti->lmodes);
1458 ioctl(SHTTY, TIOCSETC, &ti->tchars);
1459 ioctl(SHTTY, TIOCSLTC, &ti->ltchars);
1460 # endif
1461 #endif
1465 /* the default tty state */
1467 /**/
1468 mod_export struct ttyinfo shttyinfo;
1470 /* != 0 if we need to call resetvideo() */
1472 /**/
1473 mod_export int resetneeded;
1475 #ifdef TIOCGWINSZ
1476 /* window size changed */
1478 /**/
1479 mod_export int winchanged;
1480 #endif
1482 static int
1483 adjustlines(int signalled)
1485 int oldlines = lines;
1487 #ifdef TIOCGWINSZ
1488 if (signalled || lines <= 0)
1489 lines = shttyinfo.winsize.ws_row;
1490 else
1491 shttyinfo.winsize.ws_row = lines;
1492 #endif /* TIOCGWINSZ */
1493 if (lines <= 0) {
1494 DPUTS(signalled, "BUG: Impossible TIOCGWINSZ rows");
1495 lines = tclines > 0 ? tclines : 24;
1498 if (lines > 2)
1499 termflags &= ~TERM_SHORT;
1500 else
1501 termflags |= TERM_SHORT;
1503 return (lines != oldlines);
1506 static int
1507 adjustcolumns(int signalled)
1509 int oldcolumns = columns;
1511 #ifdef TIOCGWINSZ
1512 if (signalled || columns <= 0)
1513 columns = shttyinfo.winsize.ws_col;
1514 else
1515 shttyinfo.winsize.ws_col = columns;
1516 #endif /* TIOCGWINSZ */
1517 if (columns <= 0) {
1518 DPUTS(signalled, "BUG: Impossible TIOCGWINSZ cols");
1519 columns = tccolumns > 0 ? tccolumns : 80;
1522 if (columns > 2)
1523 termflags &= ~TERM_NARROW;
1524 else
1525 termflags |= TERM_NARROW;
1527 return (columns != oldcolumns);
1530 /* check the size of the window and adjust if necessary. *
1531 * The value of from: *
1532 * 0: called from update_job or setupvals *
1533 * 1: called from the SIGWINCH handler *
1534 * 2: called from the LINES parameter callback *
1535 * 3: called from the COLUMNS parameter callback */
1537 /**/
1538 void
1539 adjustwinsize(int from)
1541 static int getwinsz = 1;
1542 #ifdef TIOCGWINSZ
1543 int ttyrows = shttyinfo.winsize.ws_row;
1544 int ttycols = shttyinfo.winsize.ws_col;
1545 #endif
1546 int resetzle = 0;
1548 if (getwinsz || from == 1) {
1549 #ifdef TIOCGWINSZ
1550 if (SHTTY == -1)
1551 return;
1552 if (ioctl(SHTTY, TIOCGWINSZ, (char *)&shttyinfo.winsize) == 0) {
1553 resetzle = (ttyrows != shttyinfo.winsize.ws_row ||
1554 ttycols != shttyinfo.winsize.ws_col);
1555 if (from == 0 && resetzle && ttyrows && ttycols)
1556 from = 1; /* Signal missed while a job owned the tty? */
1557 ttyrows = shttyinfo.winsize.ws_row;
1558 ttycols = shttyinfo.winsize.ws_col;
1559 } else {
1560 /* Set to value from environment on failure */
1561 shttyinfo.winsize.ws_row = lines;
1562 shttyinfo.winsize.ws_col = columns;
1563 resetzle = (from == 1);
1565 #else
1566 resetzle = from == 1;
1567 #endif /* TIOCGWINSZ */
1568 } /* else
1569 return; */
1571 switch (from) {
1572 case 0:
1573 case 1:
1574 getwinsz = 0;
1575 /* Calling setiparam() here calls this function recursively, but *
1576 * because we've already called adjustlines() and adjustcolumns() *
1577 * here, recursive calls are no-ops unless a signal intervenes. *
1578 * The commented "else return;" above might be a safe shortcut, *
1579 * but I'm concerned about what happens on race conditions; e.g., *
1580 * suppose the user resizes his xterm during `eval $(resize)'? */
1581 if (adjustlines(from) && zgetenv("LINES"))
1582 setiparam("LINES", lines);
1583 if (adjustcolumns(from) && zgetenv("COLUMNS"))
1584 setiparam("COLUMNS", columns);
1585 getwinsz = 1;
1586 break;
1587 case 2:
1588 resetzle = adjustlines(0);
1589 break;
1590 case 3:
1591 resetzle = adjustcolumns(0);
1592 break;
1595 #ifdef TIOCGWINSZ
1596 if (interact && from >= 2 &&
1597 (shttyinfo.winsize.ws_row != ttyrows ||
1598 shttyinfo.winsize.ws_col != ttycols)) {
1599 /* shttyinfo.winsize is already set up correctly */
1600 ioctl(SHTTY, TIOCSWINSZ, (char *)&shttyinfo.winsize);
1602 #endif /* TIOCGWINSZ */
1604 if (zleactive && resetzle) {
1605 #ifdef TIOCGWINSZ
1606 winchanged =
1607 #endif /* TIOCGWINSZ */
1608 resetneeded = 1;
1609 zleentry(ZLE_CMD_REFRESH);
1610 zleentry(ZLE_CMD_RESET_PROMPT);
1614 /* Move a fd to a place >= 10 and mark the new fd in fdtable. If the fd *
1615 * is already >= 10, it is not moved. If it is invalid, -1 is returned. */
1617 /**/
1618 mod_export int
1619 movefd(int fd)
1621 if(fd != -1 && fd < 10) {
1622 #ifdef F_DUPFD
1623 int fe = fcntl(fd, F_DUPFD, 10);
1624 #else
1625 int fe = movefd(dup(fd));
1626 #endif
1627 zclose(fd);
1628 fd = fe;
1630 if(fd != -1) {
1631 if (fd > max_zsh_fd) {
1632 while (fd >= fdtable_size)
1633 fdtable = zrealloc(fdtable,
1634 (fdtable_size *= 2)*sizeof(*fdtable));
1635 max_zsh_fd = fd;
1637 fdtable[fd] = FDT_INTERNAL;
1639 return fd;
1642 /* Move fd x to y. If x == -1, fd y is closed. */
1644 /**/
1645 mod_export void
1646 redup(int x, int y)
1648 if(x < 0)
1649 zclose(y);
1650 else if (x != y) {
1651 while (y >= fdtable_size)
1652 fdtable = zrealloc(fdtable, (fdtable_size *= 2)*sizeof(*fdtable));
1653 dup2(x, y);
1654 if ((fdtable[y] = fdtable[x]) && y > max_zsh_fd)
1655 max_zsh_fd = y;
1656 zclose(x);
1660 /* Close the given fd, and clear it from fdtable. */
1662 /**/
1663 mod_export int
1664 zclose(int fd)
1666 if (fd >= 0) {
1667 fdtable[fd] = FDT_UNUSED;
1668 while (max_zsh_fd > 0 && fdtable[max_zsh_fd] == FDT_UNUSED)
1669 max_zsh_fd--;
1670 if (fd == coprocin)
1671 coprocin = -1;
1672 if (fd == coprocout)
1673 coprocout = -1;
1674 return close(fd);
1676 return -1;
1679 #ifdef HAVE__MKTEMP
1680 extern char *_mktemp(char *);
1681 #endif
1683 /* Get a unique filename for use as a temporary file. If "prefix" is
1684 * NULL, the name is relative to $TMPPREFIX; If it is non-NULL, the
1685 * unique suffix includes a prefixed '.' for improved readability. If
1686 * "use_heap" is true, we allocate the returned name on the heap. */
1688 /**/
1689 mod_export char *
1690 gettempname(const char *prefix, int use_heap)
1692 char *ret, *suffix = prefix ? ".XXXXXX" : "XXXXXX";
1694 queue_signals();
1695 if (!prefix && !(prefix = getsparam("TMPPREFIX")))
1696 prefix = DEFAULT_TMPPREFIX;
1697 if (use_heap)
1698 ret = dyncat(unmeta(prefix), suffix);
1699 else
1700 ret = bicat(unmeta(prefix), suffix);
1702 #ifdef HAVE__MKTEMP
1703 /* Zsh uses mktemp() safely, so silence the warnings */
1704 ret = (char *) _mktemp(ret);
1705 #else
1706 ret = (char *) mktemp(ret);
1707 #endif
1708 unqueue_signals();
1710 return ret;
1713 /**/
1714 mod_export int
1715 gettempfile(const char *prefix, int use_heap, char **tempname)
1717 char *fn;
1718 int fd;
1719 #if HAVE_MKSTEMP
1720 char *suffix = prefix ? ".XXXXXX" : "XXXXXX";
1722 if (!prefix && !(prefix = getsparam("TMPPREFIX")))
1723 prefix = DEFAULT_TMPPREFIX;
1724 if (use_heap)
1725 fn = dyncat(unmeta(prefix), suffix);
1726 else
1727 fn = bicat(unmeta(prefix), suffix);
1729 fd = mkstemp(fn);
1730 if (fd < 0) {
1731 if (!use_heap)
1732 free(fn);
1733 fn = NULL;
1735 #else
1736 int failures = 0;
1738 do {
1739 if (!(fn = gettempname(prefix, use_heap))) {
1740 fd = -1;
1741 break;
1743 if ((fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600)) >= 0)
1744 break;
1745 if (!use_heap)
1746 free(fn);
1747 fn = NULL;
1748 } while (errno == EEXIST && ++failures < 16);
1749 #endif
1750 *tempname = fn;
1751 return fd;
1754 /* Check if a string contains a token */
1756 /**/
1757 mod_export int
1758 has_token(const char *s)
1760 while(*s)
1761 if(itok(*s++))
1762 return 1;
1763 return 0;
1766 /* Delete a character in a string */
1768 /**/
1769 mod_export void
1770 chuck(char *str)
1772 while ((str[0] = str[1]))
1773 str++;
1776 /**/
1777 mod_export int
1778 tulower(int c)
1780 c &= 0xff;
1781 return (isupper(c) ? tolower(c) : c);
1784 /**/
1785 mod_export int
1786 tuupper(int c)
1788 c &= 0xff;
1789 return (islower(c) ? toupper(c) : c);
1792 /* copy len chars from t into s, and null terminate */
1794 /**/
1795 void
1796 ztrncpy(char *s, char *t, int len)
1798 while (len--)
1799 *s++ = *t++;
1800 *s = '\0';
1803 /* copy t into *s and update s */
1805 /**/
1806 mod_export void
1807 strucpy(char **s, char *t)
1809 char *u = *s;
1811 while ((*u++ = *t++));
1812 *s = u - 1;
1815 /**/
1816 mod_export void
1817 struncpy(char **s, char *t, int n)
1819 char *u = *s;
1821 while (n--)
1822 *u++ = *t++;
1823 *s = u;
1824 *u = '\0';
1827 /* Return the number of elements in an array of pointers. *
1828 * It doesn't count the NULL pointer at the end. */
1830 /**/
1831 mod_export int
1832 arrlen(char **s)
1834 int count;
1836 for (count = 0; *s; s++, count++);
1837 return count;
1840 /* Skip over a balanced pair of parenthesis. */
1842 /**/
1843 mod_export int
1844 skipparens(char inpar, char outpar, char **s)
1846 int level;
1848 if (**s != inpar)
1849 return -1;
1851 for (level = 1; *++*s && level;)
1852 if (**s == inpar)
1853 ++level;
1854 else if (**s == outpar)
1855 --level;
1857 return level;
1860 /* Convert string to zlong (see zsh.h). This function (without the z) *
1861 * is contained in the ANSI standard C library, but a lot of them seem *
1862 * to be broken. */
1864 /**/
1865 mod_export zlong
1866 zstrtol(const char *s, char **t, int base)
1868 const char *inp, *trunc = NULL;
1869 zulong calc = 0, newcalc = 0;
1870 int neg;
1872 while (inblank(*s))
1873 s++;
1875 if ((neg = (*s == '-')))
1876 s++;
1877 else if (*s == '+')
1878 s++;
1880 if (!base) {
1881 if (*s != '0')
1882 base = 10;
1883 else if (*++s == 'x' || *s == 'X')
1884 base = 16, s++;
1885 else
1886 base = 8;
1888 inp = s;
1889 if (base < 2 || base > 36) {
1890 zerr("invalid base (must be 2 to 36 inclusive): %d", base);
1891 return (zlong)0;
1892 } else if (base <= 10)
1893 for (; *s >= '0' && *s < ('0' + base); s++) {
1894 if (trunc)
1895 continue;
1896 newcalc = calc * base + *s - '0';
1897 if (newcalc < calc)
1899 trunc = s;
1900 continue;
1902 calc = newcalc;
1904 else
1905 for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
1906 || (*s >= 'A' && *s < ('A' + base - 10)); s++) {
1907 if (trunc)
1908 continue;
1909 newcalc = calc*base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
1910 if (newcalc < calc)
1912 trunc = s;
1913 continue;
1915 calc = newcalc;
1919 * Special case: check for a number that was just too long for
1920 * signed notation.
1921 * Extra special case: the lowest negative number would trigger
1922 * the first test, but is actually representable correctly.
1923 * This is a 1 in the top bit, all others zero, so test for
1924 * that explicitly.
1926 if (!trunc && (zlong)calc < 0 &&
1927 (!neg || calc & ~((zulong)1 << (8*sizeof(zulong)-1))))
1929 trunc = s - 1;
1930 calc /= base;
1933 if (trunc)
1934 zwarn("number truncated after %d digits: %s", (int)(trunc - inp), inp);
1936 if (t)
1937 *t = (char *)s;
1938 return neg ? -(zlong)calc : (zlong)calc;
1941 /**/
1942 mod_export int
1943 setblock_fd(int turnonblocking, int fd, long *modep)
1945 #ifdef O_NDELAY
1946 # ifdef O_NONBLOCK
1947 # define NONBLOCK (O_NDELAY|O_NONBLOCK)
1948 # else /* !O_NONBLOCK */
1949 # define NONBLOCK O_NDELAY
1950 # endif /* !O_NONBLOCK */
1951 #else /* !O_NDELAY */
1952 # ifdef O_NONBLOCK
1953 # define NONBLOCK O_NONBLOCK
1954 # else /* !O_NONBLOCK */
1955 # define NONBLOCK 0
1956 # endif /* !O_NONBLOCK */
1957 #endif /* !O_NDELAY */
1959 #if NONBLOCK
1960 struct stat st;
1962 if (!fstat(fd, &st) && !S_ISREG(st.st_mode)) {
1963 *modep = fcntl(fd, F_GETFL, 0);
1964 if (*modep != -1) {
1965 if (!turnonblocking) {
1966 /* We want to know if blocking was off */
1967 if ((*modep & NONBLOCK) ||
1968 !fcntl(fd, F_SETFL, *modep | NONBLOCK))
1969 return 1;
1970 } else if ((*modep & NONBLOCK) &&
1971 !fcntl(fd, F_SETFL, *modep & ~NONBLOCK)) {
1972 /* Here we want to know if the state changed */
1973 return 1;
1976 } else
1977 #endif /* NONBLOCK */
1978 *modep = -1;
1979 return 0;
1981 #undef NONBLOCK
1984 /**/
1986 setblock_stdin(void)
1988 long mode;
1989 return setblock_fd(1, 0, &mode);
1993 * Check for pending input on fd. If polltty is set, we may need to
1994 * use termio to look for input. As a final resort, go to non-blocking
1995 * input and try to read a character, which in this case will be
1996 * returned in *readchar.
1998 * Note that apart from setting (and restoring) non-blocking input,
1999 * this function does not change the input mode. The calling function
2000 * should have set cbreak mode if necessary.
2003 /**/
2004 mod_export int
2005 read_poll(int fd, int *readchar, int polltty, zlong microseconds)
2007 int ret = -1;
2008 long mode = -1;
2009 char c;
2010 #ifdef HAVE_SELECT
2011 fd_set foofd;
2012 struct timeval expire_tv;
2013 #else
2014 #ifdef FIONREAD
2015 int val;
2016 #endif
2017 #endif
2018 #ifdef HAS_TIO
2019 struct ttyinfo ti;
2020 #endif
2023 #if defined(HAS_TIO) && !defined(__CYGWIN__)
2025 * Under Solaris, at least, reading from the terminal in non-canonical
2026 * mode requires that we use the VMIN mechanism to poll. Any attempt
2027 * to check any other way, or to set the terminal to non-blocking mode
2028 * and poll that way, fails; it will just for canonical mode input.
2029 * We should probably use this mechanism if the user has set non-canonical
2030 * mode, in which case testing here for isatty() and ~ICANON would be
2031 * better than testing whether bin_read() set it, but for now we've got
2032 * enough problems.
2034 * Under Cygwin, you won't be surprised to here, this mechanism,
2035 * although present, doesn't work, and we *have* to use ordinary
2036 * non-blocking reads to find out if there is a character present
2037 * in non-canonical mode.
2039 * I am assuming Solaris is nearer the UNIX norm. This is not necessarily
2040 * as plausible as it sounds, but it seems the right way to guess.
2041 * pws 2000/06/26
2043 if (polltty) {
2044 gettyinfo(&ti);
2045 if ((polltty = ti.tio.c_cc[VMIN])) {
2046 ti.tio.c_cc[VMIN] = 0;
2047 /* termios timeout is 10ths of a second */
2048 ti.tio.c_cc[VTIME] = (int) (microseconds / (zlong)100000);
2049 settyinfo(&ti);
2052 #else
2053 polltty = 0;
2054 #endif
2055 #ifdef HAVE_SELECT
2056 expire_tv.tv_sec = (int) (microseconds / (zlong)1000000);
2057 expire_tv.tv_usec = microseconds % (zlong)1000000;
2058 FD_ZERO(&foofd);
2059 FD_SET(fd, &foofd);
2060 ret = select(fd+1, (SELECT_ARG_2_T) &foofd, NULL, NULL, &expire_tv);
2061 #else
2062 #ifdef FIONREAD
2063 if (ioctl(fd, FIONREAD, (char *) &val) == 0)
2064 ret = (val > 0);
2065 #endif
2066 #endif
2068 if (ret < 0) {
2070 * Final attempt: set non-blocking read and try to read a character.
2071 * Praise Bill, this works under Cygwin (nothing else seems to).
2073 if ((polltty || setblock_fd(0, fd, &mode)) && read(fd, &c, 1) > 0) {
2074 *readchar = c;
2075 ret = 1;
2077 if (mode != -1)
2078 fcntl(fd, F_SETFL, mode);
2080 #ifdef HAS_TIO
2081 if (polltty) {
2082 ti.tio.c_cc[VMIN] = 1;
2083 ti.tio.c_cc[VTIME] = 0;
2084 settyinfo(&ti);
2086 #endif
2087 return (ret > 0);
2090 /**/
2092 checkrmall(char *s)
2094 if (!shout)
2095 return 1;
2096 fprintf(shout, "zsh: sure you want to delete all the files in ");
2097 if (*s != '/') {
2098 nicezputs(pwd[1] ? unmeta(pwd) : "", shout);
2099 fputc('/', shout);
2101 nicezputs(s, shout);
2102 if(isset(RMSTARWAIT)) {
2103 fputs("? (waiting ten seconds)", shout);
2104 fflush(shout);
2105 zbeep();
2106 sleep(10);
2107 fputc('\n', shout);
2109 fputs(" [yn]? ", shout);
2110 fflush(shout);
2111 zbeep();
2112 return (getquery("ny", 1) == 'y');
2115 static int
2116 read1char(int echo)
2118 char c;
2120 while (read(SHTTY, &c, 1) != 1) {
2121 if (errno != EINTR || errflag || retflag || breaks || contflag)
2122 return -1;
2124 if (echo)
2125 write(SHTTY, &c, 1);
2126 return STOUC(c);
2129 /**/
2130 mod_export int
2131 noquery(int purge)
2133 int val = 0;
2135 #ifdef FIONREAD
2136 char c;
2138 ioctl(SHTTY, FIONREAD, (char *)&val);
2139 if (purge) {
2140 for (; val; val--)
2141 read(SHTTY, &c, 1);
2143 #endif
2145 return val;
2148 /**/
2150 getquery(char *valid_chars, int purge)
2152 int c, d, nl = 0;
2153 int isem = !strcmp(term, "emacs");
2154 struct ttyinfo ti;
2156 attachtty(mypgrp);
2158 gettyinfo(&ti);
2159 #ifdef HAS_TIO
2160 ti.tio.c_lflag &= ~ECHO;
2161 if (!isem) {
2162 ti.tio.c_lflag &= ~ICANON;
2163 ti.tio.c_cc[VMIN] = 1;
2164 ti.tio.c_cc[VTIME] = 0;
2166 #else
2167 ti.sgttyb.sg_flags &= ~ECHO;
2168 if (!isem)
2169 ti.sgttyb.sg_flags |= CBREAK;
2170 #endif
2171 settyinfo(&ti);
2173 if (noquery(purge)) {
2174 if (!isem)
2175 settyinfo(&shttyinfo);
2176 write(SHTTY, "n\n", 2);
2177 return 'n';
2180 while ((c = read1char(0)) >= 0) {
2181 if (c == 'Y')
2182 c = 'y';
2183 else if (c == 'N')
2184 c = 'n';
2185 if (!valid_chars)
2186 break;
2187 if (c == '\n') {
2188 c = *valid_chars;
2189 nl = 1;
2190 break;
2192 if (strchr(valid_chars, c)) {
2193 nl = 1;
2194 break;
2196 zbeep();
2198 if (c >= 0)
2199 write(SHTTY, &c, 1);
2200 if (nl)
2201 write(SHTTY, "\n", 1);
2203 if (isem) {
2204 if (c != '\n')
2205 while ((d = read1char(1)) >= 0 && d != '\n');
2206 } else {
2207 if (c != '\n' && !valid_chars) {
2208 #ifdef MULTIBYTE_SUPPORT
2209 if (isset(MULTIBYTE) && c >= 0) {
2211 * No waiting for a valid character, and no draining;
2212 * we should ensure we haven't stopped in the middle
2213 * of a multibyte character.
2215 mbstate_t mbs;
2216 char cc = (char)c;
2217 memset(&mbs, 0, sizeof(mbs));
2218 for (;;) {
2219 size_t ret = mbrlen(&cc, 1, &mbs);
2221 if (ret != MB_INCOMPLETE)
2222 break;
2223 c = read1char(1);
2224 if (c < 0)
2225 break;
2226 cc = (char)c;
2229 #endif
2230 write(SHTTY, "\n", 1);
2233 settyinfo(&shttyinfo);
2234 return c;
2237 static int d;
2238 static char *guess, *best;
2240 /**/
2241 static void
2242 spscan(HashNode hn, UNUSED(int scanflags))
2244 int nd;
2246 nd = spdist(hn->nam, guess, (int) strlen(guess) / 4 + 1);
2247 if (nd <= d) {
2248 best = hn->nam;
2249 d = nd;
2253 /* spellcheck a word */
2254 /* fix s ; if hist is nonzero, fix the history list too */
2256 /**/
2257 mod_export void
2258 spckword(char **s, int hist, int cmd, int ask)
2260 char *t;
2261 int x;
2262 char ic = '\0';
2263 int ne;
2264 int preflen = 0;
2265 int autocd = cmd && isset(AUTOCD) && strcmp(*s, ".") && strcmp(*s, "..");
2267 if ((histdone & HISTFLAG_NOEXEC) || **s == '-' || **s == '%')
2268 return;
2269 if (!strcmp(*s, "in"))
2270 return;
2271 if (!(*s)[0] || !(*s)[1])
2272 return;
2273 if (shfunctab->getnode(shfunctab, *s) ||
2274 builtintab->getnode(builtintab, *s) ||
2275 cmdnamtab->getnode(cmdnamtab, *s) ||
2276 aliastab->getnode(aliastab, *s) ||
2277 reswdtab->getnode(reswdtab, *s))
2278 return;
2279 else if (isset(HASHLISTALL)) {
2280 cmdnamtab->filltable(cmdnamtab);
2281 if (cmdnamtab->getnode(cmdnamtab, *s))
2282 return;
2284 t = *s;
2285 if (*t == Tilde || *t == Equals || *t == String)
2286 t++;
2287 for (; *t; t++)
2288 if (itok(*t))
2289 return;
2290 best = NULL;
2291 for (t = *s; *t; t++)
2292 if (*t == '/')
2293 break;
2294 if (**s == Tilde && !*t)
2295 return;
2296 if (**s == String && !*t) {
2297 guess = *s + 1;
2298 if (itype_end(guess, IIDENT, 1) == guess)
2299 return;
2300 ic = String;
2301 d = 100;
2302 scanhashtable(paramtab, 1, 0, 0, spscan, 0);
2303 } else if (**s == Equals) {
2304 if (*t)
2305 return;
2306 if (hashcmd(guess = *s + 1, pathchecked))
2307 return;
2308 d = 100;
2309 ic = Equals;
2310 scanhashtable(aliastab, 1, 0, 0, spscan, 0);
2311 scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
2312 } else {
2313 guess = *s;
2314 if (*guess == Tilde || *guess == String) {
2315 ic = *guess;
2316 if (!*++t)
2317 return;
2318 guess = dupstring(guess);
2319 ne = noerrs;
2320 noerrs = 2;
2321 singsub(&guess);
2322 noerrs = ne;
2323 if (!guess)
2324 return;
2325 preflen = strlen(guess) - strlen(t);
2327 if (access(unmeta(guess), F_OK) == 0)
2328 return;
2329 best = spname(guess);
2330 if (!*t && cmd) {
2331 if (hashcmd(guess, pathchecked))
2332 return;
2333 d = 100;
2334 scanhashtable(reswdtab, 1, 0, 0, spscan, 0);
2335 scanhashtable(aliastab, 1, 0, 0, spscan, 0);
2336 scanhashtable(shfunctab, 1, 0, 0, spscan, 0);
2337 scanhashtable(builtintab, 1, 0, 0, spscan, 0);
2338 scanhashtable(cmdnamtab, 1, 0, 0, spscan, 0);
2339 if (autocd) {
2340 char **pp;
2341 for (pp = cdpath; *pp; pp++) {
2342 char bestcd[PATH_MAX + 1];
2343 int thisdist;
2344 /* Less than d here, instead of less than or equal *
2345 * as used in spscan(), so that an autocd is chosen *
2346 * only when it is better than anything so far, and *
2347 * so we prefer directories earlier in the cdpath. */
2348 if ((thisdist = mindist(*pp, *s, bestcd)) < d) {
2349 best = dupstring(bestcd);
2350 d = thisdist;
2356 if (errflag)
2357 return;
2358 if (best && (int)strlen(best) > 1 && strcmp(best, guess)) {
2359 if (ic) {
2360 char *u;
2361 if (preflen) {
2362 /* do not correct the result of an expansion */
2363 if (strncmp(guess, best, preflen))
2364 return;
2365 /* replace the temporarily expanded prefix with the original */
2366 u = (char *) hcalloc(t - *s + strlen(best + preflen) + 1);
2367 strncpy(u, *s, t - *s);
2368 strcpy(u + (t - *s), best + preflen);
2369 } else {
2370 u = (char *) hcalloc(strlen(best) + 2);
2371 strcpy(u + 1, best);
2373 best = u;
2374 guess = *s;
2375 *guess = *best = ztokens[ic - Pound];
2377 if (ask) {
2378 if (noquery(0)) {
2379 x = 'n';
2380 } else if (shout) {
2381 char *pptbuf;
2382 pptbuf = promptexpand(sprompt, 0, best, guess, NULL);
2383 zputs(pptbuf, shout);
2384 free(pptbuf);
2385 fflush(shout);
2386 zbeep();
2387 x = getquery("nyae \t", 0);
2388 } else
2389 x = 'n';
2390 } else
2391 x = 'y';
2392 if (x == 'y' || x == ' ' || x == '\t') {
2393 *s = dupstring(best);
2394 if (hist)
2395 hwrep(best);
2396 } else if (x == 'a') {
2397 histdone |= HISTFLAG_NOEXEC;
2398 } else if (x == 'e') {
2399 histdone |= HISTFLAG_NOEXEC | HISTFLAG_RECALL;
2401 if (ic)
2402 **s = ic;
2407 * Helper for ztrftime. Called with a pointer to the length left
2408 * in the buffer, and a new string length to decrement from that.
2409 * Returns 0 if the new length fits, 1 otherwise. We assume a terminating
2410 * NUL and return 1 if that doesn't fit.
2413 static int
2414 ztrftimebuf(int *bufsizeptr, int decr)
2416 if (*bufsizeptr <= decr)
2417 return 1;
2418 *bufsizeptr -= decr;
2419 return 0;
2423 * Like the system function, this returns the number of characters
2424 * copied, not including the terminating NUL. This may be zero
2425 * if the string didn't fit.
2427 * As an extension, try to detect an error in strftime --- typically
2428 * not enough memory --- and return -1. Not guaranteed to be portable,
2429 * since the strftime() interface doesn't make any guarantees about
2430 * the state of the buffer if it returns zero.
2433 /**/
2434 mod_export int
2435 ztrftime(char *buf, int bufsize, char *fmt, struct tm *tm)
2437 int hr12, decr;
2438 #ifndef HAVE_STRFTIME
2439 static char *astr[] =
2440 {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
2441 static char *estr[] =
2442 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul",
2443 "Aug", "Sep", "Oct", "Nov", "Dec"};
2444 #endif
2445 char *origbuf = buf;
2446 char tmp[4];
2449 while (*fmt)
2450 if (*fmt == '%') {
2451 int strip;
2453 fmt++;
2454 if (*fmt == '-') {
2455 strip = 1;
2456 fmt++;
2457 } else
2458 strip = 0;
2460 * Assume this format will take up at least two
2461 * characters. Not always true, but if that matters
2462 * we are so close to the edge it's not a big deal.
2463 * Fix up some longer cases specially when we get to them.
2465 if (ztrftimebuf(&bufsize, 2))
2466 return -1;
2467 switch (*fmt++) {
2468 case 'd':
2469 if (tm->tm_mday > 9 || !strip)
2470 *buf++ = '0' + tm->tm_mday / 10;
2471 *buf++ = '0' + tm->tm_mday % 10;
2472 break;
2473 case 'e':
2474 strip = 1;
2475 /* FALLTHROUGH */
2476 case 'f':
2477 if (tm->tm_mday > 9)
2478 *buf++ = '0' + tm->tm_mday / 10;
2479 else if (!strip)
2480 *buf++ = ' ';
2481 *buf++ = '0' + tm->tm_mday % 10;
2482 break;
2483 case 'K':
2484 strip = 1;
2485 /* FALLTHROUGH */
2486 case 'H':
2487 case 'k':
2488 if (tm->tm_hour > 9)
2489 *buf++ = '0' + tm->tm_hour / 10;
2490 else if (!strip) {
2491 if (fmt[-1] == 'H')
2492 *buf++ = '0';
2493 else
2494 *buf++ = ' ';
2496 *buf++ = '0' + tm->tm_hour % 10;
2497 break;
2498 case 'L':
2499 strip = 1;
2500 /* FALLTHROUGH */
2501 case 'l':
2502 hr12 = tm->tm_hour % 12;
2503 if (hr12 == 0)
2504 hr12 = 12;
2505 if (hr12 > 9)
2506 *buf++ = '1';
2507 else if (!strip)
2508 *buf++ = ' ';
2510 *buf++ = '0' + (hr12 % 10);
2511 break;
2512 case 'm':
2513 if (tm->tm_mon > 8 || !strip)
2514 *buf++ = '0' + (tm->tm_mon + 1) / 10;
2515 *buf++ = '0' + (tm->tm_mon + 1) % 10;
2516 break;
2517 case 'M':
2518 if (tm->tm_min > 9 || !strip)
2519 *buf++ = '0' + tm->tm_min / 10;
2520 *buf++ = '0' + tm->tm_min % 10;
2521 break;
2522 case 'S':
2523 if (tm->tm_sec > 9 || !strip)
2524 *buf++ = '0' + tm->tm_sec / 10;
2525 *buf++ = '0' + tm->tm_sec % 10;
2526 break;
2527 case 'y':
2528 if (tm->tm_year > 9 || !strip)
2529 *buf++ = '0' + (tm->tm_year / 10) % 10;
2530 *buf++ = '0' + tm->tm_year % 10;
2531 break;
2532 case '\0':
2533 /* Guard against premature end of string */
2534 *buf++ = '%';
2535 fmt--;
2536 break;
2537 #ifndef HAVE_STRFTIME
2538 case 'Y':
2541 * Not worth handling this natively if
2542 * strftime has it.
2544 int year, digits, testyear;
2545 year = tm->tm_year + 1900;
2546 digits = 1;
2547 testyear = year;
2548 while (testyear > 9) {
2549 digits++;
2550 testyear /= 10;
2552 if (ztrftimebuf(&bufsize, digits))
2553 return -1;
2554 sprintf(buf, "%d", year);
2555 buf += digits;
2556 break;
2558 case 'a':
2559 if (ztrftimebuf(&bufsize, strlen(astr[tm->tm_wday]) - 2))
2560 return -1;
2561 strucpy(&buf, astr[tm->tm_wday]);
2562 break;
2563 case 'b':
2564 if (ztrftimebuf(&bufsize, strlen(estr[tm->tm_mon]) - 2))
2565 return -1;
2566 strucpy(&buf, estr[tm->tm_mon]);
2567 break;
2568 case 'p':
2569 *buf++ = (tm->tm_hour > 11) ? 'p' : 'a';
2570 *buf++ = 'm';
2571 break;
2572 default:
2573 *buf++ = '%';
2574 if (fmt[-1] != '%')
2575 *buf++ = fmt[-1];
2576 #else
2577 default:
2579 * Remember we've already allowed for two characters
2580 * in the accounting in bufsize (but nowhere else).
2582 *buf = '\1';
2583 sprintf(tmp, strip ? "%%-%c" : "%%%c", fmt[-1]);
2584 if (!strftime(buf, bufsize + 2, tmp, tm))
2586 if (*buf) {
2587 buf[0] = '\0';
2588 return -1;
2590 return 0;
2592 decr = strlen(buf);
2593 buf += decr;
2594 bufsize -= decr - 2;
2595 #endif
2596 break;
2598 } else {
2599 if (ztrftimebuf(&bufsize, 1))
2600 return -1;
2601 *buf++ = *fmt++;
2603 *buf = '\0';
2604 return buf - origbuf;
2607 /**/
2608 mod_export char *
2609 zjoin(char **arr, int delim, int heap)
2611 int len = 0;
2612 char **s, *ret, *ptr;
2614 for (s = arr; *s; s++)
2615 len += strlen(*s) + 1 + (imeta(delim) ? 1 : 0);
2616 if (!len)
2617 return heap? "" : ztrdup("");
2618 ptr = ret = (heap ? (char *) hcalloc(len) : (char *) zshcalloc(len));
2619 for (s = arr; *s; s++) {
2620 strucpy(&ptr, *s);
2621 if (imeta(delim)) {
2622 *ptr++ = Meta;
2623 *ptr++ = delim ^ 32;
2625 else
2626 *ptr++ = delim;
2628 ptr[-1 - (imeta(delim) ? 1 : 0)] = '\0';
2629 return ret;
2632 /* Split a string containing a colon separated list *
2633 * of items into an array of strings. */
2635 /**/
2636 char **
2637 colonsplit(char *s, int uniq)
2639 int ct;
2640 char *t, **ret, **ptr, **p;
2642 for (t = s, ct = 0; *t; t++) /* count number of colons */
2643 if (*t == ':')
2644 ct++;
2645 ptr = ret = (char **) zalloc(sizeof(char **) * (ct + 2));
2647 t = s;
2648 do {
2649 s = t;
2650 /* move t to point at next colon */
2651 for (; *t && *t != ':'; t++);
2652 if (uniq)
2653 for (p = ret; p < ptr; p++)
2654 if ((int)strlen(*p) == t - s && ! strncmp(*p, s, t - s))
2655 goto cont;
2656 *ptr = (char *) zalloc((t - s) + 1);
2657 ztrncpy(*ptr++, s, t - s);
2658 cont: ;
2660 while (*t++);
2661 *ptr = NULL;
2662 return ret;
2665 /**/
2666 static int
2667 skipwsep(char **s)
2669 char *t = *s;
2670 int i = 0;
2673 * Don't need to handle mutlibyte characters, they can't
2674 * be IWSEP. Do need to check for metafication.
2676 while (*t && iwsep(*t == Meta ? t[1] ^ 32 : *t)) {
2677 if (*t == Meta)
2678 t++;
2679 t++;
2680 i++;
2682 *s = t;
2683 return i;
2687 * haven't worked out what allownull does; it's passed down from
2688 * sepsplit but all the cases it's used are either 0 or 1 without
2689 * a comment. it seems to be something to do with the `nulstring'
2690 * which i think is some kind of a metafication thing, so probably
2691 * allownull's value is associated with whether we are using
2692 * metafied strings.
2693 * see findsep() below for handling of `quote' argument
2696 /**/
2697 mod_export char **
2698 spacesplit(char *s, int allownull, int heap, int quote)
2700 char *t, **ret, **ptr;
2701 int l = sizeof(*ret) * (wordcount(s, NULL, -!allownull) + 1);
2702 char *(*dup)(const char *) = (heap ? dupstring : ztrdup);
2704 ptr = ret = (heap ? (char **) hcalloc(l) : (char **) zshcalloc(l));
2706 if (quote) {
2708 * we will be stripping quoted separators by hacking string,
2709 * so make sure it's hackable.
2711 s = dupstring(s);
2714 t = s;
2715 skipwsep(&s);
2716 MB_METACHARINIT();
2717 if (*s && itype_end(s, ISEP, 1) != s)
2718 *ptr++ = dup(allownull ? "" : nulstring);
2719 else if (!allownull && t != s)
2720 *ptr++ = dup("");
2721 while (*s) {
2722 char *iend = itype_end(s, ISEP, 1);
2723 if (iend != s) {
2724 s = iend;
2725 skipwsep(&s);
2727 else if (quote && *s == '\\') {
2728 s++;
2729 skipwsep(&s);
2731 t = s;
2732 (void)findsep(&s, NULL, quote);
2733 if (s > t || allownull) {
2734 *ptr = (heap ? (char *) hcalloc((s - t) + 1) :
2735 (char *) zshcalloc((s - t) + 1));
2736 ztrncpy(*ptr++, t, s - t);
2737 } else
2738 *ptr++ = dup(nulstring);
2739 t = s;
2740 skipwsep(&s);
2742 if (!allownull && t != s)
2743 *ptr++ = dup("");
2744 *ptr = NULL;
2745 return ret;
2749 * Find a separator. Return 0 if already at separator, 1 if separator
2750 * found later, else -1. (Historical note: used to return length into
2751 * string but this is all that is necessary and is less ambiguous with
2752 * multibyte characters around.)
2754 * *s is the string we are looking along, which will be updated
2755 * to the point we have got to.
2757 * sep is a possibly multicharacter separator to look for. If NULL,
2758 * use normal separator characters. If *sep is NULL, split on individual
2759 * characters.
2761 * quote is a flag that '\<sep>' should not be treated as a separator.
2762 * in this case we need to be able to strip the backslash directly
2763 * in the string, so the calling function must have sent us something
2764 * modifiable. currently this only works for sep == NULL. also in
2765 * in this case only, we need to turn \\ into \.
2768 /**/
2769 static int
2770 findsep(char **s, char *sep, int quote)
2774 int i, ilen;
2775 char *t, *tt;
2776 convchar_t c;
2778 MB_METACHARINIT();
2779 if (!sep) {
2780 for (t = *s; *t; t += ilen) {
2781 if (quote && *t == '\\') {
2782 if (t[1] == '\\') {
2783 chuck(t);
2784 ilen = 1;
2785 continue;
2786 } else {
2787 ilen = MB_METACHARLENCONV(t+1, &c);
2788 if (WC_ZISTYPE(c, ISEP)) {
2789 chuck(t);
2790 /* then advance over new character, length ilen */
2791 } else {
2792 /* treat *t (backslash) as normal byte */
2793 if (isep(*t))
2794 break;
2795 ilen = 1;
2798 } else {
2799 ilen = MB_METACHARLENCONV(t, &c);
2800 if (WC_ZISTYPE(c, ISEP))
2801 break;
2804 i = (t > *s);
2805 *s = t;
2806 return i;
2808 if (!sep[0]) {
2810 * NULL separator just means advance past first character,
2811 * if any.
2813 if (**s) {
2814 *s += MB_METACHARLEN(*s);
2815 return 1;
2817 return -1;
2819 for (i = 0; **s; i++) {
2821 * The following works for multibyte characters by virtue of
2822 * the fact that sep may be a string (and we don't care how
2823 * it divides up, we need to match all of it).
2825 for (t = sep, tt = *s; *t && *tt && *t == *tt; t++, tt++);
2826 if (!*t)
2827 return (i > 0);
2828 *s += MB_METACHARLEN(*s);
2830 return -1;
2833 /**/
2834 char *
2835 findword(char **s, char *sep)
2837 char *r, *t;
2838 int sl;
2840 if (!**s)
2841 return NULL;
2843 if (sep) {
2844 sl = strlen(sep);
2845 r = *s;
2846 while (! findsep(s, sep, 0)) {
2847 r = *s += sl;
2849 return r;
2851 MB_METACHARINIT();
2852 for (t = *s; *t; t += sl) {
2853 convchar_t c;
2854 sl = MB_METACHARLENCONV(t, &c);
2855 if (!WC_ZISTYPE(c, ISEP))
2856 break;
2858 *s = t;
2859 (void)findsep(s, sep, 0);
2860 return t;
2863 /**/
2865 wordcount(char *s, char *sep, int mul)
2867 int r, sl, c;
2869 if (sep) {
2870 r = 1;
2871 sl = strlen(sep);
2872 for (; (c = findsep(&s, sep, 0)) >= 0; s += sl)
2873 if ((c && *(s + sl)) || mul)
2874 r++;
2875 } else {
2876 char *t = s;
2878 r = 0;
2879 if (mul <= 0)
2880 skipwsep(&s);
2881 if ((*s && itype_end(s, ISEP, 1) != s) ||
2882 (mul < 0 && t != s))
2883 r++;
2884 for (; *s; r++) {
2885 char *ie = itype_end(s, ISEP, 1);
2886 if (ie != s) {
2887 s = ie;
2888 if (mul <= 0)
2889 skipwsep(&s);
2891 (void)findsep(&s, NULL, 0);
2892 t = s;
2893 if (mul <= 0)
2894 skipwsep(&s);
2896 if (mul < 0 && t != s)
2897 r++;
2899 return r;
2902 /**/
2903 mod_export char *
2904 sepjoin(char **s, char *sep, int heap)
2906 char *r, *p, **t;
2907 int l, sl;
2908 char sepbuf[2];
2910 if (!*s)
2911 return heap ? "" : ztrdup("");
2912 if (!sep) {
2913 /* optimise common case that ifs[0] is space */
2914 if (ifs && *ifs != ' ') {
2915 MB_METACHARINIT();
2916 sep = dupstrpfx(ifs, MB_METACHARLEN(ifs));
2917 } else {
2918 p = sep = sepbuf;
2919 *p++ = ' ';
2920 *p = '\0';
2923 sl = strlen(sep);
2924 for (t = s, l = 1 - sl; *t; l += strlen(*t) + sl, t++);
2925 r = p = (heap ? (char *) hcalloc(l) : (char *) zshcalloc(l));
2926 t = s;
2927 while (*t) {
2928 strucpy(&p, *t);
2929 if (*++t)
2930 strucpy(&p, sep);
2932 *p = '\0';
2933 return r;
2936 /**/
2937 char **
2938 sepsplit(char *s, char *sep, int allownull, int heap)
2940 int n, sl;
2941 char *t, *tt, **r, **p;
2943 if (!sep)
2944 return spacesplit(s, allownull, heap, 0);
2946 sl = strlen(sep);
2947 n = wordcount(s, sep, 1);
2948 r = p = (heap ? (char **) hcalloc((n + 1) * sizeof(char *)) :
2949 (char **) zshcalloc((n + 1) * sizeof(char *)));
2951 for (t = s; n--;) {
2952 tt = t;
2953 (void)findsep(&t, sep, 0);
2954 *p = (heap ? (char *) hcalloc(t - tt + 1) :
2955 (char *) zshcalloc(t - tt + 1));
2956 strncpy(*p, tt, t - tt);
2957 (*p)[t - tt] = '\0';
2958 p++;
2959 t += sl;
2961 *p = NULL;
2963 return r;
2966 /* Get the definition of a shell function */
2968 /**/
2969 mod_export Shfunc
2970 getshfunc(char *nam)
2972 return (Shfunc) shfunctab->getnode(shfunctab, nam);
2976 * Call the function func to substitute string orig by setting
2977 * the parameter reply.
2978 * Return the array from reply, or NULL if the function returned
2979 * non-zero status.
2980 * The returned value comes directly from the parameter and
2981 * so should be used before there is any chance of that
2982 * being changed or unset.
2983 * If arg1 is not NULL, it is used as an initial argument to
2984 * the function, with the original string as the second argument.
2987 /**/
2988 char **
2989 subst_string_by_func(Shfunc func, char *arg1, char *orig)
2991 int osc = sfcontext;
2992 LinkList l = newlinklist();
2993 char **ret;
2995 addlinknode(l, func->node.nam);
2996 if (arg1)
2997 addlinknode(l, arg1);
2998 addlinknode(l, orig);
2999 sfcontext = SFC_SUBST;
3001 if (doshfunc(func, l, 1))
3002 ret = NULL;
3003 else
3004 ret = getaparam("reply");
3006 sfcontext = osc;
3007 return ret;
3010 /**/
3011 mod_export char **
3012 mkarray(char *s)
3014 char **t = (char **) zalloc((s) ? (2 * sizeof s) : (sizeof s));
3016 if ((*t = s))
3017 t[1] = NULL;
3018 return t;
3021 /**/
3022 mod_export void
3023 zbeep(void)
3025 char *vb;
3026 queue_signals();
3027 if ((vb = getsparam("ZBEEP"))) {
3028 int len;
3029 vb = getkeystring(vb, &len, GETKEYS_BINDKEY, NULL);
3030 write(SHTTY, vb, len);
3031 } else if (isset(BEEP))
3032 write(SHTTY, "\07", 1);
3033 unqueue_signals();
3036 /**/
3037 mod_export void
3038 freearray(char **s)
3040 char **t = s;
3042 DPUTS(!s, "freearray() with zero argument");
3044 while (*s)
3045 zsfree(*s++);
3046 free(t);
3049 /**/
3051 equalsplit(char *s, char **t)
3053 for (; *s && *s != '='; s++);
3054 if (*s == '=') {
3055 *s++ = '\0';
3056 *t = s;
3057 return 1;
3059 return 0;
3062 static int specialcomma;
3064 /* the ztypes table */
3066 /**/
3067 mod_export short int typtab[256];
3069 /* initialize the ztypes table */
3071 /**/
3072 void
3073 inittyptab(void)
3075 int t0;
3076 char *s;
3078 for (t0 = 0; t0 != 256; t0++)
3079 typtab[t0] = 0;
3080 for (t0 = 0; t0 != 32; t0++)
3081 typtab[t0] = typtab[t0 + 128] = ICNTRL;
3082 typtab[127] = ICNTRL;
3083 for (t0 = '0'; t0 <= '9'; t0++)
3084 typtab[t0] = IDIGIT | IALNUM | IWORD | IIDENT | IUSER;
3085 for (t0 = 'a'; t0 <= 'z'; t0++)
3086 typtab[t0] = typtab[t0 - 'a' + 'A'] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
3087 #ifndef MULTIBYTE_SUPPORT
3089 * This really doesn't seem to me the right thing to do when
3090 * we have multibyte character support... it was a hack to assume
3091 * eight bit characters `worked' for some values of work before
3092 * we could test for them properly. I'm not 100% convinced
3093 * having IIDENT here is a good idea at all, but this code
3094 * should disappear into history...
3096 for (t0 = 0240; t0 != 0400; t0++)
3097 typtab[t0] = IALPHA | IALNUM | IIDENT | IUSER | IWORD;
3098 #endif
3099 /* typtab['.'] |= IIDENT; */ /* Allow '.' in variable names - broken */
3100 typtab['_'] = IIDENT | IUSER;
3101 typtab['-'] = typtab['.'] = IUSER;
3102 typtab[' '] |= IBLANK | INBLANK;
3103 typtab['\t'] |= IBLANK | INBLANK;
3104 typtab['\n'] |= INBLANK;
3105 typtab['\0'] |= IMETA;
3106 typtab[STOUC(Meta) ] |= IMETA;
3107 typtab[STOUC(Marker)] |= IMETA;
3108 for (t0 = (int)STOUC(Pound); t0 <= (int)STOUC(Comma); t0++)
3109 typtab[t0] |= ITOK | IMETA;
3110 for (t0 = (int)STOUC(Snull); t0 <= (int)STOUC(Nularg); t0++)
3111 typtab[t0] |= ITOK | IMETA | INULL;
3112 for (s = ifs ? ifs : DEFAULT_IFS; *s; s++) {
3113 int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
3114 #ifdef MULTIBYTE_SUPPORT
3115 if (!isascii(c)) {
3116 /* see comment for wordchars below */
3117 continue;
3119 #endif
3120 if (inblank(c)) {
3121 if (s[1] == c)
3122 s++;
3123 else
3124 typtab[c] |= IWSEP;
3126 typtab[c] |= ISEP;
3128 for (s = wordchars ? wordchars : DEFAULT_WORDCHARS; *s; s++) {
3129 int c = STOUC(*s == Meta ? *++s ^ 32 : *s);
3130 #ifdef MULTIBYTE_SUPPORT
3131 if (!isascii(c)) {
3133 * If we have support for multibyte characters, we don't
3134 * handle non-ASCII characters here; instead, we turn
3135 * wordchars into a wide character array.
3136 * (We may actually have a single-byte 8-bit character set,
3137 * but it works the same way.)
3139 continue;
3141 #endif
3142 typtab[c] |= IWORD;
3144 #ifdef MULTIBYTE_SUPPORT
3145 set_widearray(wordchars, &wordchars_wide);
3146 set_widearray(ifs, &ifs_wide);
3147 #endif
3148 for (s = SPECCHARS; *s; s++)
3149 typtab[STOUC(*s)] |= ISPECIAL;
3150 if (specialcomma)
3151 typtab[STOUC(',')] |= ISPECIAL;
3152 if (isset(BANGHIST) && bangchar && interact && isset(SHINSTDIN))
3153 typtab[bangchar] |= ISPECIAL;
3156 /**/
3157 mod_export void
3158 makecommaspecial(int yesno)
3160 if ((specialcomma = yesno) != 0)
3161 typtab[STOUC(',')] |= ISPECIAL;
3162 else
3163 typtab[STOUC(',')] &= ~ISPECIAL;
3167 /**/
3168 #ifdef MULTIBYTE_SUPPORT
3169 /* A wide-character version of the iblank() macro. */
3170 /**/
3171 mod_export int
3172 wcsiblank(wint_t wc)
3174 if (iswspace(wc) && wc != L'\n')
3175 return 1;
3176 return 0;
3180 * zistype macro extended to support wide characters.
3181 * Works for IIDENT, IWORD, IALNUM, ISEP.
3182 * We don't need this for IWSEP because that only applies to
3183 * a fixed set of ASCII characters.
3184 * Note here that use of multibyte mode is not tested:
3185 * that's because for ZLE this is unconditional,
3186 * not dependent on the option. The caller must decide.
3189 /**/
3190 mod_export int
3191 wcsitype(wchar_t c, int itype)
3193 int len;
3194 mbstate_t mbs;
3195 VARARR(char, outstr, MB_CUR_MAX);
3197 if (!isset(MULTIBYTE))
3198 return zistype(c, itype);
3201 * Strategy: the shell requires that the multibyte representation
3202 * be an extension of ASCII. So see if converting the character
3203 * produces an ASCII character. If it does, use zistype on that.
3204 * If it doesn't, use iswalnum on the original character.
3205 * If that fails, resort to the appropriate wide character array.
3207 memset(&mbs, 0, sizeof(mbs));
3208 len = wcrtomb(outstr, c, &mbs);
3210 if (len == 0) {
3211 /* NULL is special */
3212 return zistype(0, itype);
3213 } else if (len == 1 && isascii(outstr[0])) {
3214 return zistype(outstr[0], itype);
3215 } else {
3216 switch (itype) {
3217 case IIDENT:
3218 if (!isset(POSIXIDENTIFIERS))
3219 return 0;
3220 return iswalnum(c);
3222 case IWORD:
3223 if (iswalnum(c))
3224 return 1;
3226 * If we are handling combining characters, any punctuation
3227 * characters with zero width needs to be considered part of
3228 * a word. If we are not handling combining characters then
3229 * logically they are still part of the word, even if they
3230 * don't get displayed properly, so always do this.
3232 if (IS_COMBINING(c))
3233 return 1;
3234 return !!wmemchr(wordchars_wide.chars, c, wordchars_wide.len);
3236 case ISEP:
3237 return !!wmemchr(ifs_wide.chars, c, ifs_wide.len);
3239 default:
3240 return iswalnum(c);
3245 /**/
3246 #endif
3250 * Find the end of a set of characters in the set specified by itype;
3251 * one of IALNUM, IIDENT, IWORD or IUSER. For non-ASCII characters, we assume
3252 * alphanumerics are part of the set, with the exception that
3253 * identifiers are not treated that way if POSIXIDENTIFIERS is set.
3255 * See notes above for identifiers.
3256 * Returns the same pointer as passed if not on an identifier character.
3257 * If "once" is set, just test the first character, i.e. (outptr !=
3258 * inptr) tests whether the first character is valid in an identifier.
3260 * Currently this is only called with itype IIDENT, IUSER or ISEP.
3263 /**/
3264 mod_export char *
3265 itype_end(const char *ptr, int itype, int once)
3267 #ifdef MULTIBYTE_SUPPORT
3268 if (isset(MULTIBYTE) &&
3269 (itype != IIDENT || !isset(POSIXIDENTIFIERS))) {
3270 mb_metacharinit();
3271 while (*ptr) {
3272 wint_t wc;
3273 int len = mb_metacharlenconv(ptr, &wc);
3275 if (!len)
3276 break;
3278 if (wc == WEOF) {
3279 /* invalid, treat as single character */
3280 int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
3281 /* in this case non-ASCII characters can't match */
3282 if (chr > 127 || !zistype(chr,itype))
3283 break;
3284 } else if (len == 1 && isascii(*ptr)) {
3285 /* ASCII: can't be metafied, use standard test */
3286 if (!zistype(*ptr,itype))
3287 break;
3288 } else {
3290 * Valid non-ASCII character.
3292 switch (itype) {
3293 case IWORD:
3294 if (!iswalnum(wc) &&
3295 !wmemchr(wordchars_wide.chars, wc,
3296 wordchars_wide.len))
3297 return (char *)ptr;
3298 break;
3300 case ISEP:
3301 if (!wmemchr(ifs_wide.chars, wc, ifs_wide.len))
3302 return (char *)ptr;
3303 break;
3305 default:
3306 if (!iswalnum(wc))
3307 return (char *)ptr;
3310 ptr += len;
3312 if (once)
3313 break;
3315 } else
3316 #endif
3317 for (;;) {
3318 int chr = STOUC(*ptr == Meta ? ptr[1] ^ 32 : *ptr);
3319 if (!zistype(chr,itype))
3320 break;
3321 ptr += (*ptr == Meta) ? 2 : 1;
3323 if (once)
3324 break;
3328 * Nasty. The first argument is const char * because we
3329 * don't modify it here. However, we really want to pass
3330 * back the same type as was passed down, to allow idioms like
3331 * p = itype_end(p, IIDENT, 0);
3332 * So returning a const char * isn't really the right thing to do.
3333 * Without having two different functions the following seems
3334 * to be the best we can do.
3336 return (char *)ptr;
3339 /**/
3340 mod_export char **
3341 arrdup(char **s)
3343 char **x, **y;
3345 y = x = (char **) zhalloc(sizeof(char *) * (arrlen(s) + 1));
3347 while ((*x++ = dupstring(*s++)));
3349 return y;
3352 /**/
3353 mod_export char **
3354 zarrdup(char **s)
3356 char **x, **y;
3358 y = x = (char **) zalloc(sizeof(char *) * (arrlen(s) + 1));
3360 while ((*x++ = ztrdup(*s++)));
3362 return y;
3365 /**/
3366 #ifdef MULTIBYTE_SUPPORT
3367 /**/
3368 mod_export wchar_t **
3369 wcs_zarrdup(wchar_t **s)
3371 wchar_t **x, **y;
3373 y = x = (wchar_t **) zalloc(sizeof(wchar_t *) * (arrlen((char **)s) + 1));
3375 while ((*x++ = wcs_ztrdup(*s++)));
3377 return y;
3379 /**/
3380 #endif /* MULTIBYTE_SUPPORT */
3382 /**/
3383 static char *
3384 spname(char *oldname)
3386 char *p, spnameguess[PATH_MAX + 1], spnamebest[PATH_MAX + 1];
3387 static char newname[PATH_MAX + 1];
3388 char *new = newname, *old = oldname;
3389 int bestdist = 0, thisdist, thresh, maxthresh = 0;
3391 /* This loop corrects each directory component of the path, stopping *
3392 * when any correction distance would exceed the distance threshold. *
3393 * NULL is returned only if the first component cannot be corrected; *
3394 * otherwise a copy of oldname with a corrected prefix is returned. *
3395 * Rationale for this, if there ever was any, has been forgotten. */
3396 for (;;) {
3397 while (*old == '/')
3398 *new++ = *old++;
3399 *new = '\0';
3400 if (*old == '\0')
3401 return newname;
3402 p = spnameguess;
3403 for (; *old != '/' && *old != '\0'; old++)
3404 if (p < spnameguess + PATH_MAX)
3405 *p++ = *old;
3406 *p = '\0';
3407 /* Every component is allowed a single distance 2 correction or two *
3408 * distance 1 corrections. Longer ones get additional corrections. */
3409 thresh = (int)(p - spnameguess) / 4 + 1;
3410 if (thresh < 3)
3411 thresh = 3;
3412 if ((thisdist = mindist(newname, spnameguess, spnamebest)) >= thresh) {
3413 /* The next test is always true, except for the first path *
3414 * component. We could initialize bestdist to some large *
3415 * constant instead, and then compare to that constant here, *
3416 * because an invariant is that we've never exceeded the *
3417 * threshold for any component so far; but I think that looks *
3418 * odd to the human reader, and we may make use of the total *
3419 * distance for all corrections at some point in the future. */
3420 if (bestdist < maxthresh) {
3421 strcpy(new, spnameguess);
3422 strcat(new, old);
3423 return newname;
3424 } else
3425 return NULL;
3426 } else {
3427 maxthresh = bestdist + thresh;
3428 bestdist += thisdist;
3430 for (p = spnamebest; (*new = *p++);)
3431 new++;
3435 /**/
3436 static int
3437 mindist(char *dir, char *mindistguess, char *mindistbest)
3439 int mindistd, nd;
3440 DIR *dd;
3441 char *fn;
3442 char buf[PATH_MAX];
3444 if (dir[0] == '\0')
3445 dir = ".";
3446 mindistd = 100;
3447 sprintf(buf, "%s/%s", dir, mindistguess);
3448 if (access(unmeta(buf), F_OK) == 0) {
3449 strcpy(mindistbest, mindistguess);
3450 return 0;
3452 if (!(dd = opendir(unmeta(dir))))
3453 return mindistd;
3454 while ((fn = zreaddir(dd, 0))) {
3455 nd = spdist(fn, mindistguess,
3456 (int)strlen(mindistguess) / 4 + 1);
3457 if (nd <= mindistd) {
3458 strcpy(mindistbest, fn);
3459 mindistd = nd;
3460 if (mindistd == 0)
3461 break;
3464 closedir(dd);
3465 return mindistd;
3468 /**/
3469 static int
3470 spdist(char *s, char *t, int thresh)
3472 /* TODO: Correction for non-ASCII and multibyte-input keyboards. */
3473 char *p, *q;
3474 const char qwertykeymap[] =
3475 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
3476 \t1234567890-=\t\
3477 \tqwertyuiop[]\t\
3478 \tasdfghjkl;'\n\t\
3479 \tzxcvbnm,./\t\t\t\
3480 \n\n\n\n\n\n\n\n\n\n\n\n\n\n\
3481 \t!@#$%^&*()_+\t\
3482 \tQWERTYUIOP{}\t\
3483 \tASDFGHJKL:\"\n\t\
3484 \tZXCVBNM<>?\n\n\t\
3485 \n\n\n\n\n\n\n\n\n\n\n\n\n\n";
3486 const char dvorakkeymap[] =
3487 "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\
3488 \t1234567890[]\t\
3489 \t',.pyfgcrl/=\t\
3490 \taoeuidhtns-\n\t\
3491 \t;qjkxbmwvz\t\t\t\
3492 \n\n\n\n\n\n\n\n\n\n\n\n\n\n\
3493 \t!@#$%^&*(){}\t\
3494 \t\"<>PYFGCRL?+\t\
3495 \tAOEUIDHTNS_\n\t\
3496 \t:QJKXBMWVZ\n\n\t\
3497 \n\n\n\n\n\n\n\n\n\n\n\n\n\n";
3498 const char *keymap;
3499 if ( isset( DVORAK ) )
3500 keymap = dvorakkeymap;
3501 else
3502 keymap = qwertykeymap;
3504 if (!strcmp(s, t))
3505 return 0;
3506 /* any number of upper/lower mistakes allowed (dist = 1) */
3507 for (p = s, q = t; *p && tulower(*p) == tulower(*q); p++, q++);
3508 if (!*p && !*q)
3509 return 1;
3510 if (!thresh)
3511 return 200;
3512 for (p = s, q = t; *p && *q; p++, q++)
3513 if (*p == *q)
3514 continue; /* don't consider "aa" transposed, ash */
3515 else if (p[1] == q[0] && q[1] == p[0]) /* transpositions */
3516 return spdist(p + 2, q + 2, thresh - 1) + 1;
3517 else if (p[1] == q[0]) /* missing letter */
3518 return spdist(p + 1, q + 0, thresh - 1) + 2;
3519 else if (p[0] == q[1]) /* missing letter */
3520 return spdist(p + 0, q + 1, thresh - 1) + 2;
3521 else if (*p != *q)
3522 break;
3523 if ((!*p && strlen(q) == 1) || (!*q && strlen(p) == 1))
3524 return 2;
3525 for (p = s, q = t; *p && *q; p++, q++)
3526 if (p[0] != q[0] && p[1] == q[1]) {
3527 int t0;
3528 char *z;
3530 /* mistyped letter */
3532 if (!(z = strchr(keymap, p[0])) || *z == '\n' || *z == '\t')
3533 return spdist(p + 1, q + 1, thresh - 1) + 1;
3534 t0 = z - keymap;
3535 if (*q == keymap[t0 - 15] || *q == keymap[t0 - 14] ||
3536 *q == keymap[t0 - 13] ||
3537 *q == keymap[t0 - 1] || *q == keymap[t0 + 1] ||
3538 *q == keymap[t0 + 13] || *q == keymap[t0 + 14] ||
3539 *q == keymap[t0 + 15])
3540 return spdist(p + 1, q + 1, thresh - 1) + 2;
3541 return 200;
3542 } else if (*p != *q)
3543 break;
3544 return 200;
3547 /* set cbreak mode, or the equivalent */
3549 /**/
3550 void
3551 setcbreak(void)
3553 struct ttyinfo ti;
3555 ti = shttyinfo;
3556 #ifdef HAS_TIO
3557 ti.tio.c_lflag &= ~ICANON;
3558 ti.tio.c_cc[VMIN] = 1;
3559 ti.tio.c_cc[VTIME] = 0;
3560 #else
3561 ti.sgttyb.sg_flags |= CBREAK;
3562 #endif
3563 settyinfo(&ti);
3566 /* give the tty to some process */
3568 /**/
3569 mod_export void
3570 attachtty(pid_t pgrp)
3572 static int ep = 0;
3574 if (jobbing) {
3575 #ifdef HAVE_TCSETPGRP
3576 if (SHTTY != -1 && tcsetpgrp(SHTTY, pgrp) == -1 && !ep)
3577 #else
3578 # if ardent
3579 if (SHTTY != -1 && setpgrp() == -1 && !ep)
3580 # else
3581 int arg = pgrp;
3583 if (SHTTY != -1 && ioctl(SHTTY, TIOCSPGRP, &arg) == -1 && !ep)
3584 # endif
3585 #endif
3587 if (pgrp != mypgrp && kill(-pgrp, 0) == -1)
3588 attachtty(mypgrp);
3589 else {
3590 if (errno != ENOTTY)
3592 zwarn("can't set tty pgrp: %e", errno);
3593 fflush(stderr);
3595 opts[MONITOR] = 0;
3596 ep = 1;
3602 /* get the process group associated with the tty */
3604 /**/
3605 pid_t
3606 gettygrp(void)
3608 pid_t arg;
3610 if (SHTTY == -1)
3611 return -1;
3613 #ifdef HAVE_TCSETPGRP
3614 arg = tcgetpgrp(SHTTY);
3615 #else
3616 ioctl(SHTTY, TIOCGPGRP, &arg);
3617 #endif
3619 return arg;
3623 /* Escape tokens and null characters. Buf is the string which should be *
3624 * escaped. len is the length of the string. If len is -1, buf should be *
3625 * null terminated. If len is non-negative and the third parameter is not *
3626 * META_DUP, buf should point to an at least len+1 long memory area. The *
3627 * return value points to the quoted string. If the given string does not *
3628 * contain any special character which should be quoted and the third *
3629 * parameter is not META_(HEAP|)DUP, buf is returned unchanged (a *
3630 * terminating null character is appended to buf if necessary). Otherwise *
3631 * the third `heap' argument determines the method used to allocate space *
3632 * for the result. It can have the following values: *
3633 * META_REALLOC: use zrealloc on buf *
3634 * META_HREALLOC: use hrealloc on buf *
3635 * META_USEHEAP: get memory from the heap. This leaves buf unchanged. *
3636 * META_NOALLOC: buf points to a memory area which is long enough to hold *
3637 * the quoted form, just quote it and return buf. *
3638 * META_STATIC: store the quoted string in a static area. The original *
3639 * string should be at most PATH_MAX long. *
3640 * META_ALLOC: allocate memory for the new string with zalloc(). *
3641 * META_DUP: leave buf unchanged and allocate space for the return *
3642 * value even if buf does not contains special characters *
3643 * META_HEAPDUP: same as META_DUP, but uses the heap */
3645 /**/
3646 mod_export char *
3647 metafy(char *buf, int len, int heap)
3649 int meta = 0;
3650 char *t, *p, *e;
3651 static char mbuf[PATH_MAX*2+1];
3653 if (len == -1) {
3654 for (e = buf, len = 0; *e; len++)
3655 if (imeta(*e++))
3656 meta++;
3657 } else
3658 for (e = buf; e < buf + len;)
3659 if (imeta(*e++))
3660 meta++;
3662 if (meta || heap == META_DUP || heap == META_HEAPDUP) {
3663 switch (heap) {
3664 case META_REALLOC:
3665 buf = zrealloc(buf, len + meta + 1);
3666 break;
3667 case META_HREALLOC:
3668 buf = hrealloc(buf, len, len + meta + 1);
3669 break;
3670 case META_ALLOC:
3671 case META_DUP:
3672 buf = memcpy(zalloc(len + meta + 1), buf, len);
3673 break;
3674 case META_USEHEAP:
3675 case META_HEAPDUP:
3676 buf = memcpy(zhalloc(len + meta + 1), buf, len);
3677 break;
3678 case META_STATIC:
3679 #ifdef DEBUG
3680 if (len > PATH_MAX) {
3681 fprintf(stderr, "BUG: len = %d > PATH_MAX in metafy\n", len);
3682 fflush(stderr);
3684 #endif
3685 buf = memcpy(mbuf, buf, len);
3686 break;
3687 #ifdef DEBUG
3688 case META_NOALLOC:
3689 break;
3690 default:
3691 fprintf(stderr, "BUG: metafy called with invalid heap value\n");
3692 fflush(stderr);
3693 break;
3694 #endif
3696 p = buf + len;
3697 e = t = buf + len + meta;
3698 while (meta) {
3699 if (imeta(*--t = *--p)) {
3700 *t-- ^= 32;
3701 *t = Meta;
3702 meta--;
3706 *e = '\0';
3707 return buf;
3712 * Take a null-terminated, metafied string in s into a literal
3713 * representation by converting in place. The length is in *len
3714 * len is non-NULL; if len is NULL, you don't know the length of
3715 * the final string, but if it's to be supplied to some system
3716 * routine that always uses NULL termination, such as a filename
3717 * interpreter, that doesn't matter. Note the NULL termination
3718 * is always copied for purposes of that kind.
3721 /**/
3722 mod_export char *
3723 unmetafy(char *s, int *len)
3725 char *p, *t;
3727 for (p = s; *p && *p != Meta; p++);
3728 for (t = p; (*t = *p++);)
3729 if (*t++ == Meta)
3730 t[-1] = *p++ ^ 32;
3731 if (len)
3732 *len = t - s;
3733 return s;
3736 /* Return the character length of a metafied substring, given the *
3737 * unmetafied substring length. */
3739 /**/
3740 mod_export int
3741 metalen(const char *s, int len)
3743 int mlen = len;
3745 while (len--) {
3746 if (*s++ == Meta) {
3747 mlen++;
3748 s++;
3751 return mlen;
3755 * This function converts a zsh internal string to a form which can be
3756 * passed to a system call as a filename. The result is stored in a
3757 * single static area, sized to fit. If there is no Meta character
3758 * the original string is returned.
3761 /**/
3762 mod_export char *
3763 unmeta(const char *file_name)
3765 static char *fn;
3766 static int sz;
3767 char *p;
3768 const char *t;
3769 int newsz, meta;
3771 meta = 0;
3772 for (t = file_name; *t; t++) {
3773 if (*t == Meta)
3774 meta = 1;
3776 if (!meta) {
3778 * don't need allocation... free if it's long, see below
3780 if (sz > 4 * PATH_MAX) {
3781 zfree(fn, sz);
3782 fn = NULL;
3783 sz = 0;
3785 return (char *) file_name;
3788 newsz = (t - file_name) + 1;
3790 * Optimisation: don't resize if we don't have to.
3791 * We need a new allocation if
3792 * - nothing was allocated before
3793 * - the new string is larger than the old one
3794 * - the old string was larger than an arbitrary limit but the
3795 * new string isn't so that we free up significant space by resizing.
3797 if (!fn || newsz > sz || (sz > 4 * PATH_MAX && newsz <= 4 * PATH_MAX))
3799 if (fn)
3800 zfree(fn, sz);
3801 sz = newsz;
3802 fn = (char *)zalloc(sz);
3803 if (!fn) {
3804 sz = 0;
3806 * will quite likely crash in the caller anyway...
3808 return NULL;
3812 for (t = file_name, p = fn; *t; p++)
3813 if ((*p = *t++) == Meta)
3814 *p = *t++ ^ 32;
3815 *p = '\0';
3816 return fn;
3820 * Unmetafy and compare two strings, comparing unsigned character values.
3821 * "a\0" sorts after "a".
3823 * Currently this is only used in hash table sorting, where the
3824 * keys are names of hash nodes and where we don't use strcoll();
3825 * it's not clear if that's right but it does guarantee the ordering
3826 * of shell structures on output.
3828 * As we don't use strcoll(), it seems overkill to convert multibyte
3829 * characters to wide characters for comparison every time. In the case
3830 * of UTF-8, Unicode ordering is preserved when sorted raw, and for
3831 * other character sets we rely on an extension of ASCII so the result,
3832 * while it may not be correct, is at least rational.
3835 /**/
3837 ztrcmp(char const *s1, char const *s2)
3839 int c1, c2;
3841 while(*s1 && *s1 == *s2) {
3842 s1++;
3843 s2++;
3846 if(!(c1 = *s1))
3847 c1 = -1;
3848 else if(c1 == STOUC(Meta))
3849 c1 = *++s1 ^ 32;
3850 if(!(c2 = *s2))
3851 c2 = -1;
3852 else if(c2 == STOUC(Meta))
3853 c2 = *++s2 ^ 32;
3855 if(c1 == c2)
3856 return 0;
3857 else if(c1 < c2)
3858 return -1;
3859 else
3860 return 1;
3863 /* Return the unmetafied length of a metafied string. */
3865 /**/
3866 mod_export int
3867 ztrlen(char const *s)
3869 int l;
3871 for (l = 0; *s; l++) {
3872 if (*s++ == Meta) {
3873 #ifdef DEBUG
3874 if (! *s)
3875 fprintf(stderr, "BUG: unexpected end of string in ztrlen()\n");
3876 else
3877 #endif
3878 s++;
3881 return l;
3884 /* Subtract two pointers in a metafied string. */
3886 /**/
3887 mod_export int
3888 ztrsub(char const *t, char const *s)
3890 int l = t - s;
3892 while (s != t) {
3893 if (*s++ == Meta) {
3894 #ifdef DEBUG
3895 if (! *s || s == t)
3896 fprintf(stderr, "BUG: substring ends in the middle of a metachar in ztrsub()\n");
3897 else
3898 #endif
3899 s++;
3900 l--;
3903 return l;
3906 /**/
3907 mod_export char *
3908 zreaddir(DIR *dir, int ignoredots)
3910 struct dirent *de;
3912 do {
3913 de = readdir(dir);
3914 if(!de)
3915 return NULL;
3916 } while(ignoredots && de->d_name[0] == '.' &&
3917 (!de->d_name[1] || (de->d_name[1] == '.' && !de->d_name[2])));
3919 return metafy(de->d_name, -1, META_STATIC);
3922 /* Unmetafy and output a string. Tokens are skipped. */
3924 /**/
3925 mod_export int
3926 zputs(char const *s, FILE *stream)
3928 int c;
3930 while (*s) {
3931 if (*s == Meta)
3932 c = *++s ^ 32;
3933 else if(itok(*s)) {
3934 s++;
3935 continue;
3936 } else
3937 c = *s;
3938 s++;
3939 if (fputc(c, stream) < 0)
3940 return EOF;
3942 return 0;
3945 #ifndef MULTIBYTE_SUPPORT
3946 /* Create a visibly-represented duplicate of a string. */
3948 /**/
3949 mod_export char *
3950 nicedup(char const *s, int heap)
3952 int c, len = strlen(s) * 5 + 1;
3953 VARARR(char, buf, len);
3954 char *p = buf, *n;
3956 while ((c = *s++)) {
3957 if (itok(c)) {
3958 if (c <= Comma)
3959 c = ztokens[c - Pound];
3960 else
3961 continue;
3963 if (c == Meta)
3964 c = *s++ ^ 32;
3965 /* The result here is metafied */
3966 n = nicechar(c);
3967 while(*n)
3968 *p++ = *n++;
3970 *p = '\0';
3971 return heap ? dupstring(buf) : ztrdup(buf);
3973 #endif
3975 /**/
3976 mod_export char *
3977 nicedupstring(char const *s)
3979 return nicedup(s, 1);
3983 #ifndef MULTIBYTE_SUPPORT
3984 /* Unmetafy and output a string, displaying special characters readably. */
3986 /**/
3987 mod_export int
3988 nicezputs(char const *s, FILE *stream)
3990 int c;
3992 while ((c = *s++)) {
3993 if (itok(c)) {
3994 if (c <= Comma)
3995 c = ztokens[c - Pound];
3996 else
3997 continue;
3999 if (c == Meta)
4000 c = *s++ ^ 32;
4001 if(zputs(nicechar(c), stream) < 0)
4002 return EOF;
4004 return 0;
4008 /* Return the length of the visible representation of a metafied string. */
4010 /**/
4011 mod_export size_t
4012 niceztrlen(char const *s)
4014 size_t l = 0;
4015 int c;
4017 while ((c = *s++)) {
4018 if (itok(c)) {
4019 if (c <= Comma)
4020 c = ztokens[c - Pound];
4021 else
4022 continue;
4024 if (c == Meta)
4025 c = *s++ ^ 32;
4026 l += strlen(nicechar(c));
4028 return l;
4030 #endif
4033 /**/
4034 #ifdef MULTIBYTE_SUPPORT
4036 * Version of both nicezputs() and niceztrlen() for use with multibyte
4037 * characters. Input is a metafied string; output is the screen width of
4038 * the string.
4040 * If the FILE * is not NULL, output to that, too.
4042 * If outstrp is not NULL, set *outstrp to a zalloc'd version of
4043 * the output (still metafied).
4045 * If "heap" is non-zero, use the heap for *outstrp, else zalloc.
4048 /**/
4049 mod_export size_t
4050 mb_niceformat(const char *s, FILE *stream, char **outstrp, int heap)
4052 size_t l = 0, newl;
4053 int umlen, outalloc, outleft, eol = 0;
4054 wchar_t c;
4055 char *ums, *ptr, *fmt, *outstr, *outptr;
4056 mbstate_t mbs;
4058 if (outstrp) {
4059 outleft = outalloc = 5 * strlen(s);
4060 outptr = outstr = zalloc(outalloc);
4061 } else {
4062 outleft = outalloc = 0;
4063 outptr = outstr = NULL;
4066 ums = ztrdup(s);
4068 * is this necessary at this point? niceztrlen does this
4069 * but it's used in lots of places. however, one day this may
4070 * be, too.
4072 untokenize(ums);
4073 ptr = unmetafy(ums, &umlen);
4075 memset(&mbs, 0, sizeof mbs);
4076 while (umlen > 0) {
4077 size_t cnt = eol ? MB_INVALID : mbrtowc(&c, ptr, umlen, &mbs);
4079 switch (cnt) {
4080 case MB_INCOMPLETE:
4081 eol = 1;
4082 /* FALL THROUGH */
4083 case MB_INVALID:
4084 /* The byte didn't convert, so output it as a \M-... sequence. */
4085 fmt = nicechar(*ptr);
4086 newl = strlen(fmt);
4087 cnt = 1;
4088 /* Get mbs out of its undefined state. */
4089 memset(&mbs, 0, sizeof mbs);
4090 break;
4091 case 0:
4092 /* Careful: converting '\0' returns 0, but a '\0' is a
4093 * real character for us, so we should consume 1 byte. */
4094 cnt = 1;
4095 /* FALL THROUGH */
4096 default:
4097 fmt = wcs_nicechar(c, &newl, NULL);
4098 break;
4101 umlen -= cnt;
4102 ptr += cnt;
4103 l += newl;
4105 if (stream)
4106 zputs(fmt, stream);
4107 if (outstr) {
4108 /* Append to output string */
4109 int outlen = strlen(fmt);
4110 if (outlen >= outleft) {
4111 /* Reallocate to twice the length */
4112 int outoffset = outptr - outstr;
4114 outleft += outalloc;
4115 outalloc *= 2;
4116 outstr = zrealloc(outstr, outalloc);
4117 outptr = outstr + outoffset;
4119 memcpy(outptr, fmt, outlen);
4120 /* Update start position */
4121 outptr += outlen;
4122 /* Update available bytes */
4123 outleft -= outlen;
4127 free(ums);
4128 if (outstrp) {
4129 *outptr = '\0';
4130 /* Use more efficient storage for returned string */
4131 *outstrp = heap ? dupstring(outstr) : ztrdup(outstr);
4132 free(outstr);
4135 return l;
4138 /* ztrdup multibyte string with nice formatting */
4140 /**/
4141 mod_export char *
4142 nicedup(const char *s, int heap)
4144 char *retstr;
4146 (void)mb_niceformat(s, NULL, &retstr, heap);
4148 return retstr;
4153 * The guts of mb_metacharlenconv(). This version assumes we are
4154 * processing a true multibyte character string without tokens, and
4155 * takes the shift state as an argument.
4158 /**/
4159 mod_export int
4160 mb_metacharlenconv_r(const char *s, wint_t *wcp, mbstate_t *mbsp)
4162 size_t ret = MB_INVALID;
4163 char inchar;
4164 const char *ptr;
4165 wchar_t wc;
4167 for (ptr = s; *ptr; ) {
4168 if (*ptr == Meta) {
4169 inchar = *++ptr ^ 32;
4170 DPUTS(!*ptr,
4171 "BUG: unexpected end of string in mb_metacharlen()\n");
4172 } else
4173 inchar = *ptr;
4174 ptr++;
4175 ret = mbrtowc(&wc, &inchar, 1, mbsp);
4177 if (ret == MB_INVALID)
4178 break;
4179 if (ret == MB_INCOMPLETE)
4180 continue;
4181 if (wcp)
4182 *wcp = wc;
4183 return ptr - s;
4186 if (wcp)
4187 *wcp = WEOF;
4188 /* No valid multibyte sequence */
4189 memset(mbsp, 0, sizeof(*mbsp));
4190 if (ptr > s) {
4191 return 1 + (*s == Meta); /* Treat as single byte character */
4192 } else
4193 return 0; /* Probably shouldn't happen */
4197 * Length of metafied string s which contains the next multibyte
4198 * character; single (possibly metafied) character if string is not null
4199 * but character is not valid (e.g. possibly incomplete at end of string).
4200 * Returned value is guaranteed not to reach beyond the end of the
4201 * string (assuming correct metafication).
4203 * If wcp is not NULL, the converted wide character is stored there.
4204 * If no conversion could be done WEOF is used.
4207 /**/
4208 mod_export int
4209 mb_metacharlenconv(const char *s, wint_t *wcp)
4211 if (!isset(MULTIBYTE)) {
4212 /* treat as single byte, possibly metafied */
4213 if (wcp)
4214 *wcp = (wint_t)(*s == Meta ? s[1] ^ 32 : *s);
4215 return 1 + (*s == Meta);
4218 * We have to handle tokens here, since we may be looking
4219 * through a tokenized input. Obviously this isn't
4220 * a valid multibyte character, so just return WEOF
4221 * and let the caller handle it as a single character.
4223 * TODO: I've a sneaking suspicion we could do more here
4224 * to prevent the caller always needing to handle invalid
4225 * characters specially, but sometimes it may need to know.
4227 if (itok(*s)) {
4228 if (wcp)
4229 *wcp = WEOF;
4230 return 1;
4233 return mb_metacharlenconv_r(s, wcp, &mb_shiftstate);
4237 * Total number of multibyte characters in metafied string s.
4238 * Same answer as iterating mb_metacharlen() and counting calls
4239 * until end of string.
4241 * If width is 1, return total character width rather than number.
4244 /**/
4245 mod_export int
4246 mb_metastrlen(char *ptr, int width)
4248 char inchar, *laststart;
4249 size_t ret;
4250 wchar_t wc;
4251 int num, num_in_char;
4253 if (!isset(MULTIBYTE))
4254 return ztrlen(ptr);
4256 laststart = ptr;
4257 ret = MB_INVALID;
4258 num = num_in_char = 0;
4260 memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
4261 while (*ptr) {
4262 if (*ptr == Meta)
4263 inchar = *++ptr ^ 32;
4264 else
4265 inchar = *ptr;
4266 ptr++;
4267 ret = mbrtowc(&wc, &inchar, 1, &mb_shiftstate);
4269 if (ret == MB_INCOMPLETE) {
4270 num_in_char++;
4271 } else {
4272 if (ret == MB_INVALID) {
4273 /* Reset, treat as single character */
4274 memset(&mb_shiftstate, 0, sizeof(mb_shiftstate));
4275 ptr = laststart + (*laststart == Meta) + 1;
4276 num++;
4277 } else if (width) {
4279 * Returns -1 if not a printable character. We
4280 * turn this into 1 for backward compatibility.
4282 int wcw = WCWIDTH(wc);
4283 if (wcw >= 0)
4284 num += wcw;
4285 else
4286 num++;
4287 } else
4288 num++;
4289 laststart = ptr;
4290 num_in_char = 0;
4294 /* If incomplete, treat remainder as trailing single bytes */
4295 return num + num_in_char;
4298 /**/
4299 #else
4301 /* Simple replacement for mb_metacharlenconv */
4303 /**/
4304 mod_export int
4305 metacharlenconv(const char *x, int *c)
4308 * Here we don't use STOUC() on the chars since they
4309 * may be compared against other chars and this will fail
4310 * if chars are signed and the high bit is set.
4312 if (*x == Meta) {
4313 if (c)
4314 *c = x[1] ^ 32;
4315 return 2;
4317 if (c)
4318 *c = (char)*x;
4319 return 1;
4322 /**/
4323 #endif /* MULTIBYTE_SUPPORT */
4325 /* check for special characters in the string */
4327 /**/
4328 mod_export int
4329 hasspecial(char const *s)
4331 for (; *s; s++) {
4332 if (ispecial(*s == Meta ? *++s ^ 32 : *s))
4333 return 1;
4335 return 0;
4339 static char *
4340 addunprintable(char *v, const char *u, const char *uend)
4342 for (; u < uend; u++) {
4344 * Just do this byte by byte; there's no great
4345 * advantage in being clever with multibyte
4346 * characters if we don't think they're printable.
4348 int c;
4349 if (*u == Meta)
4350 c = STOUC(*++u ^ 32);
4351 else
4352 c = STOUC(*u);
4353 switch (c) {
4354 case '\0':
4355 *v++ = '\\';
4356 *v++ = '0';
4357 if ('0' <= u[1] && u[1] <= '7') {
4358 *v++ = '0';
4359 *v++ = '0';
4361 break;
4363 case '\007': *v++ = '\\'; *v++ = 'a'; break;
4364 case '\b': *v++ = '\\'; *v++ = 'b'; break;
4365 case '\f': *v++ = '\\'; *v++ = 'f'; break;
4366 case '\n': *v++ = '\\'; *v++ = 'n'; break;
4367 case '\r': *v++ = '\\'; *v++ = 'r'; break;
4368 case '\t': *v++ = '\\'; *v++ = 't'; break;
4369 case '\v': *v++ = '\\'; *v++ = 'v'; break;
4371 default:
4372 *v++ = '\\';
4373 *v++ = '0' + ((c >> 6) & 7);
4374 *v++ = '0' + ((c >> 3) & 7);
4375 *v++ = '0' + (c & 7);
4376 break;
4380 return v;
4384 * Quote the string s and return the result.
4386 * If e is non-zero, the
4387 * pointer it points to may point to a position in s and in e the position
4388 * of the corresponding character in the quoted string is returned.
4390 * The last argument is a QT_ value defined in zsh.h other than QT_NONE.
4392 * The string may be metafied and contain tokens.
4395 /**/
4396 mod_export char *
4397 quotestring(const char *s, char **e, int instring)
4399 const char *u, *tt;
4400 char *v;
4402 * With QT_BACKSLASH we may need to use $'\300' stuff.
4403 * Keep memory usage within limits by allocating temporary
4404 * storage and using heap for correct size at end.
4406 int alloclen = (instring == QT_BACKSLASH ? 7 : 4) * strlen(s) + 1;
4407 char *buf = zshcalloc(alloclen);
4408 int sf = 0;
4409 convchar_t cc;
4410 const char *uend;
4412 DPUTS(instring < QT_BACKSLASH || instring > QT_DOLLARS,
4413 "BUG: bad quote type in quotestring");
4414 tt = v = buf;
4415 u = s;
4416 if (instring == QT_DOLLARS) {
4418 * As we test for printability here we need to be able
4419 * to look for multibyte characters.
4421 MB_METACHARINIT();
4422 while (*u) {
4423 uend = u + MB_METACHARLENCONV(u, &cc);
4425 if (e && !sf && *e <= u) {
4426 *e = v;
4427 sf = 1;
4429 if (
4430 #ifdef MULTIBYTE_SUPPORT
4431 cc != WEOF &&
4432 #endif
4433 WC_ISPRINT(cc)) {
4434 switch (cc) {
4435 case ZWC('\\'):
4436 case ZWC('\''):
4437 *v++ = '\\';
4438 break;
4440 default:
4441 if (isset(BANGHIST) && cc == (wchar_t)bangchar)
4442 *v++ = '\\';
4443 break;
4445 while (u < uend)
4446 *v++ = *u++;
4447 } else {
4448 /* Not printable */
4449 v = addunprintable(v, u, uend);
4450 u = uend;
4454 else
4457 * Here there are syntactic special characters, so
4458 * we start by going through bytewise.
4460 while (*u) {
4461 int dobackslash = 0;
4462 if (e && *e == u)
4463 *e = v, sf = 1;
4464 if (*u == Tick || *u == Qtick) {
4465 char c = *u++;
4467 *v++ = c;
4468 while (*u && *u != c)
4469 *v++ = *u++;
4470 *v++ = c;
4471 if (*u)
4472 u++;
4473 continue;
4474 } else if ((*u == Qstring || *u == '$') && u[1] == '\'' &&
4475 instring == QT_DOUBLE) {
4477 * We don't need to quote $'...' inside a double-quoted
4478 * string. This is largely cosmetic; it looks neater
4479 * if we don't but it doesn't do any harm since the
4480 * \ is stripped.
4482 *v++ = *u++;
4483 } else if ((*u == String || *u == Qstring) &&
4484 (u[1] == Inpar || u[1] == Inbrack || u[1] == Inbrace)) {
4485 char c = (u[1] == Inpar ? Outpar : (u[1] == Inbrace ?
4486 Outbrace : Outbrack));
4487 char beg = *u;
4488 int level = 0;
4490 *v++ = *u++;
4491 *v++ = *u++;
4492 while (*u && (*u != c || level)) {
4493 if (*u == beg)
4494 level++;
4495 else if (*u == c)
4496 level--;
4497 *v++ = *u++;
4499 if (*u)
4500 *v++ = *u++;
4501 continue;
4503 else if (ispecial(*u) &&
4504 ((*u != '=' && *u != '~') ||
4505 u == s ||
4506 (isset(MAGICEQUALSUBST) &&
4507 (u[-1] == '=' || u[-1] == ':')) ||
4508 (*u == '~' && isset(EXTENDEDGLOB))) &&
4509 (instring == QT_BACKSLASH ||
4510 (isset(BANGHIST) && *u == (char)bangchar &&
4511 instring != QT_SINGLE) ||
4512 (instring == QT_DOUBLE &&
4513 (*u == '$' || *u == '`' || *u == '\"' || *u == '\\')) ||
4514 (instring == QT_SINGLE && *u == '\''))) {
4515 if (*u == '\n' || (instring == QT_SINGLE && *u == '\'')) {
4516 if (unset(RCQUOTES)) {
4517 *v++ = '\'';
4518 if (*u == '\'')
4519 *v++ = '\\';
4520 *v++ = *u;
4521 *v++ = '\'';
4522 } else if (*u == '\n')
4523 *v++ = '"', *v++ = '\n', *v++ = '"';
4524 else
4525 *v++ = '\'', *v++ = '\'';
4526 u++;
4527 continue;
4528 } else {
4530 * We'll need a backslash, but don't add it
4531 * yet since if the character isn't printable
4532 * we'll have to upgrade it to $'...'.
4534 dobackslash = 1;
4538 if (itok(*u) || instring != QT_BACKSLASH) {
4539 /* Needs to be passed straight through. */
4540 if (dobackslash)
4541 *v++ = '\\';
4542 *v++ = *u++;
4543 continue;
4547 * Now check if the output is unprintable in the
4548 * current character set.
4550 uend = u + MB_METACHARLENCONV(u, &cc);
4551 if (
4552 #ifdef MULTIBYTE_SUPPORT
4553 cc != WEOF &&
4554 #endif
4555 WC_ISPRINT(cc)) {
4556 if (dobackslash)
4557 *v++ = '\\';
4558 while (u < uend) {
4559 if (*u == Meta)
4560 *v++ = *u++;
4561 *v++ = *u++;
4563 } else {
4564 /* Not printable */
4565 *v++ = '$';
4566 *v++ = '\'';
4567 v = addunprintable(v, u, uend);
4568 *v++ = '\'';
4569 u = uend;
4573 *v = '\0';
4575 if (e && *e == u)
4576 *e = v, sf = 1;
4577 DPUTS(e && !sf, "BUG: Wild pointer *e in quotestring()");
4579 v = dupstring(buf);
4580 zfree(buf, alloclen);
4581 return v;
4584 /* Unmetafy and output a string, quoted if it contains special characters. */
4586 /**/
4587 mod_export int
4588 quotedzputs(char const *s, FILE *stream)
4590 int inquote = 0, c;
4592 /* check for empty string */
4593 if(!*s)
4594 return fputs("''", stream);
4596 if (!hasspecial(s))
4597 return zputs(s, stream);
4599 if (isset(RCQUOTES)) {
4600 /* use rc-style quotes-within-quotes for the whole string */
4601 if(fputc('\'', stream) < 0)
4602 return EOF;
4603 while(*s) {
4604 if (*s == Meta)
4605 c = *++s ^ 32;
4606 else
4607 c = *s;
4608 s++;
4609 if (c == '\'') {
4610 if(fputc('\'', stream) < 0)
4611 return EOF;
4612 } else if(c == '\n' && isset(CSHJUNKIEQUOTES)) {
4613 if(fputc('\\', stream) < 0)
4614 return EOF;
4616 if(fputc(c, stream) < 0)
4617 return EOF;
4619 if(fputc('\'', stream) < 0)
4620 return EOF;
4621 } else {
4622 /* use Bourne-style quoting, avoiding empty quoted strings */
4623 while(*s) {
4624 if (*s == Meta)
4625 c = *++s ^ 32;
4626 else
4627 c = *s;
4628 s++;
4629 if (c == '\'') {
4630 if(inquote) {
4631 if(fputc('\'', stream) < 0)
4632 return EOF;
4633 inquote=0;
4635 if(fputs("\\'", stream) < 0)
4636 return EOF;
4637 } else {
4638 if (!inquote) {
4639 if(fputc('\'', stream) < 0)
4640 return EOF;
4641 inquote=1;
4643 if(c == '\n' && isset(CSHJUNKIEQUOTES)) {
4644 if(fputc('\\', stream) < 0)
4645 return EOF;
4647 if(fputc(c, stream) < 0)
4648 return EOF;
4651 if (inquote) {
4652 if(fputc('\'', stream) < 0)
4653 return EOF;
4656 return 0;
4659 /* Double-quote a metafied string. */
4661 /**/
4662 mod_export char *
4663 dquotedztrdup(char const *s)
4665 int len = strlen(s) * 4 + 2;
4666 char *buf = zalloc(len);
4667 char *p = buf, *ret;
4669 if(isset(CSHJUNKIEQUOTES)) {
4670 int inquote = 0;
4672 while(*s) {
4673 int c = *s++;
4675 if (c == Meta)
4676 c = *s++ ^ 32;
4677 switch(c) {
4678 case '"':
4679 case '$':
4680 case '`':
4681 if(inquote) {
4682 *p++ = '"';
4683 inquote = 0;
4685 *p++ = '\\';
4686 *p++ = c;
4687 break;
4688 default:
4689 if(!inquote) {
4690 *p++ = '"';
4691 inquote = 1;
4693 if(c == '\n')
4694 *p++ = '\\';
4695 *p++ = c;
4696 break;
4699 if (inquote)
4700 *p++ = '"';
4701 } else {
4702 int pending = 0;
4704 *p++ = '"';
4705 while(*s) {
4706 int c = *s++;
4708 if (c == Meta)
4709 c = *s++ ^ 32;
4710 switch(c) {
4711 case '\\':
4712 if(pending)
4713 *p++ = '\\';
4714 *p++ = '\\';
4715 pending = 1;
4716 break;
4717 case '"':
4718 case '$':
4719 case '`':
4720 if(pending)
4721 *p++ = '\\';
4722 *p++ = '\\';
4723 /* FALL THROUGH */
4724 default:
4725 *p++ = c;
4726 pending = 0;
4727 break;
4730 if(pending)
4731 *p++ = '\\';
4732 *p++ = '"';
4734 ret = metafy(buf, p - buf, META_DUP);
4735 zfree(buf, len);
4736 return ret;
4739 /* Unmetafy and output a string, double quoting it in its entirety. */
4741 #if 0 /**/
4743 dquotedzputs(char const *s, FILE *stream)
4745 char *d = dquotedztrdup(s);
4746 int ret = zputs(d, stream);
4748 zsfree(d);
4749 return ret;
4751 #endif
4753 # if defined(HAVE_NL_LANGINFO) && defined(CODESET) && !defined(__STDC_ISO_10646__)
4754 /* Convert a character from UCS4 encoding to UTF-8 */
4756 static size_t
4757 ucs4toutf8(char *dest, unsigned int wval)
4759 size_t len;
4761 if (wval < 0x80)
4762 len = 1;
4763 else if (wval < 0x800)
4764 len = 2;
4765 else if (wval < 0x10000)
4766 len = 3;
4767 else if (wval < 0x200000)
4768 len = 4;
4769 else if (wval < 0x4000000)
4770 len = 5;
4771 else
4772 len = 6;
4774 switch (len) { /* falls through except to the last case */
4775 case 6: dest[5] = (wval & 0x3f) | 0x80; wval >>= 6;
4776 case 5: dest[4] = (wval & 0x3f) | 0x80; wval >>= 6;
4777 case 4: dest[3] = (wval & 0x3f) | 0x80; wval >>= 6;
4778 case 3: dest[2] = (wval & 0x3f) | 0x80; wval >>= 6;
4779 case 2: dest[1] = (wval & 0x3f) | 0x80; wval >>= 6;
4780 *dest = wval | ((0xfc << (6 - len)) & 0xfc);
4781 break;
4782 case 1: *dest = wval;
4785 return len;
4787 #endif
4791 * The following only occurs once or twice in the code, but in different
4792 * places depending how character set conversion is implemented.
4794 #define CHARSET_FAILED() \
4795 if (how & GETKEY_DOLLAR_QUOTE) { \
4796 while ((*tdest++ = *++s)) { \
4797 if (how & GETKEY_UPDATE_OFFSET) { \
4798 if (s - sstart > *misc) \
4799 (*misc)++; \
4801 if (*s == Snull) { \
4802 *len = (s - sstart) + 1; \
4803 *tdest = '\0'; \
4804 return buf; \
4807 *len = tdest - buf; \
4808 return buf; \
4810 *t = '\0'; \
4811 *len = t - buf; \
4812 return buf
4815 * Decode a key string, turning it into the literal characters.
4816 * The value returned is a newly allocated string from the heap.
4818 * The length is returned in *len. This is usually the length of
4819 * the final unmetafied string. The exception is the case of
4820 * a complete GETKEY_DOLLAR_QUOTE conversion where *len is the
4821 * length of the input string which has been used (up to and including
4822 * the terminating single quote); as the final string is metafied and
4823 * NULL-terminated its length is not required. If both GETKEY_DOLLAR_QUOTE
4824 * and GETKEY_UPDATE_OFFSET are present in "how", the string is not
4825 * expected to be terminated (this is used in completion to parse
4826 * a partial $'...'-quoted string) and the length passed back is
4827 * that of the converted string. Note in both cases that this is a length
4828 * in bytes (i.e. the same as given by a raw pointer difference), not
4829 * characters, which may occupy multiple bytes.
4831 * how is a set of bits from the GETKEY_ values defined in zsh.h;
4832 * not all combinations of bits are useful. Callers will typically
4833 * use one of the GETKEYS_ values which define sets of bits.
4834 * Note, for example that:
4835 * - GETKEY_SINGLE_CHAR must not be combined with GETKEY_DOLLAR_QUOTE.
4836 * - GETKEY_UPDATE_OFFSET is only allowed if GETKEY_DOLLAR_QUOTE is
4837 * also present.
4839 * *misc is used for various purposes:
4840 * - If GETKEY_BACKSLASH_MINUS is set, it indicates the presence
4841 * of \- in the input.
4842 * - If GETKEY_BACKSLASH_C is set, it indicates the presence
4843 * of \c in the input.
4844 * - If GETKEY_UPDATE_OFFSET is set, it is set on input to some
4845 * mystical completion offset and is updated to a new offset based
4846 * on the converted characters. All Hail the Completion System
4847 * [makes the mystic completion system runic sign in the air].
4849 * The return value is unmetafied unless GETKEY_DOLLAR_QUOTE is
4850 * in use.
4853 /**/
4854 mod_export char *
4855 getkeystring(char *s, int *len, int how, int *misc)
4857 char *buf, tmp[1];
4858 char *t, *tdest = NULL, *u = NULL, *sstart = s, *tbuf = NULL;
4859 char svchar = '\0';
4860 int meta = 0, control = 0;
4861 int i;
4862 #if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
4863 wint_t wval;
4864 int count;
4865 #else
4866 unsigned int wval;
4867 # if defined(HAVE_NL_LANGINFO) && defined(CODESET)
4868 # if defined(HAVE_ICONV)
4869 iconv_t cd;
4870 char inbuf[4];
4871 size_t inbytes, outbytes;
4872 # endif
4873 size_t count;
4874 # endif
4875 #endif
4877 DPUTS((how & GETKEY_UPDATE_OFFSET) &&
4878 (how & ~(GETKEYS_DOLLARS_QUOTE|GETKEY_UPDATE_OFFSET)),
4879 "BUG: offset updating in getkeystring only supported with $'.");
4880 DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR)) ==
4881 (GETKEY_DOLLAR_QUOTE|GETKEY_SINGLE_CHAR),
4882 "BUG: incompatible options in getkeystring");
4884 if (how & GETKEY_SINGLE_CHAR)
4885 t = buf = tmp;
4886 else {
4887 /* Length including terminating NULL */
4888 int maxlen = 1;
4890 * We're not necessarily guaranteed the output string will
4891 * be no longer than the input with \u and \U when output
4892 * characters need to be metafied. As this is the only
4893 * case where the string can get longer (?I think),
4894 * include it in the allocation length here but don't
4895 * bother taking account of other factors.
4897 for (t = s; *t; t++) {
4898 if (*t == '\\') {
4899 if (!t[1]) {
4900 maxlen++;
4901 break;
4903 if (t[1] == 'u' || t[1] == 'U')
4904 maxlen += MB_CUR_MAX * 2;
4905 else
4906 maxlen += 2;
4907 /* skip the backslash and the following character */
4908 t++;
4909 } else
4910 maxlen++;
4912 if (how & GETKEY_DOLLAR_QUOTE) {
4914 * We're going to unmetafy into a new string, but
4915 * to get a proper metafied input we're going to metafy
4916 * into an intermediate buffer. This is necessary if we have
4917 * \u and \U's with multiple metafied bytes. We can't
4918 * simply remetafy the entire string because there may
4919 * be tokens (indeed, we know there are lexical nulls floating
4920 * around), so we have to be aware character by character
4921 * what we are converting.
4923 * In this case, buf is the final buffer (as usual),
4924 * but t points into a temporary buffer that just has
4925 * to be long enough to hold the result of one escape
4926 * code transformation. We count this is a full multibyte
4927 * character (MB_CUR_MAX) with every character metafied
4928 * (*2) plus a little bit of fuzz (for e.g. the odd backslash).
4930 buf = tdest = zhalloc(maxlen);
4931 t = tbuf = zhalloc(MB_CUR_MAX * 3 + 1);
4932 } else {
4933 t = buf = zhalloc(maxlen);
4936 for (; *s; s++) {
4937 if (*s == '\\' && s[1]) {
4938 int miscadded;
4939 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
4940 (*misc)--;
4941 miscadded = 1;
4942 } else
4943 miscadded = 0;
4944 switch (*++s) {
4945 case 'a':
4946 #ifdef __STDC__
4947 *t++ = '\a';
4948 #else
4949 *t++ = '\07';
4950 #endif
4951 break;
4952 case 'n':
4953 *t++ = '\n';
4954 break;
4955 case 'b':
4956 *t++ = '\b';
4957 break;
4958 case 't':
4959 *t++ = '\t';
4960 break;
4961 case 'v':
4962 *t++ = '\v';
4963 break;
4964 case 'f':
4965 *t++ = '\f';
4966 break;
4967 case 'r':
4968 *t++ = '\r';
4969 break;
4970 case 'E':
4971 if (!(how & GETKEY_EMACS)) {
4972 *t++ = '\\', s--;
4973 if (miscadded)
4974 (*misc)++;
4975 continue;
4977 /* FALL THROUGH */
4978 case 'e':
4979 *t++ = '\033';
4980 break;
4981 case 'M':
4982 /* HERE: GETKEY_UPDATE_OFFSET */
4983 if (how & GETKEY_EMACS) {
4984 if (s[1] == '-')
4985 s++;
4986 meta = 1 + control; /* preserve the order of ^ and meta */
4987 } else {
4988 if (miscadded)
4989 (*misc)++;
4990 *t++ = '\\', s--;
4992 continue;
4993 case 'C':
4994 /* HERE: GETKEY_UPDATE_OFFSET */
4995 if (how & GETKEY_EMACS) {
4996 if (s[1] == '-')
4997 s++;
4998 control = 1;
4999 } else {
5000 if (miscadded)
5001 (*misc)++;
5002 *t++ = '\\', s--;
5004 continue;
5005 case Meta:
5006 if (miscadded)
5007 (*misc)++;
5008 *t++ = '\\', s--;
5009 break;
5010 case '-':
5011 if (how & GETKEY_BACKSLASH_MINUS) {
5012 *misc = 1;
5013 break;
5015 goto def;
5016 case 'c':
5017 if (how & GETKEY_BACKSLASH_C) {
5018 *misc = 1;
5019 *t = '\0';
5020 *len = t - buf;
5021 return buf;
5023 goto def;
5024 case 'U':
5025 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
5026 (*misc) -= 4;
5027 /* FALLTHROUGH */
5028 case 'u':
5029 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc) {
5030 (*misc) -= 6; /* HERE don't really believe this */
5032 * We've now adjusted the offset for all the input
5033 * characters, so we need to add for each
5034 * byte of output below.
5037 wval = 0;
5038 for (i=(*s == 'u' ? 4 : 8); i>0; i--) {
5039 if (*++s && idigit(*s))
5040 wval = wval * 16 + (*s - '0');
5041 else if (*s && ((*s >= 'a' && *s <= 'f') ||
5042 (*s >= 'A' && *s <= 'F')))
5043 wval = wval * 16 + (*s & 0x1f) + 9;
5044 else {
5045 s--;
5046 break;
5049 if (how & GETKEY_SINGLE_CHAR) {
5050 *misc = wval;
5051 return s+1;
5053 #if defined(HAVE_WCHAR_H) && defined(HAVE_WCTOMB) && defined(__STDC_ISO_10646__)
5054 count = wctomb(t, (wchar_t)wval);
5055 if (count == -1) {
5056 zerr("character not in range");
5057 CHARSET_FAILED();
5059 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
5060 (*misc) += count;
5061 t += count;
5062 # else
5063 # if defined(HAVE_NL_LANGINFO) && defined(CODESET)
5064 if (!strcmp(nl_langinfo(CODESET), "UTF-8")) {
5065 count = ucs4toutf8(t, wval);
5066 t += count;
5067 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
5068 (*misc) += count;
5069 } else {
5070 # ifdef HAVE_ICONV
5071 ICONV_CONST char *inptr = inbuf;
5072 const char *codesetstr = nl_langinfo(CODESET);
5073 inbytes = 4;
5074 outbytes = 6;
5075 /* store value in big endian form */
5076 for (i=3;i>=0;i--) {
5077 inbuf[i] = wval & 0xff;
5078 wval >>= 8;
5082 * If the code set isn't handled, we'd better
5083 * assume it's US-ASCII rather than just failing
5084 * hopelessly. Solaris has a weird habit of
5085 * returning 646. This is handled by the
5086 * native iconv(), but not by GNU iconv; what's
5087 * more, some versions of the native iconv don't
5088 * handle standard names like ASCII.
5090 * This should only be a problem if there's a
5091 * mismatch between the NLS and the iconv in use,
5092 * which probably only means if libiconv is in use.
5093 * We checked at configure time if our libraries
5094 * pulled in _libiconv_version, which should be
5095 * a good test.
5097 * It shouldn't ever be NULL, but while we're
5098 * being paranoid...
5100 #ifdef ICONV_FROM_LIBICONV
5101 if (!codesetstr || !*codesetstr)
5102 codesetstr = "US-ASCII";
5103 #endif
5104 cd = iconv_open(codesetstr, "UCS-4BE");
5105 #ifdef ICONV_FROM_LIBICONV
5106 if (cd == (iconv_t)-1 && !strcmp(codesetstr, "646")) {
5107 codesetstr = "US-ASCII";
5108 cd = iconv_open(codesetstr, "UCS-4BE");
5110 #endif
5111 if (cd == (iconv_t)-1) {
5112 zerr("cannot do charset conversion (iconv failed)");
5113 CHARSET_FAILED();
5115 count = iconv(cd, &inptr, &inbytes, &t, &outbytes);
5116 iconv_close(cd);
5117 if (count == (size_t)-1) {
5118 zerr("character not in range");
5119 CHARSET_FAILED();
5121 if ((how & GETKEY_UPDATE_OFFSET) && s - sstart < *misc)
5122 (*misc) += count;
5123 # else
5124 zerr("cannot do charset conversion (iconv not available)");
5125 CHARSET_FAILED();
5126 # endif
5128 # else
5129 zerr("cannot do charset conversion (NLS not supported)");
5130 CHARSET_FAILED();
5131 # endif
5132 # endif
5133 if (how & GETKEY_DOLLAR_QUOTE) {
5134 char *t2;
5135 for (t2 = tbuf; t2 < t; t2++) {
5136 if (imeta(*t2)) {
5137 *tdest++ = Meta;
5138 *tdest++ = *t2 ^ 32;
5139 } else
5140 *tdest++ = *t2;
5142 /* reset temporary buffer after handling */
5143 t = tbuf;
5145 continue;
5146 case '\'':
5147 case '\\':
5148 if (how & GETKEY_DOLLAR_QUOTE) {
5150 * Usually \' and \\ will have the initial
5151 * \ turned into a Bnull, however that's not
5152 * necessarily the case when called from
5153 * completion.
5155 *t++ = *s;
5156 break;
5158 /* FALLTHROUGH */
5159 default:
5160 def:
5161 /* HERE: GETKEY_UPDATE_OFFSET? */
5162 if ((idigit(*s) && *s < '8') || *s == 'x') {
5163 if (!(how & GETKEY_OCTAL_ESC)) {
5164 if (*s == '0')
5165 s++;
5166 else if (*s != 'x') {
5167 *t++ = '\\', s--;
5168 continue;
5171 if (s[1] && s[2] && s[3]) {
5172 svchar = s[3];
5173 s[3] = '\0';
5174 u = s;
5176 *t++ = zstrtol(s + (*s == 'x'), &s,
5177 (*s == 'x') ? 16 : 8);
5178 if (svchar) {
5179 u[3] = svchar;
5180 svchar = '\0';
5182 s--;
5183 } else {
5184 if (!(how & GETKEY_EMACS) && *s != '\\') {
5185 if (miscadded)
5186 (*misc)++;
5187 *t++ = '\\';
5189 *t++ = *s;
5191 break;
5193 } else if ((how & GETKEY_DOLLAR_QUOTE) && *s == Snull) {
5194 /* return length to following character */
5195 *len = (s - sstart) + 1;
5196 *tdest = '\0';
5197 return buf;
5198 } else if (*s == '^' && !control && (how & GETKEY_CTRL) && s[1]) {
5199 control = 1;
5200 continue;
5201 #ifdef MULTIBYTE_SUPPORT
5202 } else if ((how & GETKEY_SINGLE_CHAR) &&
5203 isset(MULTIBYTE) && STOUC(*s) > 127) {
5204 wint_t wc;
5205 int len;
5206 len = mb_metacharlenconv(s, &wc);
5207 if (wc != WEOF) {
5208 *misc = (int)wc;
5209 return s + len;
5211 #endif
5213 } else if (*s == Meta)
5214 *t++ = *++s ^ 32;
5215 else {
5216 if (itok(*s)) {
5218 * We need to be quite careful here. We haven't
5219 * necessarily got an input stream with all tokens
5220 * removed, so the majority of tokens need passing
5221 * through untouched and without Meta handling.
5222 * However, me may need to handle tokenized
5223 * backslashes.
5225 if (meta || control) {
5227 * Presumably we should be using meta or control
5228 * on the character representing the token.
5230 * Special case: $'\M-\\' where the token is a Bnull.
5231 * This time we dump the Bnull since we're
5232 * replacing the whole thing. The lexer
5233 * doesn't know about the meta or control modifiers.
5235 if ((how & GETKEY_DOLLAR_QUOTE) && *s == Bnull)
5236 *t++ = *++s;
5237 else
5238 *t++ = ztokens[*s - Pound];
5239 } else if (how & GETKEY_DOLLAR_QUOTE) {
5241 * We don't want to metafy this, it's a real
5242 * token.
5244 *tdest++ = *s;
5245 if (*s == Bnull) {
5247 * Bnull is a backslash which quotes a couple
5248 * of special characters that always appear
5249 * literally next. See strquote handling
5250 * in gettokstr() in lex.c. We need
5251 * to retain the Bnull (as above) so that quote
5252 * handling in completion can tell where the
5253 * backslash was.
5255 *tdest++ = *++s;
5257 /* reset temporary buffer, now handled */
5258 t = tbuf;
5259 continue;
5260 } else
5261 *t++ = *s;
5262 } else
5263 *t++ = *s;
5265 if (meta == 2) {
5266 t[-1] |= 0x80;
5267 meta = 0;
5269 if (control) {
5270 if (t[-1] == '?')
5271 t[-1] = 0x7f;
5272 else
5273 t[-1] &= 0x9f;
5274 control = 0;
5276 if (meta) {
5277 t[-1] |= 0x80;
5278 meta = 0;
5280 if (how & GETKEY_DOLLAR_QUOTE) {
5281 char *t2;
5282 for (t2 = tbuf; t2 < t; t2++) {
5283 if (imeta(*t2)) {
5284 *tdest++ = Meta;
5285 *tdest++ = *t2 ^ 32;
5286 } else
5287 *tdest++ = *t2;
5290 * Reset use of temporary buffer.
5292 t = tbuf;
5294 if ((how & GETKEY_SINGLE_CHAR) && t != tmp) {
5295 *misc = STOUC(tmp[0]);
5296 return s + 1;
5300 * When called from completion, where we use GETKEY_UPDATE_OFFSET to
5301 * update the index into the metafied editor line, we don't necessarily
5302 * have the end of a $'...' quotation, else we should do.
5304 DPUTS((how & (GETKEY_DOLLAR_QUOTE|GETKEY_UPDATE_OFFSET)) ==
5305 GETKEY_DOLLAR_QUOTE, "BUG: unterminated $' substitution");
5306 *t = '\0';
5307 if (how & GETKEY_DOLLAR_QUOTE)
5308 *tdest = '\0';
5309 if (how & GETKEY_SINGLE_CHAR)
5310 *misc = 0;
5311 else
5312 *len = ((how & GETKEY_DOLLAR_QUOTE) ? tdest : t) - buf;
5313 return buf;
5316 /* Return non-zero if s is a prefix of t. */
5318 /**/
5319 mod_export int
5320 strpfx(const char *s, const char *t)
5322 while (*s && *s == *t)
5323 s++, t++;
5324 return !*s;
5327 /* Return non-zero if s is a suffix of t. */
5329 /**/
5330 mod_export int
5331 strsfx(char *s, char *t)
5333 int ls = strlen(s), lt = strlen(t);
5335 if (ls <= lt)
5336 return !strcmp(t + lt - ls, s);
5337 return 0;
5340 /**/
5341 static int
5342 upchdir(int n)
5344 char buf[PATH_MAX];
5345 char *s;
5346 int err = -1;
5348 while (n > 0) {
5349 for (s = buf; s < buf + PATH_MAX - 4 && n--; )
5350 *s++ = '.', *s++ = '.', *s++ = '/';
5351 s[-1] = '\0';
5352 if (chdir(buf))
5353 return err;
5354 err = -2;
5356 return 0;
5359 /* Change directory, without following symlinks. Returns 0 on success, -1 *
5360 * on failure. Sets errno to ENOTDIR if any symlinks are encountered. If *
5361 * fchdir() fails, or the current directory is unreadable, we might end up *
5362 * in an unwanted directory in case of failure. */
5364 /**/
5365 mod_export int
5366 lchdir(char const *path, struct dirsav *d, int hard)
5368 char const *pptr;
5369 int level;
5370 struct stat st1;
5371 struct dirsav ds;
5372 #ifdef HAVE_LSTAT
5373 char buf[PATH_MAX + 1], *ptr;
5374 int err;
5375 struct stat st2;
5376 #endif
5378 if (!d) {
5379 ds.ino = ds.dev = 0;
5380 ds.dirname = NULL;
5381 ds.dirfd = -1;
5382 d = &ds;
5384 #ifdef HAVE_LSTAT
5385 if ((*path == '/' || !hard) &&
5386 (d != &ds || hard)){
5387 #else
5388 if (*path == '/') {
5389 #endif
5390 level = -1;
5391 #ifndef HAVE_FCHDIR
5392 if (!d->dirname)
5393 zgetdir(d);
5394 #endif
5395 } else {
5396 level = 0;
5397 if (!d->dev && !d->ino) {
5398 stat(".", &st1);
5399 d->dev = st1.st_dev;
5400 d->ino = st1.st_ino;
5403 #ifdef HAVE_FCHDIR
5404 if (d->dirfd < 0 && (d->dirfd = open(".", O_RDONLY | O_NOCTTY)) < 0 &&
5405 zgetdir(d) && *d->dirname != '/')
5406 d->dirfd = open("..", O_RDONLY | O_NOCTTY);
5407 #endif
5409 #ifdef HAVE_LSTAT
5410 if (!hard)
5411 #endif
5413 if (d != &ds) {
5414 for (pptr = path; *pptr; level++) {
5415 while (*pptr && *pptr++ != '/');
5416 while (*pptr == '/')
5417 pptr++;
5419 d->level = level;
5421 return zchdir((char *) path);
5423 #ifdef HAVE_LSTAT
5424 if (*path == '/')
5425 if (chdir("/") < 0)
5426 zwarn("failed to chdir(/): %e", errno);
5427 for(;;) {
5428 while(*path == '/')
5429 path++;
5430 if(!*path) {
5431 if (d == &ds) {
5432 zsfree(ds.dirname);
5433 if (ds.dirfd >=0)
5434 close(ds.dirfd);
5435 } else
5436 d->level = level;
5437 return 0;
5439 for(pptr = path; *++pptr && *pptr != '/'; ) ;
5440 if(pptr - path > PATH_MAX) {
5441 err = ENAMETOOLONG;
5442 break;
5444 for(ptr = buf; path != pptr; )
5445 *ptr++ = *path++;
5446 *ptr = 0;
5447 if(lstat(buf, &st1)) {
5448 err = errno;
5449 break;
5451 if(!S_ISDIR(st1.st_mode)) {
5452 err = ENOTDIR;
5453 break;
5455 if(chdir(buf)) {
5456 err = errno;
5457 break;
5459 if (level >= 0)
5460 level++;
5461 if(lstat(".", &st2)) {
5462 err = errno;
5463 break;
5465 if(st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) {
5466 err = ENOTDIR;
5467 break;
5470 if (restoredir(d)) {
5471 if (d == &ds) {
5472 zsfree(ds.dirname);
5473 if (ds.dirfd >=0)
5474 close(ds.dirfd);
5476 errno = err;
5477 return -2;
5479 if (d == &ds) {
5480 zsfree(ds.dirname);
5481 if (ds.dirfd >=0)
5482 close(ds.dirfd);
5484 errno = err;
5485 return -1;
5486 #endif /* HAVE_LSTAT */
5489 /**/
5490 mod_export int
5491 restoredir(struct dirsav *d)
5493 int err = 0;
5494 struct stat sbuf;
5496 if (d->dirname && *d->dirname == '/')
5497 return chdir(d->dirname);
5498 #ifdef HAVE_FCHDIR
5499 if (d->dirfd >= 0) {
5500 if (!fchdir(d->dirfd)) {
5501 if (!d->dirname) {
5502 return 0;
5503 } else if (chdir(d->dirname)) {
5504 close(d->dirfd);
5505 d->dirfd = -1;
5506 err = -2;
5508 } else {
5509 close(d->dirfd);
5510 d->dirfd = err = -1;
5512 } else
5513 #endif
5514 if (d->level > 0)
5515 err = upchdir(d->level);
5516 else if (d->level < 0)
5517 err = -1;
5518 if (d->dev || d->ino) {
5519 stat(".", &sbuf);
5520 if (sbuf.st_ino != d->ino || sbuf.st_dev != d->dev)
5521 err = -2;
5523 return err;
5527 /* Check whether the shell is running with privileges in effect. *
5528 * This is the case if EITHER the euid is zero, OR (if the system *
5529 * supports POSIX.1e (POSIX.6) capability sets) the process' *
5530 * Effective or Inheritable capability sets are non-empty. */
5532 /**/
5534 privasserted(void)
5536 if(!geteuid())
5537 return 1;
5538 #ifdef HAVE_CAP_GET_PROC
5540 cap_t caps = cap_get_proc();
5541 if(caps) {
5542 /* POSIX doesn't define a way to test whether a capability set *
5543 * is empty or not. Typical. I hope this is conforming... */
5544 cap_flag_value_t val;
5545 cap_value_t n;
5546 for(n = 0; !cap_get_flag(caps, n, CAP_EFFECTIVE, &val); n++)
5547 if(val) {
5548 cap_free(caps);
5549 return 1;
5551 cap_free(caps);
5554 #endif /* HAVE_CAP_GET_PROC */
5555 return 0;
5558 /**/
5559 mod_export int
5560 mode_to_octal(mode_t mode)
5562 int m = 0;
5564 if(mode & S_ISUID)
5565 m |= 04000;
5566 if(mode & S_ISGID)
5567 m |= 02000;
5568 if(mode & S_ISVTX)
5569 m |= 01000;
5570 if(mode & S_IRUSR)
5571 m |= 00400;
5572 if(mode & S_IWUSR)
5573 m |= 00200;
5574 if(mode & S_IXUSR)
5575 m |= 00100;
5576 if(mode & S_IRGRP)
5577 m |= 00040;
5578 if(mode & S_IWGRP)
5579 m |= 00020;
5580 if(mode & S_IXGRP)
5581 m |= 00010;
5582 if(mode & S_IROTH)
5583 m |= 00004;
5584 if(mode & S_IWOTH)
5585 m |= 00002;
5586 if(mode & S_IXOTH)
5587 m |= 00001;
5588 return m;
5591 #ifdef MAILDIR_SUPPORT
5593 * Stat a file. If it's a maildir, check all messages
5594 * in the maildir and present the grand total as a file.
5595 * The fields in the 'struct stat' are from the mail directory.
5596 * The following fields are emulated:
5598 * st_nlink always 1
5599 * st_size total number of bytes in all files
5600 * st_blocks total number of messages
5601 * st_atime access time of newest file in maildir
5602 * st_mtime modify time of newest file in maildir
5603 * st_mode S_IFDIR changed to S_IFREG
5605 * This is good enough for most mail-checking applications.
5608 /**/
5610 mailstat(char *path, struct stat *st)
5612 DIR *dd;
5613 struct dirent *fn;
5614 struct stat st_ret, st_tmp;
5615 static struct stat st_ret_last;
5616 char *dir, *file = 0;
5617 int i;
5618 time_t atime = 0, mtime = 0;
5619 size_t plen = strlen(path), dlen;
5621 /* First see if it's a directory. */
5622 if ((i = stat(path, st)) != 0 || !S_ISDIR(st->st_mode))
5623 return i;
5625 st_ret = *st;
5626 st_ret.st_nlink = 1;
5627 st_ret.st_size = 0;
5628 st_ret.st_blocks = 0;
5629 st_ret.st_mode &= ~S_IFDIR;
5630 st_ret.st_mode |= S_IFREG;
5632 /* See if cur/ is present */
5633 dir = appstr(ztrdup(path), "/cur");
5634 if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
5635 st_ret.st_atime = st_tmp.st_atime;
5637 /* See if tmp/ is present */
5638 dir[plen] = 0;
5639 dir = appstr(dir, "/tmp");
5640 if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
5641 st_ret.st_mtime = st_tmp.st_mtime;
5643 /* And new/ */
5644 dir[plen] = 0;
5645 dir = appstr(dir, "/new");
5646 if (stat(dir, &st_tmp) || !S_ISDIR(st_tmp.st_mode)) return 0;
5647 st_ret.st_mtime = st_tmp.st_mtime;
5649 #if THERE_IS_EXACTLY_ONE_MAILDIR_IN_MAILPATH
5651 static struct stat st_new_last;
5652 /* Optimization - if new/ didn't change, nothing else did. */
5653 if (st_tmp.st_dev == st_new_last.st_dev &&
5654 st_tmp.st_ino == st_new_last.st_ino &&
5655 st_tmp.st_atime == st_new_last.st_atime &&
5656 st_tmp.st_mtime == st_new_last.st_mtime) {
5657 *st = st_ret_last;
5658 return 0;
5660 st_new_last = st_tmp;
5662 #endif
5664 /* Loop over new/ and cur/ */
5665 for (i = 0; i < 2; i++) {
5666 dir[plen] = 0;
5667 dir = appstr(dir, i ? "/cur" : "/new");
5668 if ((dd = opendir(dir)) == NULL) {
5669 zsfree(file);
5670 zsfree(dir);
5671 return 0;
5673 dlen = strlen(dir) + 1; /* include the "/" */
5674 while ((fn = readdir(dd)) != NULL) {
5675 if (fn->d_name[0] == '.')
5676 continue;
5677 if (file) {
5678 file[dlen] = 0;
5679 file = appstr(file, fn->d_name);
5680 } else {
5681 file = tricat(dir, "/", fn->d_name);
5683 if (stat(file, &st_tmp) != 0)
5684 continue;
5685 st_ret.st_size += st_tmp.st_size;
5686 st_ret.st_blocks++;
5687 if (st_tmp.st_atime != st_tmp.st_mtime &&
5688 st_tmp.st_atime > atime)
5689 atime = st_tmp.st_atime;
5690 if (st_tmp.st_mtime > mtime)
5691 mtime = st_tmp.st_mtime;
5693 closedir(dd);
5695 zsfree(file);
5696 zsfree(dir);
5698 if (atime) st_ret.st_atime = atime;
5699 if (mtime) st_ret.st_mtime = mtime;
5701 *st = st_ret_last = st_ret;
5702 return 0;
5704 #endif