histrap.c revision 03ebf06f4e1112a0e9533b93062d169232c4cbfe
15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: history.c,v 1.39 2010/05/19 17:36:08 jasper Exp $	*/
25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*	$OpenBSD: trap.c,v 1.23 2010/05/19 17:36:08 jasper Exp $	*/
35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Thorsten Glaser <tg@mirbsd.org>
75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices
95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission
105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un-
115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify,
125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence.
135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor
165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event
175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect,
185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out
195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such
205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out
215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended.
225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h"
2503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SYS_FILE_H
265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <sys/file.h>
275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.111 2011/09/07 15:24:16 tg Exp $");
305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*-
325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * MirOS: This is the default mapping type, and need not be specified.
335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * IRIX doesn't have this constant.
345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MAP_FILE
365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define MAP_FILE	0
375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTrap sigtraps[NSIG + 1];
405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct sigaction Sigact_ign;
415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hist_count_lines(unsigned char *, int);
445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hist_shrink(unsigned char *, int);
455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic unsigned char *hist_skip_back(unsigned char *,int *,int);
465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void histload(Source *, unsigned char *, int);
475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void histinsert(Source *, int, const char *);
485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void writehistfile(int, char *);
495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int sprinkle(int);
505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hist_execute(char *);
535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hist_replace(char **, const char *, const char *, bool);
545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **hist_get(const char *, bool, bool);
555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **hist_get_oldest(void);
565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void histbackup(void);
575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **current;		/* current position in history[] */
595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hstarted;		/* set after hist_init() called */
605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Source *hist_source;
615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* current history file: name, fd, size */
6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic char *hname;
655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int histfd;
6603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic size_t hsize;
675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char Tnot_in_history[] = "not in history";
7003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define Thistory (Tnot_in_history + 7)
7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_fc(const char **wp)
745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct shf *shf;
765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct temp *tf;
775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *p;
785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *editor = NULL;
795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool gflag = false, lflag = false, nflag = false, rflag = false,
805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    sflag = false;
815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int optc;
825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *first = NULL, *last = NULL;
835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **hfirst, **hlast, **hp;
845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!Flag(FTALKING_I)) {
8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("history %ss not available", Tfunction);
875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while ((optc = ksh_getopt(wp, &builtin_opt,
915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    "e:glnrs0,1,2,3,4,5,6,7,8,9,")) != -1)
925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (optc) {
9303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'e':
955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p = builtin_opt.optarg;
965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (ksh_isdash(p))
975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				sflag = true;
985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				size_t len = strlen(p);
10003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
10103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* almost certainly not overflowing */
1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				editor = alloc(len + 4, ATEMP);
1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				memcpy(editor, p, len);
1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				memcpy(editor + len, " $_", 4);
1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
10703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
10803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* non-AT&T ksh */
10903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 'g':
1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			gflag = true;
1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'l':
1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lflag = true;
1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
11603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'n':
1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			nflag = true;
1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case 'r':
1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rflag = true;
1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* POSIX version of -e - */
12603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		case 's':
1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sflag = true;
1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* kludge city - accept -num as -- -num (kind of) */
1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '0': case '1': case '2': case '3': case '4':
1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '5': case '6': case '7': case '8': case '9':
1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p = shf_smprintf("-%c%s",
1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					optc, builtin_opt.optarg);
1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!first)
1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				first = p;
1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else if (!last)
1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				last = p;
1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				bi_errorf("too many arguments");
1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				return (1);
1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case '?':
1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	wp += builtin_opt.optind;
1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Substitute and execute command */
1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (sflag) {
1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *pat = NULL, *rep = NULL;
1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (editor || lflag || nflag || rflag) {
1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("can't use -e, -l, -n, -r with -s (-e -)");
1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Check for pattern replacement argument */
1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*wp && **wp && (p = cstrchr(*wp + 1, '='))) {
1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			strdupx(pat, *wp, ATEMP);
1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			rep = pat + (p - *wp);
1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*rep++ = '\0';
1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* Check for search prefix */
1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!first && (first = *wp))
1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			wp++;
1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (last || *wp) {
1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			bi_errorf("too many arguments");
1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hp = first ? hist_get(first, false, false) :
1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    hist_get_newest(false);
1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!hp)
1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (hist_replace(hp, pat, rep, gflag));
1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (editor && (lflag || nflag)) {
1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("can't use -l, -n with -e");
1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!first && (first = *wp))
1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!last && (last = *wp))
1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		wp++;
1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (*wp) {
1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("too many arguments");
1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!first) {
1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hfirst = lflag ? hist_get("-16", true, true) :
1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    hist_get_newest(false);
1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!hfirst)
1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* can't fail if hfirst didn't fail */
2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hlast = hist_get_newest(false);
2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/*
20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * POSIX says not an error if first/last out of bounds
20403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * when range is specified; AT&T ksh and pdksh allow out
20503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		 * of bounds for -l as well.
2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
20703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hfirst = hist_get(first, tobool(lflag || last), lflag);
2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!hfirst)
2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hlast = last ? hist_get(last, true, lflag) :
2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (lflag ? hist_get_newest(false) : hfirst);
2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!hlast)
2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (hfirst > hlast) {
2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char **temp;
2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		temp = hfirst; hfirst = hlast; hlast = temp;
21903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* POSIX */
22003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		rflag = !rflag;
2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* List history */
2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (lflag) {
2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *s, *t;
2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (hp = rflag ? hlast : hfirst;
2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) {
2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (!nflag)
2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_fprintf(shl_stdout, "%d",
2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				    hist_source->line - (int)(histptr - hp));
2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_putc('\t', shl_stdout);
2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* print multi-line commands correctly */
2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			s = *hp;
2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((t = strchr(s, '\n'))) {
2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*t = '\0';
2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				shf_fprintf(shl_stdout, "%s\n\t", s);
2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				*t++ = '\n';
2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				s = t;
2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_fprintf(shl_stdout, "%s\n", s);
2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_flush(shl_stdout);
2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Run editor on selected lines, then run resulting commands */
2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps);
2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(shf = tf->shf)) {
25103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("can't %s temporary file %s: %s",
25203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    "create", tf->name, strerror(errno));
2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (hp = rflag ? hlast : hfirst;
2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1)
2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_fprintf(shf, "%s\n", *hp);
2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (shf_close(shf) == EOF) {
25903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		bi_errorf("can't %s temporary file %s: %s",
26003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		    "write", tf->name, strerror(errno));
2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Ignore setstr errors here (arbitrary) */
2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setstr(local("_", false), tf->name, KSH_RETURN_ERROR);
2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* XXX: source should not get trashed by this.. */
2685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{
2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Source *sold = source;
2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int ret;
2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ret = command(editor ? editor : "${FCEDIT:-/bin/ed} $_", 0);
2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		source = sold;
2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ret)
2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (ret);
2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{
2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		struct stat statb;
2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XString xs;
2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *xp;
2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int n;
2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(shf = shf_open(tf->name, O_RDONLY, 0, 0))) {
28503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("can't %s temporary file %s: %s",
28603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "open", tf->name, strerror(errno));
2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (stat(tf->name, &statb) < 0)
29103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			n = 128;
29203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		else if (statb.st_size > (1024 * 1048576)) {
29303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s %s too large: %lu", Thistory,
29403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "file", (unsigned long)statb.st_size);
29503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			goto errout;
29603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		} else
29703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			n = statb.st_size + 1;
2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xinit(xs, xp, n, hist_source->areap);
2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) {
3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp += n;
3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (Xnleft(xs, xp) <= 0)
3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				XcheckN(xs, xp, Xlength(xs, xp));
3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (n < 0) {
30503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("can't %s temporary file %s: %s",
30603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			    "read", tf->name, strerror(shf_errno(shf)));
30703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errout:
3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			shf_close(shf);
3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		shf_close(shf);
3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*xp = '\0';
3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strip_nuls(Xstring(xs, xp), Xlength(xs, xp));
3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (hist_execute(Xstring(xs, xp)));
3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Save cmd in history, execute cmd (cmd gets trashed) */
3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
3205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_execute(char *cmd)
3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Source *sold;
3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int ret;
3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *p, *q;
3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	histbackup();
3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = cmd; p; p = q) {
3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((q = strchr(p, '\n'))) {
33003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* kill the newline */
33103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			*q++ = '\0';
33203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			if (!*q)
33303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				/* ignore trailing newline */
3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				q = NULL;
3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsave(&hist_source->line, p, true, true);
3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
33803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* POSIX doesn't say this is done... */
33903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		shellf("%s\n", p);
34003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (q)
34103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* restore \n (trailing \n not restored) */
3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			q[-1] = '\n';
3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
34503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/*-
3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Commands are executed here instead of pushing them onto the
3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * input 'cause POSIX says the redirection and variable assignments
3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * in
3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	X=y fc -e - 42 2> /dev/null
3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * are to effect the repeated commands environment.
3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* XXX: source should not get trashed by this.. */
3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sold = source;
3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	ret = command(cmd, 0);
3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	source = sold;
3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (ret);
3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_replace(char **hp, const char *pat, const char *rep, bool globr)
3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *line;
3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!pat)
3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(line, *hp, ATEMP);
3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else {
3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *s, *s1;
36803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		size_t pat_len = strlen(pat);
36903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		size_t rep_len = strlen(rep);
37003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		size_t len;
3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XString xs;
3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		char *xp;
3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bool any_subst = false;
3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		Xinit(xs, xp, 128, ATEMP);
3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (s = *hp; (s1 = strstr(s, pat)) && (!any_subst || globr);
3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    s = s1 + pat_len) {
3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			any_subst = true;
3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			len = s1 - s;
3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			XcheckN(xs, xp, len + rep_len);
38103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/*; first part */
38203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			memcpy(xp, s, len);
3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp += len;
38403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			/* replacement */
38503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			memcpy(xp, rep, rep_len);
3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			xp += rep_len;
3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!any_subst) {
38903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("bad substitution");
3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (1);
3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		len = strlen(s) + 1;
3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		XcheckN(xs, xp, len);
3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		memcpy(xp, s, len);
3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		xp += len;
3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		line = Xclose(xs, xp);
3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (hist_execute(line));
3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * get pointer to history given pattern
4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * pattern is a number or string
4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **
4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get(const char *str, bool approx, bool allow_cur)
4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **hp = NULL;
4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n;
4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (getn(str, &n)) {
4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hp = histptr + (n < 0 ? n : (n - hist_source->line));
4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((ptrdiff_t)hp < (ptrdiff_t)history) {
4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (approx)
4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hp = hist_get_oldest();
4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
41703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", str, Tnot_in_history);
4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hp = NULL;
4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) {
4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (approx)
4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hp = hist_get_newest(allow_cur);
4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
42403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				bi_errorf("%s: %s", str, Tnot_in_history);
4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hp = NULL;
4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else if (!allow_cur && hp == histptr) {
42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", str, "invalid range");
4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hp = NULL;
4305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int anchored = *str == '?' ? (++str, 0) : 1;
4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* the -1 is to avoid the current fc command */
4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0)
43603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bi_errorf("%s: %s", str, Tnot_in_history);
4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hp = &history[n];
4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (hp);
4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Return a pointer to the newest command in the history */
4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar **
4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get_newest(bool allow_cur)
4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histptr < history || (!allow_cur && histptr == history)) {
4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("no history (yet)");
4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (allow_cur ? histptr : histptr - 1);
4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Return a pointer to the oldest command in the history */
4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **
4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get_oldest(void)
4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histptr <= history) {
4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bi_errorf("no history (yet)");
4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (NULL);
4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (history);
4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
46503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*
46603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Back up over last histsave
46703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */
4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistbackup(void)
4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static int last_line = -1;
4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histptr >= history && last_line != hist_source->line) {
4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hist_source->line--;
4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(*histptr, APERM);
4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histptr--;
4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		last_line = hist_source->line;
4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Return the current position.
4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar **
4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistpos(void)
4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (current);
4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistnum(int n)
4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int last = histptr - history;
4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (n < 0 || n >= last) {
4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		current = histptr;
4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (last);
4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else {
4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		current = &history[n];
5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (n);
5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This will become unnecessary if hist_get is modified to allow
5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * searching from positions other than the end, and in either
5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direction.
5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufindhist(int start, int fwd, const char *str, int anchored)
5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
51203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char **hp;
51303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int maxhist = histptr - history;
51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int incr = fwd ? 1 : -1;
51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	size_t len = strlen(str);
5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (start < 0 || start >= maxhist)
5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		start = maxhist;
5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hp = &history[start];
5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (; hp >= history && hp <= histptr; hp += incr)
5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((anchored && strncmp(*hp, str, len) == 0) ||
5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (!anchored && strstr(*hp, str)))
5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (hp - history);
5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (-1);
5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	set history
5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	this means reallocating the dataspace
5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusethistsize(int n)
5355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (n > 0 && n != histsize) {
5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int cursize = histptr - history;
5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* save most recent history */
5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (n < cursize) {
5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			memmove(history, histptr - n, n * sizeof(char *));
5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cursize = n;
5435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		history = aresize2(history, n, sizeof(char *), APERM);
5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsize = n;
5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histptr = history + cursize;
5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	set history file
5555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	This can mean reloading/resetting/starting history file
5565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	maintenance
5575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
5595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusethistfile(const char *name)
5605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* if not started then nothing to do */
5625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (hstarted == 0)
5635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* if the name is the same as the name we have */
5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (hname && strcmp(hname, name) == 0)
5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * its a new name - possibly
5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histfd) {
5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* yes the file is open */
5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(void)close(histfd);
5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histfd = 0;
5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hsize = 0;
5775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(hname, APERM);
5785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hname = NULL;
5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* let's reset the history */
5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histptr = history - 1;
5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hist_source->line = 0;
5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hist_init(hist_source);
5855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
5865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	initialise the history vector
5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinit_histvec(void)
5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (history == (char **)NULL) {
5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histsize = HISTORYSIZE;
59603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		history = alloc2(histsize, sizeof(char *), APERM);
5975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histptr = history - 1;
5985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
5995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
6035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Routines added by Peter Collinson BSDI(Europe)/Hillside Systems to
6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	a) permit HISTSIZE to control number of lines of history stored
6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	b) maintain a physical history file
6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	It turns out that there is a lot of ghastly hackery here
6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* do not save command in history but possibly sync */
6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubool
6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistsync(void)
6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	bool changed = false;
6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histfd) {
6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int lno = hist_source->line;
6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hist_source->line++;
6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		writehistfile(0, NULL);
6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hist_source->line--;
6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (lno != hist_source->line)
6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			changed = true;
6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (changed);
6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * save command in history
6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups)
6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **hp;
6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *c, *cp;
6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	strdupx(c, cmd, APERM);
6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((cp = strchr(c, '\n')) != NULL)
6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		*cp = '\0';
6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ignoredups && !strcmp(c, *histptr)
6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY
6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    && !histsync()
6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    ) {
6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(c, APERM);
6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	++*lnp;
6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histfd && dowrite)
6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		writehistfile(*lnp, c);
6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hp = histptr;
6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
66203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (++hp >= history + histsize) {
66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* remove oldest command */
6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(*history, APERM);
6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (hp = history; hp < history + histsize - 1; hp++)
6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hp[0] = hp[1];
6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	*hp = c;
6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	histptr = hp;
6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
6735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Write history data to a file nominated by HISTFILE
6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	if HISTFILE is unset then history still happens, but
6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	the data is not written to a file
6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	All copies of ksh looking at the file will maintain the
6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	same history. This is ksh behaviour.
6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *
6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	This stuff uses mmap()
6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	if your system ain't got it - then you'll have to undef HISTORYFILE
6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
68303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*-
6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Open a history file
6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Format is:
6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Bytes 1, 2:
6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *		HMAGIC - just to check that we are dealing with
6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *		the correct object
6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Then follows a number of stored commands
6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Each command is
6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	<command byte><command number(4 bytes)><bytes><null>
6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define HMAGIC1		0xab
6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define HMAGIC2		0xcd
6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define COMMAND		0xff
6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_init(Source *s)
6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char *base;
7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int lines, fd, rv = 0;
70303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	off_t hfsize;
7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (Flag(FTALKING) == 0)
7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hstarted = 1;
7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hist_source = s;
7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((hname = str_val(global("HISTFILE"))) == NULL)
7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	strdupx(hname, hname, APERM);
7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru retry:
7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* we have a file and are interactive */
7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((fd = open(hname, O_RDWR|O_CREAT|O_APPEND, 0600)) < 0)
7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	histfd = savefd(fd);
7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (histfd != fd)
7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		close(fd);
7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)flock(histfd, LOCK_EX);
7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	hfsize = lseek(histfd, (off_t)0, SEEK_END);
73003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	hsize = 1024 * 1048576;
73103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hfsize < (off_t)hsize)
73203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hsize = (size_t)hfsize;
7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (hsize == 0) {
7355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/* add magic */
7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (sprinkle(histfd)) {
7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hist_finish();
7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return;
7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (hsize > 0) {
7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * we have some data
7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		base = (void *)mmap(NULL, hsize, PROT_READ,
7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    MAP_FILE | MAP_PRIVATE, histfd, (off_t)0);
7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * check on its validity
7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (base == (unsigned char *)MAP_FAILED ||
7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    *base != HMAGIC1 || base[1] != HMAGIC2) {
7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (base != (unsigned char *)MAP_FAILED)
7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				munmap((caddr_t)base, hsize);
7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hist_finish();
7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (unlink(hname) /* fails */)
7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto hiniterr;
7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto retry;
7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (hsize > 2) {
7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lines = hist_count_lines(base+2, hsize-2);
7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (lines > histsize) {
7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* we need to make the file smaller */
7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (hist_shrink(base, hsize))
7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					rv = unlink(hname);
7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				munmap((caddr_t)base, hsize);
7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				hist_finish();
7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (rv) {
7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hiniterr:
76803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					bi_errorf("can't %s %s: %s",
76903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    "unlink HISTFILE", hname,
77003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra					    strerror(errno));
7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					hsize = 0;
7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					return;
7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto retry;
7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		histload(hist_source, base+2, hsize-2);
7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		munmap((caddr_t)base, hsize);
7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)flock(histfd, LOCK_UN);
78103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	hfsize = lseek(histfd, (off_t)0, SEEK_END);
78203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	hsize = 1024 * 1048576;
78303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (hfsize < (off_t)hsize)
78403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hsize = hfsize;
7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY
7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutypedef enum state {
7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	shdr,		/* expecting a header */
7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sline,		/* looking for a null byte to end the line */
7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sn1,		/* bytes 1 to 4 of a line no */
7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sn2, sn3, sn4
7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} State;
7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_count_lines(unsigned char *base, int bytes)
7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	State state = shdr;
8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int lines = 0;
8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	while (bytes--) {
8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case shdr:
8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*base == COMMAND)
8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = sn1;
8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn1:
8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn2; break;
8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn2:
8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn3; break;
8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn3:
8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn4; break;
8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn4:
8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sline; break;
8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sline:
8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*base == '\0') {
8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				lines++;
8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = shdr;
8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		base++;
8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (lines);
8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Shrink the history file to histsize lines
8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_shrink(unsigned char *oldbase, int oldbytes)
8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int fd, rv = 0;
8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char *nfile = NULL;
8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct	stat statb;
8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char *nbase = oldbase;
8375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int nbytes = oldbytes;
8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	nbase = hist_skip_back(nbase, &nbytes, histsize);
8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (nbase == NULL)
8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (nbase == oldbase)
8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	create temp file
8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	nfile = shf_smprintf("%s.%d", hname, (int)procpid);
8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((fd = open(nfile, O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0)
8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto errout;
8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (fstat(histfd, &statb) >= 0 &&
8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    chown(nfile, statb.st_uid, statb.st_gid))
8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto errout;
8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (sprinkle(fd) || write(fd, nbase, nbytes) != nbytes)
8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		goto errout;
8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	close(fd);
8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fd = -1;
8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	rename
8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (rename(nfile, hname) < 0) {
8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errout:
8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (fd >= 0) {
8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			close(fd);
8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (nfile)
8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				unlink(nfile);
8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		rv = 1;
8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	afree(nfile, ATEMP);
8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (rv);
8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	find a pointer to the data 'no' back from the end of the file
8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	return the pointer and the number of bytes left
8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic unsigned char *
8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_skip_back(unsigned char *base, int *bytes, int no)
8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int lines = 0;
8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char *ep;
8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (ep = base + *bytes; --ep > base; ) {
8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * this doesn't really work: the 4 byte line number that
8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * is encoded after the COMMAND byte can itself contain
8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * the COMMAND byte....
8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		for (; ep > base && *ep != COMMAND; ep--)
8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			;
8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (ep == base)
8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (++lines == no) {
8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			*bytes = *bytes - ((char *)ep - (char *)base);
8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (ep);
8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (NULL);
9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	load the history structure from the stored data
9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistload(Source *s, unsigned char *base, int bytes)
9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	State state;
9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int lno = 0;
9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	unsigned char *line = NULL;
9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (state = shdr; bytes-- > 0; base++) {
9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		switch (state) {
9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case shdr:
9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*base == COMMAND)
9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = sn1;
9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn1:
9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lno = (((*base)&0xff)<<24);
9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn2;
9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn2:
9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lno |= (((*base)&0xff)<<16);
9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn3;
9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn3:
9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lno |= (((*base)&0xff)<<8);
9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sn4;
9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sn4:
9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lno |= (*base)&0xff;
9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			line = base+1;
9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			state = sline;
9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			break;
9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		case sline:
9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*base == '\0') {
9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				/* worry about line numbers */
9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (histptr >= history && lno-1 != s->line) {
9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					/* a replacement ? */
9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					histinsert(s, lno, (char *)line);
9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				} else {
9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					s->line = lno--;
9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					histsave(&lno, (char *)line, false,
9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					    false);
9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				}
9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				state = shdr;
9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	Insert a line into the history at a specified number
9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistinsert(Source *s, int lno, const char *line)
9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	char **hp;
9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (lno >= s->line - (histptr - history) && lno <= s->line) {
9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hp = &histptr[lno - s->line];
9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (*hp)
9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(*hp, APERM);
9665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		strdupx(*hp, line, APERM);
9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	write a command to the end of the history file
9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	This *MAY* seem easy but it's also necessary to check
9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	that the history file has not changed in size.
9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	If it has - then some other shell has written to it
9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	and we should read those commands to update our history
9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruwritehistfile(int lno, char *cmd)
9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
98003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	off_t sizenow;
98103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	ssize_t bytes;
98203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	unsigned char *base, *news, hdr[5];
9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)flock(histfd, LOCK_EX);
9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sizenow = lseek(histfd, (off_t)0, SEEK_END);
98603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if ((sizenow <= (1024 * 1048576)) && ((size_t)sizenow != hsize)) {
9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 *	Things have changed
9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
99003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if ((size_t)sizenow > hsize) {
9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* someone has added some lines */
99203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			bytes = (size_t)sizenow - hsize;
99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			base = (void *)mmap(NULL, (size_t)sizenow, PROT_READ,
9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    MAP_FILE | MAP_PRIVATE, histfd, (off_t)0);
9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (base == (unsigned char *)MAP_FAILED)
9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto bad;
9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			news = base + hsize;
9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (*news != COMMAND) {
99903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				munmap((caddr_t)base, (size_t)sizenow);
10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				goto bad;
10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hist_source->line--;
10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			histload(hist_source, news, bytes);
10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			hist_source->line++;
10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			lno = hist_source->line;
100603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			munmap((caddr_t)base, (size_t)sizenow);
100703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			hsize = (size_t)sizenow;
10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* it has shrunk */
10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* but to what? */
10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* we'll give up for now */
10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto bad;
10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (cmd) {
10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 *	we can write our bit now
10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hdr[0] = COMMAND;
10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hdr[1] = (lno>>24)&0xff;
10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hdr[2] = (lno>>16)&0xff;
10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hdr[3] = (lno>>8)&0xff;
10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		hdr[4] = lno&0xff;
10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		bytes = strlen(cmd) + 1;
10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((write(histfd, hdr, 5) != 5) ||
10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    (write(histfd, cmd, bytes) != bytes))
10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			goto bad;
102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sizenow = lseek(histfd, (off_t)0, SEEK_END);
102903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		hsize = 1024 * 1048576;
103003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (sizenow < (off_t)hsize)
103103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			hsize = (size_t)sizenow;
10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)flock(histfd, LOCK_UN);
10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return;
10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bad:
10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	hist_finish();
10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_finish(void)
10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)flock(histfd, LOCK_UN);
10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)close(histfd);
10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	histfd = 0;
10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *	add magic to the history file
10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int
10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusprinkle(int fd)
10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	static const unsigned char mag[] = { HMAGIC1, HMAGIC2 };
10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (write(fd, mag, 2) != 2);
10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_SYS_SIGNAME
10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct mksh_sigpair {
10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *const name;
10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int nr;
10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} mksh_sigpairs[] = {
10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "signames.inc"
10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	{ NULL, 0 }
10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru};
10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinittraps(void)
10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *cs;
10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
107503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	trap_exstat = -1;
107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* Populate sigtraps based on sys_signame and sys_siglist. */
10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = 0; i <= NSIG; i++) {
10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sigtraps[i].signal = i;
108003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		if (i == ksh_SIGERR) {
10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sigtraps[i].name = "ERR";
10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sigtraps[i].mess = "Error handler";
10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else {
10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGNAME
10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cs = sys_signame[i];
10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			const struct mksh_sigpair *pair = mksh_sigpairs;
10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			while ((pair->nr != i) && (pair->name != NULL))
10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				++pair;
10905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			cs = pair->name;
10915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((cs == NULL) ||
10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (cs[0] == '\0'))
10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				sigtraps[i].name = shf_smprintf("%d", i);
10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else {
10965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				char *s;
10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				if (!strncasecmp(cs, "SIG", 3))
10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					cs += 3;
11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				strdupx(s, cs, APERM);
11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				sigtraps[i].name = s;
11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				while ((*s = ksh_toupper(*s)))
11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru					++s;
11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			}
11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGLIST
11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sigtraps[i].mess = sys_siglist[i];
11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif HAVE_STRSIGNAL
11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sigtraps[i].mess = strsignal(i);
11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else
11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			sigtraps[i].mess = NULL;
11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif
11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if ((sigtraps[i].mess == NULL) ||
11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    (sigtraps[i].mess[0] == '\0'))
111403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				sigtraps[i].mess = shf_smprintf("%s %d",
111503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra				    "Signal", i);
11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
111803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* our name for signal 0 */
111903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	sigtraps[ksh_SIGEXIT].name = "EXIT";
11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	(void)sigemptyset(&Sigact_ign.sa_mask);
11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Sigact_ign.sa_flags = 0; /* interruptible */
11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Sigact_ign.sa_handler = SIG_IGN;
11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR;
11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR;
112703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* SIGTERM is not fatal for interactive */
112803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	sigtraps[SIGTERM].flags |= TF_DFL_INTR;
11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGHUP].flags |= TF_FATAL;
11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGCHLD].flags |= TF_SHELL_USES;
11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* these are always caught so we can clean up any temporary files. */
11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG);
11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG);
11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG);
11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG);
11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void alarm_catcher(int sig);
11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_init(void)
11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sigtraps[SIGALRM].flags |= TF_SHELL_USES;
11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(&sigtraps[SIGALRM], alarm_catcher,
11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP);
11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* ARGSUSED */
11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void
11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_catcher(int sig MKSH_A_UNUSED)
11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* this runs inside interrupt context, with errno saved */
11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_tmout_state == TMOUT_READING) {
11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		int left = alarm(0);
11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (left == 0) {
11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			ksh_tmout_state = TMOUT_LEAVING;
11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			intrsig = 1;
11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		} else
11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			alarm(left);
11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTrap *
11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugettrap(const char *name, int igncase)
11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int n = NSIG + 1;
11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	const char *n2;
11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int (*cmpfunc)(const char *, const char *) = strcmp;
11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_isdigit(*name)) {
11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (getn(name, &n) && 0 <= n && n < NSIG)
11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (&sigtraps[n]);
11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (NULL);
11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	n2 = strncasecmp(name, "SIG", 3) ? NULL : name + 3;
11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (igncase)
11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		cmpfunc = strcasecmp;
11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = sigtraps; --n >= 0; p++)
11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!cmpfunc(p->name, name) || (n2 && !cmpfunc(p->name, n2)))
11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (p);
11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (NULL);
11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * trap signal handler
11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrapsig(int i)
11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p = &sigtraps[i];
119703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int errno_sv = errno;
11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	trap = p->set = 1;
12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p->flags & TF_DFL_INTR)
12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		intrsig = 1;
12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p->flags & TF_FATAL) && !p->trap) {
12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fatal_trap = 1;
12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		intrsig = 1;
12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p->shtrap)
12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(*p->shtrap)(i);
120803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	errno = errno_sv;
12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called when we want to allow the user to ^C out of something - won't
12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * work if user has trapped SIGINT.
12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruintrcheck(void)
12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (intrsig)
12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		runtraps(TF_DFL_INTR|TF_FATAL);
12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called after EINTR to check if a signal with normally causes process
12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * termination has been received.
12255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufatal_trap_check(void)
12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* todo: should check if signal is fatal, not the TF_DFL_INTR flag */
12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL)))
12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* return value is used as an exit code */
12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (128 + p->signal);
12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Returns the signal number of any pending traps: ie, a signal which has
12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * occurred for which a trap has been set or for which the TF_DFL_INTR flag
12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is set.
12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrap_pending(void)
12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->set && ((p->trap && p->trap[0]) ||
12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap)))
12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			return (p->signal);
12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (0);
12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * run any pending traps. If intr is set, only run traps that
12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * can interrupt commands.
12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruruntraps(int flag)
12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (ksh_tmout_state == TMOUT_LEAVING) {
12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_EXECUTING;
12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		warningf(false, "timed out waiting for input");
12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		unwind(LEXIT);
12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else
12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * XXX: this means the alarm will have no effect if a trap
12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * is caught after the alarm() was started...not good.
12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		ksh_tmout_state = TMOUT_EXECUTING;
12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!flag)
12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		trap = 0;
12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flag & TF_DFL_INTR)
12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		intrsig = 0;
12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flag & TF_FATAL)
12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		fatal_trap = 0;
128403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	++trap_nested;
12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (p = sigtraps, i = NSIG+1; --i >= 0; p++)
12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->set && (!flag ||
12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    ((p->flags & flag) && p->trap == NULL)))
128803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra			runtrap(p, false);
128903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (!--trap_nested)
129003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		runtrap(NULL, true);
12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
129403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraruntrap(Trap *p, bool is_last)
12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
129603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	int old_changed = 0, i;
129703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	char *trapstr;
129803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
129903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (p == NULL)
130003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* just clean up, see runtraps() above */
130103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto donetrap;
130203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	i = p->signal;
130303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	trapstr = p->trap;
13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->set = 0;
130503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (trapstr == NULL) {
130603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* SIG_DFL */
13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->flags & TF_FATAL) {
13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* eg, SIGHUP */
13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = 128 + i;
13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unwind(LLEAVE);
13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->flags & TF_DFL_INTR) {
13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* eg, SIGINT, SIGQUIT, SIGTERM, etc. */
13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			exstat = 128 + i;
13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			unwind(LINTR);
13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
131703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto donetrap;
13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
131903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (trapstr[0] == '\0')
132003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* SIG_IGN */
132103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		goto donetrap;
132203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (i == ksh_SIGEXIT || i == ksh_SIGERR) {
132303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* avoid recursion on these */
13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		old_changed = p->flags & TF_CHANGED;
13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags &= ~TF_CHANGED;
13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->trap = NULL;
13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
132803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (trap_exstat == -1)
132903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		trap_exstat = exstat;
13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Note: trapstr is fully parsed before anything is executed, thus
13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * no problem with afree(p->trap) in settrap() while still in use.
13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	command(trapstr, current_lineno);
133503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (i == ksh_SIGEXIT || i == ksh_SIGERR) {
13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->flags & TF_CHANGED)
13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* don't clear TF_CHANGED */
13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			afree(trapstr, APERM);
13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		else
13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p->trap = trapstr;
13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags |= old_changed;
13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
134303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra
134403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra donetrap:
134503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* we're the last trap of a sequence executed */
134603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (is_last && trap_exstat != -1) {
134703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		exstat = trap_exstat;
134803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		trap_exstat = -1;
134903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	}
13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* clear pending traps and reset user's trap handlers; used after fork(2) */
13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleartraps(void)
13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	trap = 0;
13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	intrsig = 0;
13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	fatal_trap = 0;
13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = NSIG+1, p = sigtraps; --i >= 0; p++) {
13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->set = 0;
13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0]))
13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			settrap(p, NULL);
13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* restore signals just before an exec(2) */
13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestoresigs(void)
13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int i;
13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p;
13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	for (i = NSIG+1, p = sigtraps; --i >= 0; p++)
13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL))
13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL,
13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			    SS_RESTORE_CURR|SS_FORCE);
13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusettrap(Trap *p, const char *s)
13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	sig_t f;
13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p->trap)
13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		afree(p->trap, APERM);
138903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	/* handles s == NULL */
139003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	strdupx(p->trap, s, APERM);
13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->flags |= TF_CHANGED;
13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN;
13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->flags |= TF_USER_SET;
13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL)
13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		f = trapsig;
13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	else if (p->flags & TF_SHELL_USES) {
13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) {
13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			/* do what user wants at exec time */
14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			if (f == SIG_IGN)
14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				p->flags |= TF_EXEC_IGN;
14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			else
14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru				p->flags |= TF_EXEC_DFL;
14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		}
14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		/*
14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * assumes handler already set to what shell wants it
14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 * (normally trapsig, but could be j_sigchld() or SIG_IGN)
14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		 */
14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return;
14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* todo: should we let user know signal is ignored? how? */
14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setsig(p, f, SS_RESTORE_CURR|SS_USER);
14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Called by c_print() when writing to a co-process to ensure SIGPIPE won't
14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * kill shell (unless user catches it and exits)
14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querublock_pipe(void)
14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	int restore_dfl = 0;
14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	Trap *p = &sigtraps[SIGPIPE];
14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setsig(p, SIG_IGN, SS_RESTORE_CURR);
14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		if (p->flags & TF_ORIG_DFL)
14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru			restore_dfl = 1;
14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	} else if (p->cursig == SIG_DFL) {
14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setsig(p, SIG_IGN, SS_RESTORE_CURR);
143403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* restore to SIG_DFL */
143503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		restore_dfl = 1;
14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (restore_dfl);
14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called by c_print() to undo whatever block_pipe() did */
14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestore_pipe(int restore_dfl)
14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (restore_dfl)
14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR);
14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*
14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Set action for a signal. Action may not be set if original
14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * action was SIG_IGN, depending on the value of flags and FTALKING.
14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */
14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint
14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetsig(Trap *p, sig_t f, int flags)
14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	struct sigaction sigact;
14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
145703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR)
14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (1);
14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * First time setting this signal? If so, get and note the current
14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * setting.
14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) {
14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sigaction(p->signal, &Sigact_ign, &sigact);
14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags |= sigact.sa_handler == SIG_IGN ?
14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    TF_ORIG_IGN : TF_ORIG_DFL;
14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->cursig = SIG_IGN;
14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*-
14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * Generally, an ignored signal stays ignored, except if
14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	- the user of an interactive shell wants to change it
14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 *	- the shell wants for force a change
14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE) &&
14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	    (!(flags & SS_USER) || !Flag(FTALKING)))
14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		return (0);
14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	setexecsig(p, flags & SS_RESTORE_MASK);
14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/*
14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * This is here 'cause there should be a way of clearing
14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * shtraps, but don't know if this is a sane way of doing
14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * it. At the moment, all users of shtrap are lifetime
14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 * users (SIGALRM, SIGCHLD, SIGWINCH).
14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	 */
14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(flags & SS_USER))
14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->shtrap = (sig_t)NULL;
14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (flags & SS_SHTRAP) {
14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->shtrap = f;
14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		f = trapsig;
14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (p->cursig != f) {
14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->cursig = f;
14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		(void)sigemptyset(&sigact.sa_mask);
149803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* interruptible */
149903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		sigact.sa_flags = 0;
15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sigact.sa_handler = f;
15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		sigaction(p->signal, &sigact, NULL);
15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	return (1);
15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* control what signal is set to before an exec() */
15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid
15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetexecsig(Trap *p, int restore)
15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{
15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* XXX debugging */
15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL)))
15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		internal_errorf("setexecsig: unset signal %d(%s)",
15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		    p->signal, p->name);
15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru
15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	/* restore original value for exec'd kids */
15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL);
15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	switch (restore & SS_RESTORE_MASK) {
151903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra	case SS_RESTORE_CURR:
152003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra		/* leave things as they currently are */
15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case SS_RESTORE_ORIG:
15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL;
15245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case SS_RESTORE_DFL:
15265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags |= TF_EXEC_DFL;
15275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	case SS_RESTORE_IGN:
15295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		p->flags |= TF_EXEC_IGN;
15305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru		break;
15315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru	}
15325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}
1533