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, 6427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes * 2011, 2012, 2014 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 30427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes__RCSID("$MirOS: src/bin/mksh/histrap.c,v 1.134 2014/06/09 13:25:53 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 { 445427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes bool anchored = *str == '?' ? (++str, false) : true; 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 512427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughesfindhist(int start, int fwd, const char *str, bool 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 */ 723427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if ((fd = open(hname, O_RDWR | O_CREAT | O_APPEND | O_BINARY, 724427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes 0600)) < 0) 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histfd = savefd(fd); 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (histfd != fd) 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 731c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_lockfd(histfd); 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 733c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 734c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfsize > MKSH_MAXHISTFSIZE || hs == hist_init_restore) { 735c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we ignore too large files but still append to them */ 736c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we also don't need to re-read after truncation */ 737c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_tail; 738c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (histfsize > 2) { 739c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we have some data, check its validity */ 740c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = (void *)mmap(NULL, (size_t)histfsize, PROT_READ, 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 742c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base == (unsigned char *)MAP_FAILED) 743c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_fail; 744c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base[0] != HMAGIC1 || base[1] != HMAGIC2) { 745c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)histfsize); 746c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_init_fail; 747c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 748c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* load _all_ data */ 749c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lines = histload(hist_source, base + 2, (size_t)histfsize - 2); 750c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)histfsize); 751c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* check if the file needs to be truncated */ 752c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (lines > histsize && histptr >= history) { 753c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* you're fucked up with the current code, trust me */ 754c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *nhname, **hp; 755c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct stat sb; 756c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 757c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* create temporary file */ 758c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser nhname = shf_smprintf("%s.%d", hname, (int)procpid); 759c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((fd = open(nhname, O_RDWR | O_CREAT | O_TRUNC | 760427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes O_EXCL | O_BINARY, 0600)) < 0) { 761c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* just don't truncate then, meh. */ 762c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_dont; 763c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 764c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fstat(histfd, &sb) >= 0 && 765c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser chown(nhname, sb.st_uid, sb.st_gid)) { 766c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* abort the truncation then, meh. */ 767c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 768c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 769c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* we definitively want some magic in that file */ 770c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (write(fd, sprinkle, 2) != 2) 771c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 772c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* and of course the entries */ 773c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hp = history; 774c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while (hp < histptr) { 775c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!writehistline(fd, 776c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser s->line - (histptr - hp), *hp)) 777c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_abort; 778c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++hp; 779c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 780c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* now unlock, close both, rename, rinse, repeat */ 781c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser close(fd); 782c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser fd = -1; 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_finish(); 784c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (rename(nhname, hname) < 0) { 785c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_trunc_abort: 786c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fd != -1) 787c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser close(fd); 788c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unlink(nhname); 789c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (fd != -1) 790c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto hist_trunc_dont; 791c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* darn! restore histfd and pray */ 792c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 793c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hs = hist_init_restore; 794c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_trunc_dont: 795c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(nhname, ATEMP); 796c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hs == hist_init_restore) 797c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto retry; 798c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 799c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (histfsize != 0) { 800c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* negative or too small... */ 801c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_init_fail: 802c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* ... or mmap failed or illegal */ 803c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 804c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* nuke the bogus file then retry, at most once */ 805c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!unlink(hname) && hs != hist_init_retry) { 806c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hs = hist_init_retry; 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto retry; 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 809c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (hs != hist_init_retry) 810c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bi_errorf("can't %s %s: %s", 811c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "unlink HISTFILE", hname, cstrerror(errno)); 812c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = 0; 813c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 814c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 815c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* size 0, add magic to the history file */ 816c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (write(histfd, sprinkle, 2) != 2) { 817c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 818c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 821c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 822c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_init_tail: 823c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_PERSISTENT_HISTORY 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 829c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * load the history structure from the stored data 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 832c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserhistload(Source *s, unsigned char *base, size_t bytes) 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 834c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int lno = 0, lines = 0; 835c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char *cp; 836c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 837c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histload_loop: 838c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* !bytes check as some systems (older FreeBSDs) have buggy memchr */ 839c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!bytes || (cp = memchr(base, COMMAND, bytes)) == NULL) 840c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (lines); 841c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* advance base pointer past COMMAND byte */ 842c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes -= ++cp - base; 843c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = cp; 844c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* if there is no full string left, don't bother with the rest */ 845c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (bytes < 5 || (cp = memchr(base + 4, '\0', bytes - 4)) == NULL) 846c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (lines); 847c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* load the stored line number */ 848c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lno = ((base[0] & 0xFF) << 24) | ((base[1] & 0xFF) << 16) | 849c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ((base[2] & 0xFF) << 8) | (base[3] & 0xFF); 850c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* store away the found line (@base[4]) */ 851c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++lines; 852c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histptr >= history && lno - 1 != s->line) { 853c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* a replacement? */ 854c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char **hp; 855c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 856c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (lno >= s->line - (histptr - history) && lno <= s->line) { 857c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hp = &histptr[lno - s->line]; 858c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (*hp) 859c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(*hp, APERM); 860c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(*hp, (char *)(base + 4), APERM); 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 862c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 863c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser s->line = lno--; 864c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histsave(&lno, (char *)(base + 4), false, false); 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 866c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* advance base pointer past NUL */ 867c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes -= ++cp - base; 868c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = cp; 869c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* repeat until no more */ 870c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto histload_loop; 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 874c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * write a command to the end of the history file 875c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * 876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * This *MAY* seem easy but it's also necessary to check 877c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * that the history file has not changed in size. 878c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * If it has - then some other shell has written to it and 879c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * we should (re)read those commands to update our history 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 882c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserwritehistfile(int lno, const char *cmd) 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 88403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra off_t sizenow; 885c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t bytes; 886c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char *base, *news; 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 888c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_lockfd(histfd); 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sizenow = lseek(histfd, (off_t)0, SEEK_END); 890c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (sizenow < histfsize) { 891c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* the file has shrunk; give up */ 892c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto bad; 893c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 894c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ( 895c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* ignore changes when the file is too large */ 896c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sizenow <= MKSH_MAXHISTFSIZE 897c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser && 898c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* the size has changed, we need to do read updates */ 899c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser sizenow > histfsize 900c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ) { 901c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* both sizenow and histfsize are <= MKSH_MAXHISTFSIZE */ 902c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes = (size_t)(sizenow - histfsize); 903c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser base = (void *)mmap(NULL, (size_t)sizenow, PROT_READ, 904c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser MAP_FILE | MAP_PRIVATE, histfd, (off_t)0); 905c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (base == (unsigned char *)MAP_FAILED) 906c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto bad; 907c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser news = base + (size_t)histfsize; 908c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (*news == COMMAND) { 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line--; 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru histload(hist_source, news, bytes); 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru hist_source->line++; 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru lno = hist_source->line; 913c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 914c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bytes = 0; 915c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser munmap(caddr_cast(base), (size_t)sizenow); 916c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!bytes) 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto bad; 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 919c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (cmd && !writehistline(histfd, lno, cmd)) { 9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bad: 921c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hist_finish(); 922c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 924c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfsize = lseek(histfd, (off_t)0, SEEK_END); 925c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 928c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic int 929c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserwritehistline(int fd, int lno, const char *cmd) 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 931c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ssize_t n; 932c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char hdr[5]; 933c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 934c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[0] = COMMAND; 935c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[1] = (lno >> 24) & 0xFF; 936c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[2] = (lno >> 16) & 0xFF; 937c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[3] = (lno >> 8) & 0xFF; 938c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser hdr[4] = lno & 0xFF; 939c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser n = strlen(cmd) + 1; 940c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (write(fd, hdr, 5) == 5 && write(fd, cmd, n) == n); 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 943c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 944c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserhist_finish(void) 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 946c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (histfd >= 0) { 947c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mksh_unlkfd(histfd); 948c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)close(histfd); 949c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 950c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser histfd = -1; 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 954c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_SYS_SIGNAME 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const struct mksh_sigpair { 957c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const char * const name; 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nr; 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} mksh_sigpairs[] = { 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "signames.inc" 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru { NULL, 0 } 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 965c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_SYS_SIGLIST 966c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if !HAVE_SYS_SIGLIST_DECL 967c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserextern const char * const sys_siglist[]; 968c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 969c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 970c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinittraps(void) 9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *cs; 9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 97703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trap_exstat = -1; 97803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Populate sigtraps based on sys_signame and sys_siglist. */ 980427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes /*XXX this is idiotic, use a multi-key/value hashtable! */ 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i <= NSIG; i++) { 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].signal = i; 98303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGERR) { 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = "ERR"; 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = "Error handler"; 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGNAME 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs = sys_signame[i]; 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct mksh_sigpair *pair = mksh_sigpairs; 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((pair->nr != i) && (pair->name != NULL)) 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++pair; 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs = pair->name; 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cs == NULL) || 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (cs[0] == '\0')) 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = shf_smprintf("%d", i); 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *s; 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1001c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* this is not optimal, what about SIGSIG1? */ 1002c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((cs[0] & 0xDF) == 'S' && 1003c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[1] & 0xDF) == 'I' && 1004c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[2] & 0xDF) == 'G' && 1005c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs[3] != '\0') { 1006c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* skip leading "SIG" */ 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cs += 3; 1008c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strdupx(s, cs, APERM); 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].name = s; 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((*s = ksh_toupper(*s))) 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++s; 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SYS_SIGLIST 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = sys_siglist[i]; 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#elif HAVE_STRSIGNAL 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = strsignal(i); 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[i].mess = NULL; 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((sigtraps[i].mess == NULL) || 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (sigtraps[i].mess[0] == '\0')) 102303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[i].mess = shf_smprintf("%s %d", 102403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "Signal", i); 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 102703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* our name for signal 0 */ 102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[ksh_SIGEXIT].name = "EXIT"; 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (void)sigemptyset(&Sigact_ign.sa_mask); 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sigact_ign.sa_flags = 0; /* interruptible */ 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Sigact_ign.sa_handler = SIG_IGN; 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGINT].flags |= TF_DFL_INTR | TF_TTY_INTR; 10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGQUIT].flags |= TF_DFL_INTR | TF_TTY_INTR; 103603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIGTERM is not fatal for interactive */ 103703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigtraps[SIGTERM].flags |= TF_DFL_INTR; 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGHUP].flags |= TF_FATAL; 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGCHLD].flags |= TF_SHELL_USES; 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* these are always caught so we can clean up any temporary files. */ 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGINT], trapsig, SS_RESTORE_ORIG); 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGQUIT], trapsig, SS_RESTORE_ORIG); 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGTERM], trapsig, SS_RESTORE_ORIG); 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGHUP], trapsig, SS_RESTORE_ORIG); 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void alarm_catcher(int sig); 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_init(void) 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigtraps[SIGALRM].flags |= TF_SHELL_USES; 10545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGALRM], alarm_catcher, 10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_ORIG|SS_FORCE|SS_SHTRAP); 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* ARGSUSED */ 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querualarm_catcher(int sig MKSH_A_UNUSED) 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* this runs inside interrupt context, with errno saved */ 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_tmout_state == TMOUT_READING) { 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int left = alarm(0); 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (left == 0) { 10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_LEAVING; 10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru alarm(left); 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste QueruTrap * 1076c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasergettrap(const char *cs, bool igncase) 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1078c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int i; 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 1080c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *as; 10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1082c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (ksh_isdigit(*cs)) { 1083c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return ((getn(cs, &i) && 0 <= i && i < NSIG) ? 1084c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (&sigtraps[i]) : NULL); 10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1087c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* this breaks SIGSIG1, but we do that above anyway */ 1088c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((cs[0] & 0xDF) == 'S' && 1089c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[1] & 0xDF) == 'I' && 1090c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (cs[2] & 0xDF) == 'G' && 1091c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs[3] != '\0') { 1092c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* skip leading "SIG" */ 1093c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs += 3; 1094c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1095c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (igncase) { 1096c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *s; 1097c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1098c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser strdupx(as, cs, ATEMP); 1099c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser cs = s = as; 1100c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((*s = ksh_toupper(*s))) 1101c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++s; 1102c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 1103c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser as = NULL; 1104c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1105c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = sigtraps; 1106c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser for (i = 0; i <= NSIG; i++) { 1107c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!strcmp(p->name, cs)) 1108c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser goto found; 1109c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++p; 1110c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1111c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = NULL; 1112c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser found: 1113c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser afree(as, ATEMP); 1114c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (p); 11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * trap signal handler 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrapsig(int i) 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p = &sigtraps[i]; 1124c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int eno = errno; 11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = p->set = 1; 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_DFL_INTR) 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_FATAL) && !p->trap) { 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 1; 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 1; 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->shtrap) 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p->shtrap)(i); 1135c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser errno = eno; 11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called when we want to allow the user to ^C out of something - won't 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * work if user has trapped SIGINT. 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruintrcheck(void) 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (intrsig) 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru runtraps(TF_DFL_INTR|TF_FATAL); 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * called after EINTR to check if a signal with normally causes process 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * termination has been received. 11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 11545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querufatal_trap_check(void) 11555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* todo: should check if signal is fatal, not the TF_DFL_INTR flag */ 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && (p->flags & (TF_DFL_INTR|TF_FATAL))) 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* return value is used as an exit code */ 11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (128 + p->signal); 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Returns the signal number of any pending traps: ie, a signal which has 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * occurred for which a trap has been set or for which the TF_DFL_INTR flag 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is set. 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querutrap_pending(void) 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 11795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && ((p->trap && p->trap[0]) || 11805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((p->flags & (TF_DFL_INTR|TF_FATAL)) && !p->trap))) 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p->signal); 11825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 11835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * run any pending traps. If intr is set, only run traps that 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * can interrupt commands. 11885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruruntraps(int flag) 11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_tmout_state == TMOUT_LEAVING) { 11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_EXECUTING; 11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru warningf(false, "timed out waiting for input"); 11985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LEXIT); 11995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * XXX: this means the alarm will have no effect if a trap 12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is caught after the alarm() was started...not good. 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_tmout_state = TMOUT_EXECUTING; 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!flag) 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = 0; 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag & TF_DFL_INTR) 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 0; 12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag & TF_FATAL) 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 0; 121103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++trap_nested; 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = sigtraps, i = NSIG+1; --i >= 0; p++) 12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->set && (!flag || 12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ((p->flags & flag) && p->trap == NULL))) 121503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(p, false); 121603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!--trap_nested) 121703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra runtrap(NULL, true); 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 122103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraruntrap(Trap *p, bool is_last) 12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 122303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int old_changed = 0, i; 122403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *trapstr; 122503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 122603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p == NULL) 122703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just clean up, see runtraps() above */ 122803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 122903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra i = p->signal; 123003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trapstr = p->trap; 12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->set = 0; 123203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trapstr == NULL) { 123303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIG_DFL */ 12345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_FATAL) { 12355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* eg, SIGHUP */ 1236c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = (int)ksh_min(128U + (unsigned)i, 255U); 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LLEAVE); 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_DFL_INTR) { 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* eg, SIGINT, SIGQUIT, SIGTERM, etc. */ 1241c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser exstat = (int)ksh_min(128U + (unsigned)i, 255U); 12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unwind(LINTR); 12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 124403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 124603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trapstr[0] == '\0') 124703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* SIG_IGN */ 124803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto donetrap; 124903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 125003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* avoid recursion on these */ 12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru old_changed = p->flags & TF_CHANGED; 12525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~TF_CHANGED; 12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->trap = NULL; 12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 125503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (trap_exstat == -1) 1256c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser trap_exstat = exstat & 0xFF; 12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note: trapstr is fully parsed before anything is executed, thus 12595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * no problem with afree(p->trap) in settrap() while still in use. 12605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru command(trapstr, current_lineno); 126203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (i == ksh_SIGEXIT || i == ksh_SIGERR) { 12635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_CHANGED) 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* don't clear TF_CHANGED */ 12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(trapstr, APERM); 12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->trap = trapstr; 12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= old_changed; 12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 127003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 127103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra donetrap: 127203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we're the last trap of a sequence executed */ 127303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (is_last && trap_exstat != -1) { 127403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra exstat = trap_exstat; 127503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra trap_exstat = -1; 127603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* clear pending traps and reset user's trap handlers; used after fork(2) */ 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucleartraps(void) 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru trap = 0; 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru intrsig = 0; 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fatal_trap = 0; 12895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = NSIG+1, p = sigtraps; --i >= 0; p++) { 12905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->set = 0; 12915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_USER_SET) && (p->trap && p->trap[0])) 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru settrap(p, NULL); 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* restore signals just before an exec(2) */ 12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestoresigs(void) 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i; 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p; 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = NSIG+1, p = sigtraps; --i >= 0; p++) 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & (TF_EXEC_IGN|TF_EXEC_DFL)) 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, (p->flags & TF_EXEC_IGN) ? SIG_IGN : SIG_DFL, 13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru SS_RESTORE_CURR|SS_FORCE); 13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusettrap(Trap *p, const char *s) 13115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sig_t f; 13135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->trap) 13155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(p->trap, APERM); 131603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* handles s == NULL */ 131703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(p->trap, s, APERM); 13185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_CHANGED; 13195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = !s ? SIG_DFL : s[0] ? trapsig : SIG_IGN; 13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_USER_SET; 13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & (TF_DFL_INTR|TF_FATAL)) && f == SIG_DFL) 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = trapsig; 13245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (p->flags & TF_SHELL_USES) { 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & TF_ORIG_IGN) || Flag(FTALKING)) { 13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* do what user wants at exec time */ 13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f == SIG_IGN) 13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_IGN; 13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_DFL; 13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 13355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * assumes handler already set to what shell wants it 13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (normally trapsig, but could be j_sigchld() or SIG_IGN) 13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* todo: should we let user know signal is ignored? how? */ 13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, f, SS_RESTORE_CURR|SS_USER); 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Called by c_print() when writing to a co-process to ensure SIGPIPE won't 13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * kill shell (unless user catches it and exits) 13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querublock_pipe(void) 13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int restore_dfl = 0; 13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Trap *p = &sigtraps[SIGPIPE]; 13545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 13565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, SIG_IGN, SS_RESTORE_CURR); 13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->flags & TF_ORIG_DFL) 13585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru restore_dfl = 1; 13595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (p->cursig == SIG_DFL) { 13605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(p, SIG_IGN, SS_RESTORE_CURR); 136103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* restore to SIG_DFL */ 136203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra restore_dfl = 1; 13635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (restore_dfl); 13655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Called by c_print() to undo whatever block_pipe() did */ 13685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 13695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querurestore_pipe(int restore_dfl) 13705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (restore_dfl) 13725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setsig(&sigtraps[SIGPIPE], SIG_DFL, SS_RESTORE_CURR); 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Set action for a signal. Action may not be set if original 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * action was SIG_IGN, depending on the value of flags and FTALKING. 13785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetsig(Trap *p, sig_t f, int flags) 13815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct sigaction sigact; 13835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 138403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p->signal == ksh_SIGEXIT || p->signal == ksh_SIGERR) 13855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 13865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1387c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&sigact, 0, sizeof(sigact)); 1388c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 13895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 13905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * First time setting this signal? If so, get and note the current 13915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * setting. 13925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) { 13945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigaction(p->signal, &Sigact_ign, &sigact); 13955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= sigact.sa_handler == SIG_IGN ? 13965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru TF_ORIG_IGN : TF_ORIG_DFL; 13975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->cursig = SIG_IGN; 13985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /*- 14015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Generally, an ignored signal stays ignored, except if 14025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the user of an interactive shell wants to change it 14035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the shell wants for force a change 14045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((p->flags & TF_ORIG_IGN) && !(flags & SS_FORCE) && 14065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!(flags & SS_USER) || !Flag(FTALKING))) 14075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 14085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setexecsig(p, flags & SS_RESTORE_MASK); 14105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 14125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is here 'cause there should be a way of clearing 14135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * shtraps, but don't know if this is a sane way of doing 14145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * it. At the moment, all users of shtrap are lifetime 14155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * users (SIGALRM, SIGCHLD, SIGWINCH). 14165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 14175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags & SS_USER)) 14185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->shtrap = (sig_t)NULL; 14195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flags & SS_SHTRAP) { 14205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->shtrap = f; 14215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f = trapsig; 14225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p->cursig != f) { 14255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->cursig = f; 14265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (void)sigemptyset(&sigact.sa_mask); 142703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* interruptible */ 142803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sigact.sa_flags = 0; 14295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigact.sa_handler = f; 14305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sigaction(p->signal, &sigact, NULL); 14315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 14345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 14355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* control what signal is set to before an exec() */ 14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetexecsig(Trap *p, int restore) 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX debugging */ 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(p->flags & (TF_ORIG_IGN|TF_ORIG_DFL))) 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("setexecsig: unset signal %d(%s)", 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->signal, p->name); 14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* restore original value for exec'd kids */ 14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags &= ~(TF_EXEC_IGN|TF_EXEC_DFL); 14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (restore & SS_RESTORE_MASK) { 144803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case SS_RESTORE_CURR: 144903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* leave things as they currently are */ 14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_ORIG: 14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= p->flags & TF_ORIG_IGN ? TF_EXEC_IGN : TF_EXEC_DFL; 14535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_DFL: 14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_DFL; 14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case SS_RESTORE_IGN: 14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p->flags |= TF_EXEC_IGN; 14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1462c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1463c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_PERSISTENT_HISTORY || defined(DF) 1464c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* 1465c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * File descriptor locking and unlocking functions. 1466c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Could use some error handling, but hey, this is only 1467c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * advisory locking anyway, will often not work over NFS, 1468c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * and you are SOL if this fails... 1469c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 1470c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1471c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1472c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_lockfd(int fd) 1473c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1474c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(__OpenBSD__) 1475c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* flock is not interrupted by signals */ 1476c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)flock(fd, LOCK_EX); 1477c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_FLOCK 1478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int rv; 1479c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1480c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* e.g. on Linux */ 1481c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do { 1482c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = flock(fd, LOCK_EX); 1483c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } while (rv == 1 && errno == EINTR); 1484c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_LOCK_FCNTL 1485c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser int rv; 1486c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct flock lks; 1487c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1488c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&lks, 0, sizeof(lks)); 1489c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lks.l_type = F_WRLCK; 1490c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser do { 1491c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser rv = fcntl(fd, F_SETLKW, &lks); 1492c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } while (rv == 1 && errno == EINTR); 1493c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1494c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1495c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1496c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser/* designed to not define mksh_unlkfd if none triggered */ 1497c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if HAVE_FLOCK 1498c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1499c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_unlkfd(int fd) 1500c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1501c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)flock(fd, LOCK_UN); 1502c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1503c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#elif HAVE_LOCK_FCNTL 1504c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaservoid 1505c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasermksh_unlkfd(int fd) 1506c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser{ 1507c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser struct flock lks; 1508c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1509c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser memset(&lks, 0, sizeof(lks)); 1510c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser lks.l_type = F_UNLCK; 1511c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser (void)fcntl(fd, F_SETLKW, &lks); 1512c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser} 1513c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1514c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1515