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