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/*- 5c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 6c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 2011, 2012 75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 2603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SYS_FILE_H 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <sys/file.h> 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 30c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.131 2012/12/28 02:28:35 tg Exp $"); 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTrap sigtraps[NSIG + 1]; 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic struct sigaction Sigact_ign; 345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 36c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int histload(Source *, unsigned char *, size_t); 37c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int writehistline(int, int, const char *); 38c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic void writehistfile(int, const char *); 395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int hist_execute(char *); 425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **hist_get(const char *, bool, bool); 435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char **hist_get_oldest(void); 445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 45c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic bool hstarted; /* set after hist_init() called */ 465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic Source *hist_source; 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 49c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/*XXX imake style */ 50c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(__linux) 51c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define caddr_cast(x) ((void *)(x)) 52c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#else 53c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define caddr_cast(x) ((caddr_t)(x)) 54c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 55c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 56c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* several OEs do not have these constants */ 57c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MAP_FAILED 58c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define MAP_FAILED caddr_cast(-1) 59c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 60c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 61c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* some OEs need the default mapping type specified */ 62c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MAP_FILE 63c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define MAP_FILE 0 64c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 65c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 6603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* current history file: name, fd, size */ 6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic char *hname; 68c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int histfd = -1; 69c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic off_t histfsize; 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const char Tnot_in_history[] = "not in history"; 7303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define Thistory (Tnot_in_history + 7) 7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 75c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const char TFCEDIT_dollaru[] = "${FCEDIT:-/bin/ed} $_"; 76c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define Tspdollaru (TFCEDIT_dollaru + 18) 77c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 78c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* HISTSIZE default: size of saved history, persistent or standard */ 79c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH_SMALL 80c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define MKSH_DEFHISTSIZE 255 81c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#else 82c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define MKSH_DEFHISTSIZE 2047 83c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 84c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* maximum considered size of persistent history file */ 85c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define MKSH_MAXHISTFSIZE ((off_t)1048576 * 96) 86c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruc_fc(const char **wp) 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct shf *shf; 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct temp *tf; 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool gflag = false, lflag = false, nflag = false, rflag = false, 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sflag = false; 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int optc; 95c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char *p, *first = NULL, *last = NULL; 96c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char **hfirst, **hlast, **hp, *editor = NULL; 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!Flag(FTALKING_I)) { 9903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("history %ss not available", Tfunction); 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((optc = ksh_getopt(wp, &builtin_opt, 1045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru "e:glnrs0,1,2,3,4,5,6,7,8,9,")) != -1) 1055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (optc) { 10603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'e': 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = builtin_opt.optarg; 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_isdash(p)) 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sflag = true; 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len = strlen(p); 11303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 11403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* almost certainly not overflowing */ 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru editor = alloc(len + 4, ATEMP); 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(editor, p, len); 117c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memcpy(editor + len, Tspdollaru, 4); 1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 12103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* non-AT&T ksh */ 12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'g': 1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru gflag = true; 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 12503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'l': 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru lflag = true; 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 12903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'n': 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nflag = true; 1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'r': 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rflag = true; 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 13803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX version of -e - */ 13903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 's': 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sflag = true; 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* kludge city - accept -num as -- -num (kind of) */ 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': case '1': case '2': case '3': case '4': 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '5': case '6': case '7': case '8': case '9': 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = shf_smprintf("-%c%s", 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru optc, builtin_opt.optarg); 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!first) 1495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru first = p; 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (!last) 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru last = p; 1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("too many arguments"); 1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 15703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp += builtin_opt.optind; 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Substitute and execute command */ 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sflag) { 165c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *pat = NULL, *rep = NULL, *line; 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (editor || lflag || nflag || rflag) { 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("can't use -e, -l, -n, -r with -s (-e -)"); 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for pattern replacement argument */ 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*wp && **wp && (p = cstrchr(*wp + 1, '='))) { 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(pat, *wp, ATEMP); 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rep = pat + (p - *wp); 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *rep++ = '\0'; 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp++; 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Check for search prefix */ 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!first && (first = *wp)) 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp++; 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (last || *wp) { 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("too many arguments"); 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = first ? hist_get(first, false, false) : 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_get_newest(false); 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!hp) 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 191c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* hist_replace */ 192c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!pat) 193c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(line, *hp, ATEMP); 194c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser else { 195c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *s, *s1; 196c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t len, pat_len, rep_len; 197c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XString xs; 198c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *xp; 199c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool any_subst = false; 200c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 201c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser pat_len = strlen(pat); 202c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rep_len = strlen(rep); 203c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Xinit(xs, xp, 128, ATEMP); 204c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser for (s = *hp; (s1 = strstr(s, pat)) && 205c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (!any_subst || gflag); s = s1 + pat_len) { 206c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser any_subst = true; 207c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser len = s1 - s; 208c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XcheckN(xs, xp, len + rep_len); 209c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /*; first part */ 210c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memcpy(xp, s, len); 211c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp += len; 212c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* replacement */ 213c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memcpy(xp, rep, rep_len); 214c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp += rep_len; 215c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 216c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!any_subst) { 217c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bi_errorf("bad substitution"); 218c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (1); 219c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 220c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser len = strlen(s) + 1; 221c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser XcheckN(xs, xp, len); 222c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memcpy(xp, s, len); 223c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser xp += len; 224c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser line = Xclose(xs, xp); 225c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 226c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (hist_execute(line)); 2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (editor && (lflag || nflag)) { 2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("can't use -l, -n with -e"); 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!first && (first = *wp)) 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp++; 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!last && (last = *wp)) 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wp++; 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*wp) { 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("too many arguments"); 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!first) { 2435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hfirst = lflag ? hist_get("-16", true, true) : 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_get_newest(false); 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!hfirst) 2465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* can't fail if hfirst didn't fail */ 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hlast = hist_get_newest(false); 2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 25003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 25103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * POSIX says not an error if first/last out of bounds 25203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * when range is specified; AT&T ksh and pdksh allow out 25303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * of bounds for -l as well. 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 25503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra hfirst = hist_get(first, tobool(lflag || last), lflag); 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!hfirst) 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hlast = last ? hist_get(last, true, lflag) : 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (lflag ? hist_get_newest(false) : hfirst); 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!hlast) 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (hfirst > hlast) { 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char **temp; 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru temp = hfirst; hfirst = hlast; hlast = temp; 26703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX */ 26803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rflag = !rflag; 2695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* List history */ 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (lflag) { 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s, *t; 2745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (hp = rflag ? hlast : hfirst; 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) { 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!nflag) 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shl_stdout, "%d", 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line - (int)(histptr - hp)); 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\t', shl_stdout); 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* print multi-line commands correctly */ 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = *hp; 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((t = strchr(s, '\n'))) { 2845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *t = '\0'; 2855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shl_stdout, "%s\n\t", s); 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *t++ = '\n'; 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = t; 2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shl_stdout, "%s\n", s); 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_flush(shl_stdout); 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Run editor on selected lines, then run resulting commands */ 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru tf = maketemp(ATEMP, TT_HIST_EDIT, &e->temps); 2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(shf = tf->shf)) { 29903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't %s temporary file %s: %s", 300c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "create", tf->tffn, cstrerror(errno)); 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (hp = rflag ? hlast : hfirst; 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp >= hfirst && hp <= hlast; hp += rflag ? -1 : 1) 3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%s\n", *hp); 3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (shf_close(shf) == EOF) { 30703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't %s temporary file %s: %s", 308c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "write", tf->tffn, cstrerror(errno)); 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Ignore setstr errors here (arbitrary) */ 313c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser setstr(local("_", false), tf->tffn, KSH_RETURN_ERROR); 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX: source should not get trashed by this.. */ 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *sold = source; 3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int ret; 3195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 320c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ret = command(editor ? editor : TFCEDIT_dollaru, 0); 3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ret) 3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { 3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat statb; 3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString xs; 3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp; 330c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ssize_t n; 3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 332c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!(shf = shf_open(tf->tffn, O_RDONLY, 0, 0))) { 33303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't %s temporary file %s: %s", 334c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "open", tf->tffn, cstrerror(errno)); 3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 338c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (stat(tf->tffn, &statb) < 0) 33903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra n = 128; 340c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser else if ((off_t)statb.st_size > MKSH_MAXHISTFSIZE) { 34103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s %s too large: %lu", Thistory, 34203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "file", (unsigned long)statb.st_size); 34303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto errout; 34403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else 345c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser n = (size_t)statb.st_size + 1; 3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xinit(xs, xp, n, hist_source->areap); 3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((n = shf_read(xp, Xnleft(xs, xp), shf)) > 0) { 3485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += n; 3495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Xnleft(xs, xp) <= 0) 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(xs, xp, Xlength(xs, xp)); 3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (n < 0) { 35303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't %s temporary file %s: %s", 354c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "read", tf->tffn, cstrerror(shf_errno(shf))); 35503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errout: 3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_close(shf); 3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_close(shf); 3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *xp = '\0'; 3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strip_nuls(Xstring(xs, xp), Xlength(xs, xp)); 3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (hist_execute(Xstring(xs, xp))); 3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Save cmd in history, execute cmd (cmd gets trashed) */ 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_execute(char *cmd) 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 370c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser static int last_line = -1; 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Source *sold; 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int ret; 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p, *q; 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 375c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* Back up over last histsave */ 376c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histptr >= history && last_line != hist_source->line) { 377c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_source->line--; 378c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(*histptr, APERM); 379c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histptr--; 380c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser last_line = hist_source->line; 381c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = cmd; p; p = q) { 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((q = strchr(p, '\n'))) { 38503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* kill the newline */ 38603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *q++ = '\0'; 38703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*q) 38803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ignore trailing newline */ 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru q = NULL; 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histsave(&hist_source->line, p, true, true); 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 39303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* POSIX doesn't say this is done... */ 39403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shellf("%s\n", p); 39503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (q) 39603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore \n (trailing \n not restored) */ 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru q[-1] = '\n'; 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 40003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Commands are executed here instead of pushing them onto the 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * input 'cause POSIX says the redirection and variable assignments 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * X=y fc -e - 42 2> /dev/null 4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are to effect the repeated commands environment. 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX: source should not get trashed by this.. */ 4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sold = source; 4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ret = command(cmd, 0); 4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru source = sold; 4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * get pointer to history given pattern 4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * pattern is a number or string 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char ** 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get(const char *str, bool approx, bool allow_cur) 4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char **hp = NULL; 4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int n; 4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (getn(str, &n)) { 4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = histptr + (n < 0 ? n : (n - hist_source->line)); 4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((ptrdiff_t)hp < (ptrdiff_t)history) { 4275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (approx) 4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = hist_get_oldest(); 4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 43003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", str, Tnot_in_history); 4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = NULL; 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((ptrdiff_t)hp > (ptrdiff_t)histptr) { 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (approx) 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = hist_get_newest(allow_cur); 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 43703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", str, Tnot_in_history); 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = NULL; 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (!allow_cur && hp == histptr) { 44103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", str, "invalid range"); 4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = NULL; 4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int anchored = *str == '?' ? (++str, 0) : 1; 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* the -1 is to avoid the current fc command */ 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((n = findhist(histptr - history - 1, 0, str, anchored)) < 0) 44903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", str, Tnot_in_history); 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = &history[n]; 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (hp); 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Return a pointer to the newest command in the history */ 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar ** 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get_newest(bool allow_cur) 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (histptr < history || (!allow_cur && histptr == history)) { 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("no history (yet)"); 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (allow_cur ? histptr : histptr - 1); 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Return a pointer to the oldest command in the history */ 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char ** 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_get_oldest(void) 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (histptr <= history) { 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorf("no history (yet)"); 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (history); 4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if !defined(MKSH_NO_CMDLINE_EDITING) && !MKSH_S_NOVI 479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* current position in history[] */ 480c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char **current; 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Return the current position. 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar ** 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistpos(void) 4875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (current); 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 4925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistnum(int n) 4935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int last = histptr - history; 4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (n < 0 || n >= last) { 4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru current = histptr; 4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (last); 4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru current = &history[n]; 5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (n); 5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This will become unnecessary if hist_get is modified to allow 5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * searching from positions other than the end, and in either 5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direction. 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufindhist(int start, int fwd, const char *str, int anchored) 5135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char **hp; 51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int maxhist = histptr - history; 51603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int incr = fwd ? 1 : -1; 51703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len = strlen(str); 5185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (start < 0 || start >= maxhist) 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru start = maxhist; 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = &history[start]; 5235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; hp >= history && hp <= histptr; hp += incr) 5245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((anchored && strncmp(*hp, str, len) == 0) || 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!anchored && strstr(*hp, str))) 5265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (hp - history); 5275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 5295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 532c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * set history; this means reallocating the dataspace 5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 535c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasersethistsize(mksh_ari_t n) 5365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (n > 0 && n != histsize) { 5385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int cursize = histptr - history; 5395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* save most recent history */ 5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (n < cursize) { 542c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memmove(history, histptr - n + 1, n * sizeof(char *)); 543c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cursize = n - 1; 5445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 54603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra history = aresize2(history, n, sizeof(char *), APERM); 5475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histsize = n; 5495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histptr = history + cursize; 5505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 5545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 555c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * set history file; this can mean reloading/resetting/starting 556c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * history file 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 */ 562c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hstarted == false) 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 /* 570c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * it's a new name - possibly 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 572c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfd != -1) { 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* yes the file is open */ 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (void)close(histfd); 575c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfd = -1; 576c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = 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/* 589c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 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) { 595c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histsize = MKSH_DEFHISTSIZE; 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/* 603c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * It turns out that there is a lot of ghastly hackery here 6045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY 6075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* do not save command in history but possibly sync */ 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubool 6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistsync(void) 6105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool changed = false; 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 613c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfd != -1) { 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int lno = hist_source->line; 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line++; 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru writehistfile(0, NULL); 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line--; 6195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (lno != hist_source->line) 6215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru changed = true; 6225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (changed); 6255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * save command in history 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhistsave(int *lnp, const char *cmd, bool dowrite MKSH_A_UNUSED, bool ignoredups) 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char **hp; 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *c, *cp; 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 637c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mkssert(cmd != NULL); 6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(c, cmd, APERM); 6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cp = strchr(c, '\n')) != NULL) 6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp = '\0'; 6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ignoredups && !strcmp(c, *histptr) 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) && HAVE_PERSISTENT_HISTORY 6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru && !histsync() 6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ) { 6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(c, APERM); 6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++*lnp; 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 653c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (dowrite && histfd != -1) 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru writehistfile(*lnp, c); 6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp = histptr; 6585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 65903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (++hp >= history + histsize) { 66003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* remove oldest command */ 6615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(*history, APERM); 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (hp = history; hp < history + histsize - 1; hp++) 6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hp[0] = hp[1]; 6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *hp = c; 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histptr = hp; 6675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 670c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Write history data to a file nominated by HISTFILE; 671c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * if HISTFILE is unset then history still happens, but 672c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * the data is not written to a file. All copies of ksh 673c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * looking at the file will maintain the same history. 674c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * This is ksh behaviour. 675c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 676c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * This stuff uses mmap() 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 678c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * This stuff is so totally broken it must eventually be 679c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * redesigned, without mmap, better checks, support for 680c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * larger files, etc. and handle partially corrupted files 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 68303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*- 684c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Open a history file 685c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Format is: 686c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Bytes 1, 2: 687c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * HMAGIC - just to check that we are dealing with the correct object 688c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Then follows a number of stored commands 689c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Each command is 690c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * <command byte><command number(4 octets, big endian)><bytes><NUL> 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 692c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define HMAGIC1 0xAB 693c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define HMAGIC2 0xCD 694c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define COMMAND 0xFF 695c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 696c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_PERSISTENT_HISTORY 697c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic const unsigned char sprinkle[2] = { HMAGIC1, HMAGIC2 }; 698c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhist_init(Source *s) 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char *base; 705c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int lines, fd; 706c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser enum { hist_init_first, hist_init_retry, hist_init_restore } hs; 7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(FTALKING) == 0) 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 712c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hstarted = true; 7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source = s; 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((hname = str_val(global("HISTFILE"))) == NULL) 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(hname, hname, APERM); 719c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hs = hist_init_first; 7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru retry: 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* we have a file and are interactive */ 723c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND, 0600)) < 0) 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histfd = savefd(fd); 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (histfd != fd) 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 730c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_lockfd(histfd); 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 732c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 733c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfsize > MKSH_MAXHISTFSIZE || hs == hist_init_restore) { 734c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we ignore too large files but still append to them */ 735c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we also don't need to re-read after truncation */ 736c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_tail; 737c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (histfsize > 2) { 738c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we have some data, check its validity */ 739c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = (void *)mmap(NULL, (size_t)histfsize, PROT_READ, 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 741c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base == (unsigned char *)MAP_FAILED) 742c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_fail; 743c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base[0] != HMAGIC1 || base[1] != HMAGIC2) { 744c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)histfsize); 745c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_fail; 746c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 747c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* load _all_ data */ 748c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lines = histload(hist_source, base + 2, (size_t)histfsize - 2); 749c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)histfsize); 750c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* check if the file needs to be truncated */ 751c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (lines > histsize && histptr >= history) { 752c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* you're fucked up with the current code, trust me */ 753c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *nhname, **hp; 754c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct stat sb; 755c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 756c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* create temporary file */ 757c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser nhname = shf_smprintf("%s.%d", hname, (int)procpid); 758c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC | 759c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser O_EXCL, 0600)) < 0) { 760c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* just don't truncate then, meh. */ 761c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_dont; 762c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 763c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fstat(histfd, &sb) >= 0 && 764c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser chown(nhname, sb.st_uid, sb.st_gid)) { 765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* abort the truncation then, meh. */ 766c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 767c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 768c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we definitively want some magic in that file */ 769c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (write(fd, sprinkle, 2) != 2) 770c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 771c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* and of course the entries */ 772c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hp = history; 773c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while (hp < histptr) { 774c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!writehistline(fd, 775c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser s->line - (histptr - hp), *hp)) 776c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 777c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++hp; 778c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 779c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* now unlock, close both, rename, rinse, repeat */ 780c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser close(fd); 781c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser fd = -1; 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_finish(); 783c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (rename(nhname, hname) < 0) { 784c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_trunc_abort: 785c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fd != -1) 786c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser close(fd); 787c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unlink(nhname); 788c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fd != -1) 789c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_dont; 790c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* darn! restore histfd and pray */ 791c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 792c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hs = hist_init_restore; 793c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_trunc_dont: 794c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(nhname, ATEMP); 795c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hs == hist_init_restore) 796c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto retry; 797c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 798c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (histfsize != 0) { 799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* negative or too small... */ 800c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_init_fail: 801c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* ... or mmap failed or illegal */ 802c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 803c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* nuke the bogus file then retry, at most once */ 804c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!unlink(hname) && hs != hist_init_retry) { 805c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hs = hist_init_retry; 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto retry; 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 808c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hs != hist_init_retry) 809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bi_errorf("can't %s %s: %s", 810c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "unlink HISTFILE", hname, cstrerror(errno)); 811c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = 0; 812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* size 0, add magic to the history file */ 815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (write(histfd, sprinkle, 2) != 2) { 816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 820c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_init_tail: 822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 828c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * load the history structure from the stored data 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 831c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserhistload(Source *s, unsigned char *base, size_t bytes) 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 833c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int lno = 0, lines = 0; 834c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char *cp; 835c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histload_loop: 837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* !bytes check as some systems (older FreeBSDs) have buggy memchr */ 838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!bytes || (cp = memchr(base, COMMAND, bytes)) == NULL) 839c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (lines); 840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* advance base pointer past COMMAND byte */ 841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes -= ++cp - base; 842c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = cp; 843c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* if there is no full string left, don't bother with the rest */ 844c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (bytes < 5 || (cp = memchr(base + 4, '\0', bytes - 4)) == NULL) 845c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (lines); 846c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* load the stored line number */ 847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lno = ((base[0] & 0xFF) << 24) | ((base[1] & 0xFF) << 16) | 848c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ((base[2] & 0xFF) << 8) | (base[3] & 0xFF); 849c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* store away the found line (@base[4]) */ 850c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++lines; 851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histptr >= history && lno - 1 != s->line) { 852c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* a replacement? */ 853c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char **hp; 854c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 855c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (lno >= s->line - (histptr - history) && lno <= s->line) { 856c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hp = &histptr[lno - s->line]; 857c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (*hp) 858c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(*hp, APERM); 859c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(*hp, (char *)(base + 4), APERM); 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 861c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 862c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser s->line = lno--; 863c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histsave(&lno, (char *)(base + 4), false, false); 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 865c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* advance base pointer past NUL */ 866c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes -= ++cp - base; 867c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = cp; 868c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* repeat until no more */ 869c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto histload_loop; 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 873c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * write a command to the end of the history file 874c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 875c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * This *MAY* seem easy but it's also necessary to check 876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * that the history file has not changed in size. 877c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * If it has - then some other shell has written to it and 878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * we should (re)read those commands to update our history 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 881c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserwritehistfile(int lno, const char *cmd) 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 88303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra off_t sizenow; 884c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t bytes; 885c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char *base, *news; 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 887c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_lockfd(histfd); 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sizenow = lseek(histfd, (off_t)0, SEEK_END); 889c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (sizenow < histfsize) { 890c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* the file has shrunk; give up */ 891c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto bad; 892c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 893c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ( 894c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* ignore changes when the file is too large */ 895c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sizenow <= MKSH_MAXHISTFSIZE 896c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser && 897c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* the size has changed, we need to do read updates */ 898c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sizenow > histfsize 899c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ) { 900c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* both sizenow and histfsize are <= MKSH_MAXHISTFSIZE */ 901c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes = (size_t)(sizenow - histfsize); 902c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = (void *)mmap(NULL, (size_t)sizenow, PROT_READ, 903c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 904c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base == (unsigned char *)MAP_FAILED) 905c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto bad; 906c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser news = base + (size_t)histfsize; 907c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (*news == COMMAND) { 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line--; 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histload(hist_source, news, bytes); 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line++; 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru lno = hist_source->line; 912c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 913c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes = 0; 914c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)sizenow); 915c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!bytes) 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto bad; 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 918c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (cmd && !writehistline(histfd, lno, cmd)) { 9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bad: 920c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 921c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 924c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 927c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int 928c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserwritehistline(int fd, int lno, const char *cmd) 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 930c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ssize_t n; 931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char hdr[5]; 932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[0] = COMMAND; 934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[1] = (lno >> 24) & 0xFF; 935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[2] = (lno >> 16) & 0xFF; 936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[3] = (lno >> 8) & 0xFF; 937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[4] = lno & 0xFF; 938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser n = strlen(cmd) + 1; 939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (write(fd, hdr, 5) == 5 && write(fd, cmd, n) == n); 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 942c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserhist_finish(void) 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 945c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfd >= 0) { 946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)close(histfd); 948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfd = -1; 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 953c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_SYS_SIGNAME 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct mksh_sigpair { 956c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char * const name; 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nr; 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} mksh_sigpairs[] = { 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "signames.inc" 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { NULL, 0 } 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 964c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_SYS_SIGLIST 965c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if !HAVE_SYS_SIGLIST_DECL 966c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserextern const char * const sys_siglist[]; 967c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 968c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinittraps(void) 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cs; 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 97603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trap_exstat = -1; 97703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Populate sigtraps based on sys_signame and sys_siglist. */ 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i <= NSIG; i++) { 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].signal = i; 98103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGERR) { 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = "ERR"; 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = "Error handler"; 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGNAME 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs = sys_signame[i]; 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct mksh_sigpair *pair = mksh_sigpairs; 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((pair->nr != i) && (pair->name != NULL)) 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++pair; 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs = pair->name; 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cs == NULL) || 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (cs[0] == '\0')) 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = shf_smprintf("%d", i); 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s; 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 999c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* this is not optimal, what about SIGSIG1? */ 1000c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((cs[0] & 0xDF) == 'S' && 1001c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[1] & 0xDF) == 'I' && 1002c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[2] & 0xDF) == 'G' && 1003c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs[3] != '\0') { 1004c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* skip leading "SIG" */ 10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs += 3; 1006c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(s, cs, APERM); 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = s; 10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((*s = ksh_toupper(*s))) 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++s; 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGLIST 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = sys_siglist[i]; 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif HAVE_STRSIGNAL 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = strsignal(i); 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = NULL; 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((sigtraps[i].mess == NULL) || 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (sigtraps[i].mess[0] == '\0')) 102103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[i].mess = shf_smprintf("%s %d", 102203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "Signal", i); 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 102503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* our name for signal 0 */ 102603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[ksh_SIGEXIT].name = "EXIT"; 10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (void)sigemptyset(&Sigact_ign.sa_mask); 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sigact_ign.sa_flags = 0; /* interruptible */ 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sigact_ign.sa_handler = SIG_IGN; 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR; 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR; 103403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIGTERM is not fatal for interactive */ 103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[SIGTERM].flags |= TF_DFL_INTR; 10365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGHUP].flags |= TF_FATAL; 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGCHLD].flags |= TF_SHELL_USES; 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* these are always caught so we can clean up any temporary files. */ 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG); 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG); 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG); 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG); 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void alarm_catcher(int sig); 10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_init(void) 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGALRM].flags |= TF_SHELL_USES; 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGALRM], alarm_catcher, 10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* ARGSUSED */ 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_catcher(int sig MKSH_A_UNUSED) 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this runs inside interrupt context, with errno saved */ 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_tmout_state == TMOUT_READING) { 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int left = alarm(0); 10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (left == 0) { 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_LEAVING; 10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alarm(left); 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTrap * 1074c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasergettrap(const char *cs, bool igncase) 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1076c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int i; 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 1078c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *as; 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1080c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (ksh_isdigit(*cs)) { 1081c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return ((getn(cs, &i) && 0 <= i && i < NSIG) ? 1082c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (&sigtraps[i]) : NULL); 10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1085c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* this breaks SIGSIG1, but we do that above anyway */ 1086c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((cs[0] & 0xDF) == 'S' && 1087c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[1] & 0xDF) == 'I' && 1088c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[2] & 0xDF) == 'G' && 1089c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs[3] != '\0') { 1090c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* skip leading "SIG" */ 1091c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs += 3; 1092c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1093c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (igncase) { 1094c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *s; 1095c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1096c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(as, cs, ATEMP); 1097c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs = s = as; 1098c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((*s = ksh_toupper(*s))) 1099c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++s; 1100c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 1101c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser as = NULL; 1102c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1103c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = sigtraps; 1104c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser for (i = 0; i <= NSIG; i++) { 1105c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!strcmp(p->name, cs)) 1106c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto found; 1107c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++p; 1108c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1109c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = NULL; 1110c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser found: 1111c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(as, ATEMP); 1112c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (p); 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * trap signal handler 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrapsig(int i) 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p = &sigtraps[i]; 1122c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int eno = errno; 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = p->set = 1; 11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_DFL_INTR) 11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_FATAL) && !p->trap) { 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 1; 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->shtrap) 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p->shtrap)(i); 1133c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errno = eno; 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called when we want to allow the user to ^C out of something - won't 11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * work if user has trapped SIGINT. 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruintrcheck(void) 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (intrsig) 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru runtraps(TF_DFL_INTR|TF_FATAL); 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called after EINTR to check if a signal with normally causes process 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * termination has been received. 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufatal_trap_check(void) 11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */ 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL))) 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* return value is used as an exit code */ 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (128 + p->signal); 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Returns the signal number of any pending traps: ie, a signal which has 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * occurred for which a trap has been set or for which the TF_DFL_INTR flag 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is set. 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrap_pending(void) 11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && ((p->trap && p->trap[0]) || 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap))) 11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p->signal); 11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * run any pending traps. If intr is set, only run traps that 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * can interrupt commands. 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruruntraps(int flag) 11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_tmout_state == TMOUT_LEAVING) { 11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_EXECUTING; 11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(false, "timed out waiting for input"); 11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LEXIT); 11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * XXX: this means the alarm will have no effect if a trap 12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is caught after the alarm() was started...not good. 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_EXECUTING; 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!flag) 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = 0; 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag & TF_DFL_INTR) 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 0; 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag & TF_FATAL) 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 0; 120903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++trap_nested; 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && (!flag || 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((p->flags & flag) && p->trap == NULL))) 121303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(p, false); 121403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!--trap_nested) 121503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(NULL, true); 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 121903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraruntrap(Trap *p, bool is_last) 12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 122103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int old_changed = 0, i; 122203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *trapstr; 122303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 122403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p == NULL) 122503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just clean up, see runtraps() above */ 122603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 122703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = p->signal; 122803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trapstr = p->trap; 12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->set = 0; 123003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trapstr == NULL) { 123103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIG_DFL */ 12325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_FATAL) { 12335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* eg, SIGHUP */ 1234c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = (int)ksh_min(128U + (unsigned)i, 255U); 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LLEAVE); 12365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_DFL_INTR) { 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */ 1239c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = (int)ksh_min(128U + (unsigned)i, 255U); 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LINTR); 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 124203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 124403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trapstr[0] == '\0') 124503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIG_IGN */ 124603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 124703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 124803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* avoid recursion on these */ 12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_changed = p->flags & TF_CHANGED; 12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~TF_CHANGED; 12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->trap = NULL; 12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 125303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trap_exstat == -1) 1254c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser trap_exstat = exstat & 0xFF; 12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note: trapstr is fully parsed before anything is executed, thus 12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * no problem with afree(p->trap) in settrap() while still in use. 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru command(trapstr, current_lineno); 126003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_CHANGED) 12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* don't clear TF_CHANGED */ 12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(trapstr, APERM); 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->trap = trapstr; 12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= old_changed; 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 126803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 126903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra donetrap: 127003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we're the last trap of a sequence executed */ 127103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (is_last && trap_exstat != -1) { 127203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra exstat = trap_exstat; 127303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trap_exstat = -1; 127403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* clear pending traps and reset user's trap handlers; used after fork(2) */ 12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleartraps(void) 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = 0; 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 0; 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 0; 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = NSIG+1, p = sigtraps; --i >= 0; p++) { 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->set = 0; 12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) 12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru settrap(p, NULL); 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* restore signals just before an exec(2) */ 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestoresigs(void) 12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = NSIG+1, p = sigtraps; --i >= 0; p++) 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL)) 13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL, 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_CURR|SS_FORCE); 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusettrap(Trap *p, const char *s) 13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sig_t f; 13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->trap) 13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(p->trap, APERM); 131403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* handles s == NULL */ 131503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(p->trap, s, APERM); 13165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_CHANGED; 13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN; 13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_USER_SET; 13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL) 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = trapsig; 13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (p->flags & TF_SHELL_USES) { 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) { 13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do what user wants at exec time */ 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f == SIG_IGN) 13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_IGN; 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_DFL; 13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * assumes handler already set to what shell wants it 13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (normally trapsig, but could be j_sigchld() or SIG_IGN) 13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* todo: should we let user know signal is ignored? how? */ 13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, f, SS_RESTORE_CURR|SS_USER); 13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Called by c_print() when writing to a co-process to ensure SIGPIPE won't 13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * kill shell (unless user catches it and exits) 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querublock_pipe(void) 13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int restore_dfl = 0; 13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p = &sigtraps[SIGPIPE]; 13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, SIG_IGN, SS_RESTORE_CURR); 13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_ORIG_DFL) 13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restore_dfl = 1; 13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (p->cursig == SIG_DFL) { 13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, SIG_IGN, SS_RESTORE_CURR); 135903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore to SIG_DFL */ 136003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra restore_dfl = 1; 13615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (restore_dfl); 13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called by c_print() to undo whatever block_pipe() did */ 13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestore_pipe(int restore_dfl) 13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (restore_dfl) 13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR); 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Set action for a signal. Action may not be set if original 13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * action was SIG_IGN, depending on the value of flags and FTALKING. 13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetsig(Trap *p, sig_t f, int flags) 13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct sigaction sigact; 13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 138203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) 13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 13845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1385c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&sigact, 0, sizeof(sigact)); 1386c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 13875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 13885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * First time setting this signal? If so, get and note the current 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * setting. 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigaction(p->signal, &Sigact_ign, &sigact); 13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= sigact.sa_handler == SIG_IGN ? 13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru TF_ORIG_IGN : TF_ORIG_DFL; 13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->cursig = SIG_IGN; 13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /*- 13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Generally, an ignored signal stays ignored, except if 14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the user of an interactive shell wants to change it 14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the shell wants for force a change 14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE) && 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!(flags & SS_USER) || !Flag(FTALKING))) 14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setexecsig(p, flags & SS_RESTORE_MASK); 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is here 'cause there should be a way of clearing 14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * shtraps, but don't know if this is a sane way of doing 14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it. At the moment, all users of shtrap are lifetime 14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * users (SIGALRM, SIGCHLD, SIGWINCH). 14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags & SS_USER)) 14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->shtrap = (sig_t)NULL; 14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flags & SS_SHTRAP) { 14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->shtrap = f; 14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = trapsig; 14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->cursig != f) { 14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->cursig = f; 14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (void)sigemptyset(&sigact.sa_mask); 142503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* interruptible */ 142603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigact.sa_flags = 0; 14275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigact.sa_handler = f; 14285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigaction(p->signal, &sigact, NULL); 14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* control what signal is set to before an exec() */ 14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetexecsig(Trap *p, int restore) 14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX debugging */ 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("setexecsig: unset signal %d(%s)", 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->signal, p->name); 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* restore original value for exec'd kids */ 14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (restore & SS_RESTORE_MASK) { 144603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case SS_RESTORE_CURR: 144703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* leave things as they currently are */ 14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_ORIG: 14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL; 14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_DFL: 14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_DFL; 14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_IGN: 14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_IGN; 14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1460c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1461c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_PERSISTENT_HISTORY || defined(DF) 1462c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* 1463c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * File descriptor locking and unlocking functions. 1464c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Could use some error handling, but hey, this is only 1465c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * advisory locking anyway, will often not work over NFS, 1466c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * and you are SOL if this fails... 1467c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 1468c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1469c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1470c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_lockfd(int fd) 1471c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1472c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(__OpenBSD__) 1473c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* flock is not interrupted by signals */ 1474c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)flock(fd, LOCK_EX); 1475c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_FLOCK 1476c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int rv; 1477c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* e.g. on Linux */ 1479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do { 1480c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = flock(fd, LOCK_EX); 1481c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } while (rv == 1 && errno == EINTR); 1482c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_LOCK_FCNTL 1483c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int rv; 1484c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct flock lks; 1485c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1486c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&lks, 0, sizeof(lks)); 1487c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lks.l_type = F_WRLCK; 1488c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do { 1489c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = fcntl(fd, F_SETLKW, &lks); 1490c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } while (rv == 1 && errno == EINTR); 1491c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1492c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1493c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1494c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* designed to not define mksh_unlkfd if none triggered */ 1495c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_FLOCK 1496c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1497c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_unlkfd(int fd) 1498c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1499c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)flock(fd, LOCK_UN); 1500c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1501c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_LOCK_FCNTL 1502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1503c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_unlkfd(int fd) 1504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1505c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct flock lks; 1506c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1507c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&lks, 0, sizeof(lks)); 1508c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lks.l_type = F_UNLCK; 1509c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)fcntl(fd, F_SETLKW, &lks); 1510c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1511c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1512c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1513