1427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes/* $OpenBSD: misc.c,v 1.38 2013/11/28 10:33:37 sobrado Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */ 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 5c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 6427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes * 2011, 2012, 2013, 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" 265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_GETRUSAGE 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <sys/times.h> 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_GRP_H 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <grp.h> 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 33427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.219 2014/01/05 21:57:27 tg Exp $"); 34c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 35c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define KSH_CHVT_FLAG 36c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH_SMALL 37c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#undef KSH_CHVT_FLAG 38c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 39c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef TIOCSCTTY 40c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define KSH_CHVT_CODE 41c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define KSH_CHVT_FLAG 42c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 43c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH_LEGACY_MODE 44c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#undef KSH_CHVT_CODE 45c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#undef KSH_CHVT_FLAG 46c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* type bits for unsigned char */ 4903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraunsigned char chtypes[UCHAR_MAX + 1]; 505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const unsigned char *pat_scan(const unsigned char *, 52427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes const unsigned char *, bool) MKSH_A_PURE; 535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int do_gmatch(const unsigned char *, const unsigned char *, 54427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes const unsigned char *, const unsigned char *) MKSH_A_PURE; 55427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughesstatic const unsigned char *cclass(const unsigned char *, unsigned char) 56427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes MKSH_A_PURE; 57c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef KSH_CHVT_CODE 58811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserstatic void chvt(const Getopt *); 595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*XXX this should go away */ 6203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int make_path(const char *, const char *, char **, XString *, int *); 6303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 6403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef SETUID_CAN_FAIL_WITH_EAGAIN 6503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* we don't need to check for other codes, EPERM won't happen */ 6603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define DO_SETUID(func, argvec) do { \ 6703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((func argvec) && errno == EAGAIN) \ 6803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s failed with EAGAIN, probably due to a" \ 6903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra " too low process limit; aborting", #func); \ 7003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0) 7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define DO_SETUID(func, argvec) func argvec 7303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 7403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Fast character classes 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetctypes(const char *s, int t) 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int i; 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t & C_IFS) { 845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < UCHAR_MAX + 1; i++) 855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[i] &= ~C_IFS; 8603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* include \0 in C_IFS */ 8703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra chtypes[0] |= C_IFS; 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s != 0) 905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[(unsigned char)*s++] |= t; 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitctypes(void) 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 'a'; c <= 'z'; c++) 995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[c] |= C_ALPHA; 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 'A'; c <= 'Z'; c++) 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[c] |= C_ALPHA; 1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes['_'] |= C_ALPHA; 1035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("0123456789", C_DIGIT); 10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* \0 added automatically */ 105c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser setctypes(TC_LEX1, C_LEX1); 1065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("*@#!$-?", C_VAR1); 107c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser setctypes(TC_IFSWS, C_IFSWS); 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("=-+?", C_SUBOP1); 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("\t\n \"#$&'()*;<=>?[\\]`|", C_QUOTE); 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* called from XcheckN() to grow buffer */ 1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 114c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten GlaserXcheck_grow(XString *xsp, const char *xp, size_t more) 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *old_beg = xsp->beg; 1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (more < xsp->len) 11903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra more = xsp->len; 12003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* (xsp->len + X_EXTRA) never overflows */ 12103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra checkoktoadd(more, xsp->len + X_EXTRA); 12203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xsp->beg = aresize(xsp->beg, (xsp->len += more) + X_EXTRA, xsp->areap); 1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xsp->end = xsp->beg + xsp->len; 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (xsp->beg + (xp - old_beg)); 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 127811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHFLAGS_DEFNS 129427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#include "sh_flags.gen" 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 131811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define OFC(i) (options[i][-2]) 132811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define OFF(i) (((const unsigned char *)options[i])[-1]) 133811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#define OFN(i) (options[i]) 134811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 135811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserconst char * const options[] = { 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHFLAGS_ITEMS 137427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#include "sh_flags.gen" 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * translate -o option into F* constant (also used for test -o option) 1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusize_t 1445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruoption(const char *n) 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 146811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser size_t i = 0; 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 148811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((n[0] == '-' || n[0] == '+') && n[1] && !n[2]) 149811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (i < NELEM(options)) { 150811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (OFC(i) == n[1]) 151811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return (i); 152811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++i; 153811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 154811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else 155811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (i < NELEM(options)) { 156811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!strcmp(OFN(i), n)) 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (i); 158811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++i; 159811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((size_t)-1); 1625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct options_info { 1655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int opt_width; 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int opts[NELEM(options)]; 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 169c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstatic char *options_fmt_entry(char *, size_t, unsigned int, const void *); 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void printoptions(bool); 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* format a single select menu item */ 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 174c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaseroptions_fmt_entry(char *buf, size_t buflen, unsigned int i, const void *arg) 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct options_info *oi = (const struct options_info *)arg; 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_snprintf(buf, buflen, "%-*s %s", 179811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser oi->opt_width, OFN(oi->opts[i]), 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(oi->opts[i]) ? "on" : "off"); 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (buf); 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprintoptions(bool verbose) 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 18703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t i = 0; 1885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (verbose) { 190c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t n = 0, len, octs = 0; 1915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct options_info oi; 1925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* verbose version */ 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_puts("Current option settings\n", shl_stdout); 1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi.opt_width = 0; 19703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (i < NELEM(options)) { 198811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((len = strlen(OFN(i)))) { 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi.opts[n++] = i; 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (len > octs) 2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru octs = len; 202811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser len = utf_mbswidth(OFN(i)); 203c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((int)len > oi.opt_width) 204c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser oi.opt_width = (int)len; 2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++i; 2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru print_columns(shl_stdout, n, options_fmt_entry, &oi, 2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru octs + 4, oi.opt_width + 4, true); 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 21103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* short version like AT&T ksh93 */ 21203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_puts(Tset, shl_stdout); 213811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (i < NELEM(options)) { 214811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (Flag(i) && OFN(i)[0]) 215811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shprintf(" -o %s", OFN(i)); 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++i; 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\n', shl_stdout); 2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetoptions(void) 2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 225811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser size_t i = 0; 226811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char c, m[(int)FNFLAGS + 1]; 2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp = m; 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 229811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser while (i < NELEM(options)) { 230811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((c = OFC(i)) && Flag(i)) 231811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *cp++ = c; 232811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++i; 233811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(cp, m, cp - m, ATEMP); 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (cp); 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* change a Flag(*) value; takes care of special actions */ 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 240c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserchange_flag(enum sh_flag f, int what, bool newset) 2415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char oldval; 243811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser unsigned char newval = (newset ? 1 : 0); 2445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (f == FXTRACE) { 246811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(newval, true); 247811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return; 248811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 2495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oldval = Flag(f); 250c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Flag(f) = newval = (newset ? 1 : 0); 2515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f == FMONITOR) { 2535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what != OF_CMDLINE && newval != oldval) 2545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_change(); 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 257c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH_NO_CMDLINE_EDITING 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (( 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f == FVI || 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f == FEMACS || f == FGMACS) && newval) { 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FVI) = 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FEMACS) = Flag(FGMACS) = 0; 267c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Flag(f) = newval; 268c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 269c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 270c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (f == FPRIVILEGED && oldval && !newval) { 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Turning off -p? */ 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 27303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX this can probably be optimised */ 27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshegid = kshgid = getgid(); 275427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes ksheuid = kshuid = getuid(); 27603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SETRESUGID 27703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setresgid, (kshegid, kshegid, kshegid)); 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SETGROUPS 27903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* setgroups doesn't EAGAIN on Linux */ 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setgroups(1, &kshegid); 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 28203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid)); 283427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#else /* !HAVE_SETRESUGID */ 28403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* seteuid, setegid, setgid don't EAGAIN on Linux */ 285c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH__NO_SETEUGID 286c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser seteuid(ksheuid); 287c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 28803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setuid, (ksheuid)); 289c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH__NO_SETEUGID 29003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setegid(kshegid); 291c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setgid(kshegid); 293427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#endif /* !HAVE_SETRESUGID */ 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((f == FPOSIX || f == FSH) && newval) { 295811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* Turning on -o posix or -o sh? */ 296811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser Flag(FBRACEEXPAND) = 0; 297811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } else if (f == FTALKING) { 298811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* Changing interactive flag? */ 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid) 300c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser Flag(FTALKING_I) = newval; 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 304811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaservoid 305811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserchange_xtrace(unsigned char newval, bool dosnapshot) 306811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser{ 307811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!dosnapshot && newval == Flag(FXTRACE)) 308811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return; 309811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 310811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (Flag(FXTRACE) == 2) { 311811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_putc('\n', shl_xtrace); 312811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser Flag(FXTRACE) = 1; 313811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_flush(shl_xtrace); 314811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 315811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 316811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!dosnapshot && Flag(FXTRACE) == 1) 317811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch (newval) { 318811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case 1: 319811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser return; 320811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case 2: 321811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser goto changed_xtrace; 322811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 323811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 324811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_flush(shl_xtrace); 325811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (shl_xtrace->fd != 2) 326811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser close(shl_xtrace->fd); 327811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (!newval || (shl_xtrace->fd = savefd(2)) == -1) 328811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shl_xtrace->fd = 2; 329811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 330811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser changed_xtrace: 331811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((Flag(FXTRACE) = newval) == 2) 332811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_puts(substitute(str_val(global("PS4")), 0), shl_xtrace); 333811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser} 334811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 33503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 33603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Parse command line and set command arguments. Returns the index of 3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-option arguments, -1 if there is an error. 3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruparse_args(const char **argv, 34103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* OF_CMDLINE or OF_SET */ 34203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int what, 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool *setargsp) 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 345427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes static const char cmd_opts[] = 346427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#define SHFLAGS_NOT_SET 347427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#define SHFLAGS_OPTCS 348427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#include "sh_flags.gen" 349427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#undef SHFLAGS_NOT_SET 350427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes ; 351427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes static const char set_opts[] = 352427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#define SHFLAGS_NOT_CMD 353427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#define SHFLAGS_OPTCS 354427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#include "sh_flags.gen" 355427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes#undef SHFLAGS_NOT_CMD 356427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes ; 357c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool set; 358427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes const char *opts; 3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *array = NULL; 3605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Getopt go; 3615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t i; 36203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int optc, arrayset = 0; 36303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool sortargs = false; 364811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser bool fcompatseen = false; 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_CMDLINE) { 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p = argv[0], *q; 36803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 36903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set FLOGIN before parsing options so user can clear 3705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * flag using +l. 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*p != '-') 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (q = p; *q; ) 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*q++ == '/') 3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = q; 3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FLOGIN) = (*p == '-'); 3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = cmd_opts; 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (what == OF_FIRSTTIME) { 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = cmd_opts; 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = set_opts; 3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT); 3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((optc = ksh_getopt(argv, &go, opts)) != -1) { 384c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser set = tobool(!(go.info & GI_PLUS)); 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (optc) { 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'A': 3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru arrayset = set ? 1 : -1; 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru array = go.optarg; 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'o': 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go.optarg == NULL) { 39703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 39803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * lone -o: print options 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that on the command line, -o requires 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * an option (ie, can't get here if what is 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * OF_CMDLINE). 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru printoptions(set); 4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = option(go.optarg); 408811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if ((i == FPOSIX || i == FSH) && set && !fcompatseen) { 409811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* 410811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * If running 'set -o posix' or 411811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * 'set -o sh', turn off the other; 412811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * if running 'set -o posix -o sh' 413811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser * allow both to be set though. 414811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser */ 415811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser Flag(FPOSIX) = 0; 416811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser Flag(FSH) = 0; 417811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser fcompatseen = true; 418811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 419c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((i != (size_t)-1) && (set ? 1U : 0U) == Flag(i)) 42003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 42103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Don't check the context if the flag 4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * isn't changing - makes "set -o interactive" 4235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * work if you're already interactive. Needed 4245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if the output of "set +o" is to be used. 4255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 4265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 427811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser else if ((i != (size_t)-1) && (OFF(i) & what)) 4285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag((enum sh_flag)i, what, set); 4295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 43003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", go.optarg, "bad option"); 4315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 435c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef KSH_CHVT_FLAG 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'T': 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what != OF_FIRSTTIME) 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 439c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef KSH_CHVT_CODE 4405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("no TIOCSCTTY ioctl"); 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 442c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser change_flag(FTALKING, OF_CMDLINE, true); 443811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser chvt(&go); 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* -s: sort positional params (AT&T ksh stupidity) */ 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_SET && optc == 's') { 45603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sortargs = true; 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < NELEM(options); i++) 460811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (optc == OFC(i) && 461811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser (what & OFF(i))) { 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag((enum sh_flag)i, what, set); 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == NELEM(options)) 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("parse_args: '%c'", optc); 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(go.info & GI_MINUSMINUS) && argv[go.optind] && 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') && 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv[go.optind][1] == '\0') { 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* lone - clears -v and -x flags */ 473811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (argv[go.optind][0] == '-') { 474811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser Flag(FVERBOSE) = 0; 475811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser change_xtrace(0, false); 476811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* set skips lone - or + option */ 4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go.optind++; 4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setargsp) 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* -- means set $#/$* even if there are no arguments */ 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *setargsp = !arrayset && ((go.info & GI_MINUSMINUS) || 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv[go.optind]); 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 48503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (arrayset) { 48603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *ccp = NULL; 48703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 488c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser mkssert(array != NULL); 48903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*array) 49003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = skip_varname(array, false); 49103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ccp || !(!ccp[0] || (ccp[0] == '+' && !ccp[1]))) { 49203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", array, "is not an identifier"); 49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-1); 49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 4955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sortargs) { 4975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = go.optind; argv[i]; i++) 4985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 4995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru qsort(&argv[go.optind], i - go.optind, sizeof(void *), 5005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xstrcmp); 5015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 5025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (arrayset) 50303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra go.optind += set_array(array, tobool(arrayset > 0), 5045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv + go.optind); 5055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (go.optind); 5075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */ 5105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 5115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetn(const char *s, int *ai) 5125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 513c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char c; 514811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser mksh_ari_u num; 5155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool neg = false; 5165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 517811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser num.u = 0; 518811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 5195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 5205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *s++; 5215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (ksh_isspace(c)); 522c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 523c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser switch (c) { 524c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '-': 5255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru neg = true; 526c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 527c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '+': 5285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *s++; 529c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 530c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 531c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 5325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 5335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ksh_isdigit(c)) 534c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* not numeric */ 535c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (0); 536811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (num.u > 214748364U) 537c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* overflow on multiplication */ 538c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (0); 539811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser num.u = num.u * 10U + (unsigned int)(c - '0'); 540811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* now: num.u <= 2147483649U */ 5415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while ((c = *s++)); 5425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 543811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (num.u > (neg ? 2147483648U : 2147483647U)) 544c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* overflow for signed 32-bit int */ 545c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (0); 5465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 547811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (neg) 548811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser num.u = -num.u; 549811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser *ai = num.i; 550c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (1); 5515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 5525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 55303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 55403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * pattern simplifications: 55503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - @(x) -> x (not @(x|y) though) 55603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - ** -> * 55703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 55803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void * 55903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasimplify_gmatch_pattern(const unsigned char *sp) 56003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 56103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra uint8_t c; 56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unsigned char *cp, *dp; 56303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const unsigned char *ps, *se; 56403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 56503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = alloc(strlen((const void *)sp) + 1, ATEMP); 56603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto simplify_gmatch_pat1a; 56703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 56803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* foo@(b@(a)r)b@(a|a)z -> foobarb@(a|a)z */ 56903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_gmatch_pat1: 57003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = cp; 57103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_gmatch_pat1a: 57203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp = cp; 57303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra se = sp + strlen((const void *)sp); 57403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((c = *sp++)) { 57503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ISMAGIC(c)) { 57603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 57703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 57803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 57903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch ((c = *sp++)) { 58003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'@': 58103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @ */ 58203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|' ': 58303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check whether it has only one clause */ 58403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ps = pat_scan(sp, se, true); 58503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ps || ps[-1] != /*(*/ ')') 58603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* nope */ 58703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 58803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* copy inner clause until matching close */ 58903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ps -= 2; 59003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((const unsigned char *)sp < ps) 59103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = *sp++; 59203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip MAGIC and closing parenthesis */ 59303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp += 2; 59403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* copy the rest of the pattern */ 59503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memmove(dp, sp, strlen((const void *)sp) + 1); 59603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* redo from start */ 59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto simplify_gmatch_pat1; 59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 60103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 60403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* collapse adjacent asterisk wildcards */ 60503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = dp = cp; 60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((c = *sp++)) { 60703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ISMAGIC(c)) { 60803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 60903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 61003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 61103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch ((c = *sp++)) { 61203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '*': 61303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (ISMAGIC(sp[0]) && sp[1] == c) 61403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp += 2; 61503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 61603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 61703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 61803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 61903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 62003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 62103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 62203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* return the result, allocated from ATEMP */ 62303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (cp); 62403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 62503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 6265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* -------- gmatch.c -------- */ 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * int gmatch(string, pattern) 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * char *string, *pattern; 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Match a pattern as in sh(1). 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * pattern character are prefixed with MAGIC by expand. 6345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugmatchx(const char *s, const char *p, bool isfile) 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *se, *pe; 63903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *pnew; 64003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int rv; 6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s == NULL || p == NULL) 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se = s + strlen(s); 6465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pe = p + strlen(p); 64703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 64803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * isfile is false iff no syntax check has been done on 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the pattern. If check fails, just to a strcmp(). 6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!isfile && !has_globbing(p, pe)) { 6525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len = pe - p + 1; 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char tbuf[64]; 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *t = len <= sizeof(tbuf) ? tbuf : alloc(len, ATEMP); 6555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(t, p, len); 6565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (!strcmp(t, s)); 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 65803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 65903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 66003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * since the do_gmatch() engine sucks so much, we must do some 66103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * pattern simplifications 66203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 66303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnew = simplify_gmatch_pattern((const unsigned char *)p); 66403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pe = pnew + strlen(pnew); 66503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 66603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = do_gmatch((const unsigned char *)s, (const unsigned char *)se, 66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (const unsigned char *)pnew, (const unsigned char *)pe); 66803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(pnew, ATEMP); 66903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 67303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Returns if p is a syntacticly correct globbing pattern, false 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if it contains no pattern characters or if there is a syntax error. 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Syntax errors are: 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - [ with no closing ] 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - imbalanced $(...) expression 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d)) 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*XXX 68103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - if no magic, 68203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if dest given, copy to dst 68303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return ? 68403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - if magic && (no globbing || syntax error) 68503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * debunk to dst 68603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return ? 68703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - return ? 68803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhas_globbing(const char *xp, const char *xpe) 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *p = (const unsigned char *) xp; 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *pe = (const unsigned char *) xpe; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nest = 0, bnest = 0; 69603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool saw_glob = false; 69703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* inside [...] */ 69803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool in_bracket = false; 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; p < pe; p++) { 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*p)) 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = *++p) == '*' || c == '?') 70403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c == '[') { 7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!in_bracket) { 70703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 70803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra in_bracket = true; 709c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (ISMAGIC(p[1]) && p[2] == '!') 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(p[1]) && p[2] == ']') 7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 71403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX Do we need to check ranges here? POSIX Q */ 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == ']') { 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) { 71703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (bnest) 71803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* [a*(b]) */ 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 72003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra in_bracket = false; 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((c & 0x80) && vstrchr("*+?@! ", c & 0x7f)) { 72303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bnest++; 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest++; 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '|') { 72903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (in_bracket && !bnest) 73003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* *(a[foo|bar]) */ 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == /*(*/ ')') { 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) { 73403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!bnest--) 73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* *(a[b)c] */ 7365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (nest) 7385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest--; 7395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * else must be a MAGIC-MAGIC, or MAGIC-!, 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * MAGIC--, MAGIC-], MAGIC-{, MAGIC-, MAGIC-} 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (saw_glob && !in_bracket && !nest); 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Function must return either 0 or 1 (assumed by code for 0x80|'!') */ 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudo_gmatch(const unsigned char *s, const unsigned char *se, 7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *p, const unsigned char *pe) 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 753c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char sc, pc; 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *prest, *psub, *pnext; 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *srest; 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s == NULL || p == NULL) 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p < pe) { 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pc = *p++; 7615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sc = s < se ? *s : '\0'; 7625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s++; 7635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(pc)) { 7645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc != pc) 7655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (*p++) { 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '[': 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc == 0 || (p = cclass(p, sc)) == NULL) 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 7755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc == 0) 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --s; 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += utf_ptradj((const void *)s); 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '*': 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p == pe) 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 7875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 7885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, se, p, pe)) 7895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (s++ < se); 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /** 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * [*+?@!](pattern|pattern|..) 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is also needed for ${..%..}, etc. 7965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 79703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 79803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches one or more times */ 79903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'+': 80003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches zero or more times */ 80103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'*': 80203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* take care of zero matches */ 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p[-1] == (0x80 | '*') && 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(s, se, prest, pe)) 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 81003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (srest = s; srest <= se; srest++) { 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, pnext - 2) && 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (do_gmatch(srest, se, prest, pe) || 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (s != srest && do_gmatch(srest, 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se, p - 2, pe)))) 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 82303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches zero or once */ 82403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'?': 82503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches one of the patterns */ 82603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'@': 82703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @ */ 82803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|' ': 82903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Take care of zero matches */ 8335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p[-1] == (0x80 | '?') && 8345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(s, se, prest, pe)) 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 83703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru srest = prest == pe ? se : s; 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; srest <= se; srest++) { 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, pnext - 2) && 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(srest, se, prest, pe)) 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 84903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches none of the patterns */ 85003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'!': 85103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (srest = s; srest <= se; srest++) { 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int matched = 0; 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 85803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pnext - 2)) { 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru matched = 1; 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!matched && 8685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(srest, se, prest, pe)) 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc != p[-1]) 8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (s == se); 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const unsigned char * 883c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glasercclass(const unsigned char *p, unsigned char sub) 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 885c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char c, d; 886c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool notp, found = false; 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *orig_p = p; 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 889c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if ((notp = tobool(ISMAGIC(*p) && *++p == '!'))) 8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p++; 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p++; 8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(c)) { 8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p++; 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c & 0x80) && !ISMAGIC(c)) { 89603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* extended pattern matching: *+?@! */ 89703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c &= 0x7F; 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX the ( char isn't handled as part of [] */ 89903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (c == ' ') 90003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @: plain (..) */ 9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '(' /*)*/; 9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* No closing ] - act as if the opening [ was quoted */ 9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (sub == '[' ? orig_p : NULL); 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(p[0]) && p[1] == '-' && 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!ISMAGIC(p[2]) || p[3] != ']')) { 90903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* MAGIC- */ 91003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra p += 2; 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = *p++; 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(d)) { 9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = *p++; 9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((d & 0x80) && !ISMAGIC(d)) 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d &= 0x7f; 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* POSIX says this is an invalid expression */ 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c > d) 9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = c; 9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == sub || (c <= sub && sub <= d)) 923c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser found = true; 9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (!(ISMAGIC(p[0]) && p[1] == ']')); 9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((found != notp) ? p+2 : NULL); 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */ 93003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const unsigned char * 93103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrapat_scan(const unsigned char *p, const unsigned char *pe, bool match_sep) 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nest = 0; 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; p < pe; p++) { 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*p)) 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*++p == /*(*/ ')' && nest-- == 0) || 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p == '|' && match_sep && nest == 0)) 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p + 1); 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*p & 0x80) && vstrchr("*+?@! ", *p & 0x7f)) 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest++; 9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 9455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruxstrcmp(const void *p1, const void *p2) 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (strcmp(*(const char * const *)p1, *(const char * const *)p2)); 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Initialise a Getopt structure */ 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_getopt_reset(Getopt *go, int flags) 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind = 1; 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->flags = flags; 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info = 0; 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[1] = '\0'; 9635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 96603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 96703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * getopt() used for shell built-in commands, the getopts command, and 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * command line options. 9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * A leading ':' in options means don't print errors, instead return '?' 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * or ':' and set go->optarg to the offending option character. 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * If GF_ERROR is set (and option doesn't start with :), errors result in 9725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a call to bi_errorf(). 9735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Non-standard features: 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - ';' is like ':' in options, except the argument is optional 9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (if it isn't present, optarg is set to 0). 9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'set -o'. 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - ',' is like ':' in options, except the argument always immediately 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * follows the option character (optarg is set to the null string if 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the option is missing). 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'read -u2', 'print -u2' and fc -40. 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - '#' is like ':' in options, expect that the argument is optional 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and must start with a digit. If the argument doesn't start with a 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * digit, it is assumed to be missing and normal option processing 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * continues (optarg is set to 0 if the option is missing). 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'typeset -LZ4'. 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * option starting with + is accepted, the GI_PLUS flag will be set 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in go->info. 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_getopt(const char **argv, Getopt *go, const char *optionsp) 9935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char c; 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *o; 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') { 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *arg = argv[go->optind], flag = arg ? *arg : '\0'; 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 1; 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag == '-' && arg[1] == '-' && arg[2] == '\0') { 10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind++; 10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info |= GI_MINUSMINUS; 10055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (arg == NULL || 100803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ((flag != '-' ) && 100903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* neither a - nor a + (if + allowed) */ 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!(go->flags & GF_PLUSOPT) || flag != '+')) || 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (c = arg[1]) == '\0') { 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind++; 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info &= ~(GI_MINUS|GI_PLUS); 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info |= flag == '-' ? GI_MINUS : GI_PLUS; 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p++; 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#' || 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !(o = cstrchr(optionsp, c))) { 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optionsp[0] == ':') { 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[0] = c; 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = go->buf; 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 102603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s%s-%c: %s", 10275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (go->flags & GF_NONAME) ? "" : argv[0], 102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (go->flags & GF_NONAME) ? "" : ": ", c, 102903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "unknown option"); 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->flags & GF_ERROR) 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorfz(); 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ('?'); 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 103503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /** 103603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * : means argument must be present, may be part of option argument 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * or the next argument 10385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ; same as : but argument may be missing 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * , means argument is part of option argument, and may be null. 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*++o == ':' || *o == ';') { 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind - 1][go->p]) 10435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (argv[go->optind]) 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind++]; 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (*o == ';') 10475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 10485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optionsp[0] == ':') { 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[0] = c; 10515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = go->buf; 10525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (':'); 10535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s%s-%c: %s", 10555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (go->flags & GF_NONAME) ? "" : argv[0], 105603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (go->flags & GF_NONAME) ? "" : ": ", c, 105703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "requires an argument"); 10585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->flags & GF_ERROR) 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorfz(); 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ('?'); 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (*o == ',') { 10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* argument is attached to option character, even if null */ 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (*o == '#') { 106803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 106903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * argument is optional and may be attached or unattached 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * but must start with a digit. optarg is set to 0 if the 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * argument is missing. 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind - 1][go->p]) { 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_isdigit(argv[go->optind - 1][go->p])) { 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 10765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 10795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind] && ksh_isdigit(argv[go->optind][0])) { 10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind++]; 10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (c); 10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 109003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 109103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * print variable/alias value using necessary quotes 10925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (POSIX says they should be suitable for re-entry...) 10935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * No trailing newline is printed. 10945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 1096c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserprint_value_quoted(struct shf *shf, const char *s) 10975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1098c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned char c; 1099c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser const unsigned char *p = (const unsigned char *)s; 1100c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bool inquote = true; 11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 110203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* first, check whether any quotes are needed */ 1103c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((c = *p++) >= 32) 1104c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (ctype(c, C_QUOTE)) 1105c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser inquote = false; 1106c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1107c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p = (const unsigned char *)s; 1108c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c == 0) { 1109c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (inquote) { 1110c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* nope, use the shortcut */ 1111c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_puts(s, shf); 1112c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 1113c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 111403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1115c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* otherwise, quote nicely via state machine */ 1116c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((c = *p++) != 0) { 1117c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c == '\'') { 1118c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* 1119c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * multiple single quotes or any of them 1120c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * at the beginning of a string look nicer 1121c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser * this way than when simply substituting 1122c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser */ 1123c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (inquote) { 1124c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\'', shf); 1125c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser inquote = false; 1126c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1127c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\\', shf); 1128c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else if (!inquote) { 1129c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\'', shf); 1130c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser inquote = true; 1131c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1132c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc(c, shf); 1133c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1134c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else { 1135c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned int wc; 1136c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser size_t n; 1137c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1138c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* use $'...' quote format */ 1139c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('$', shf); 1140c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\'', shf); 1141c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser while ((c = *p) != 0) { 1142c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c >= 0xC2) { 1143c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser n = utf_mbtowc(&wc, (const char *)p); 1144c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (n != (size_t)-1) { 1145c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser p += n; 1146c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_fprintf(shf, "\\u%04X", wc); 1147c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser continue; 1148c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1149c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1150c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser ++p; 1151c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser switch (c) { 1152c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* see unbksl() in this file for comments */ 1153c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case 7: 1154c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'a'; 1155c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1156c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1157c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\b': 1158c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'b'; 1159c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1160c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1161c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\f': 1162c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'f'; 1163c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1164c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1165c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\n': 1166c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'n'; 1167c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1168c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1169c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\r': 1170c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'r'; 1171c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1172c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1173c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\t': 1174c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 't'; 1175c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1176c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1177c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case 11: 1178c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'v'; 1179c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1180c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1181c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\033': 1182c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* take E not e because \e is \ in *roff */ 1183c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser c = 'E'; 1184c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1185c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\\': 1186c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\\', shf); 1187c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1188c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (0) 1189c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1190c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser default: 1191c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (c < 32 || c > 0x7E) { 1192c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser /* FALLTHROUGH */ 1193c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser case '\'': 1194c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_fprintf(shf, "\\%03o", c); 1195c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 1196c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } 1197c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1198c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc(c, shf); 1199c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser break; 120003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1202c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser inquote = true; 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (inquote) 1205c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser shf_putc('\'', shf); 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Print things in columns and rows - func() is called to format 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the i-th element 12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 1213c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserprint_columns(struct shf *shf, unsigned int n, 1214c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser char *(*func)(char *, size_t, unsigned int, const void *), 121503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const void *arg, size_t max_oct, size_t max_colz, bool prefcol) 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1217c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser unsigned int i, r, c, rows, cols, nspace, max_col; 12185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *str; 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1220c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (!n) 1221c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return; 1222c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 1223c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (max_colz > 2147483646) { 12245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL 1225c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser internal_warningf("print_columns called with %s=%zu >= INT_MAX", 1226c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "max_col", max_colz); 12275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 12295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1230c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser max_col = (unsigned int)max_colz; 12315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1232c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (max_oct > 2147483646) { 123303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_SMALL 1234c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser internal_warningf("print_columns called with %s=%zu >= INT_MAX", 1235c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser "max_oct", max_oct); 123603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 123703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return; 123803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++max_oct; 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru str = alloc(max_oct, ATEMP); 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 12435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * We use (max_col + 1) to consider the space separator. 12445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that no space is printed after the last column 12455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to avoid problems with terminals that have auto-wrap. 12465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cols = x_cols / (max_col + 1); 12485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* if we can only print one column anyway, skip the goo */ 12505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cols < 2) { 12515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < n; ++i) 1252811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser shf_fprintf(shf, "%s\n", 12535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*func)(str, max_oct, i, arg)); 12545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto out; 12555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rows = (n + cols - 1) / cols; 12585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (prefcol && cols > rows) { 1259811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cols = rows; 1260811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser rows = (n + cols - 1) / cols; 12615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1263811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser nspace = (x_cols - max_col * cols) / cols; 12645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru max_col = -max_col; 12655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nspace <= 0) 12665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nspace = 1; 12675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (r = 0; r < rows; r++) { 12685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 0; c < cols; c++) { 12695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = c * rows + r; 12705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i < n) { 12715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%*s", max_col, 12725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*func)(str, max_oct, i, arg)); 12735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c + 1 < cols) 12745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%*s", nspace, null); 12755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putchar('\n', shf); 12785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 12795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru out: 12805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(str, ATEMP); 12815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */ 12845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 12855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrip_nuls(char *buf, int nbytes) 12865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dst; 12885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 128903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 129003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * nbytes check because some systems (older FreeBSDs) have a 129103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * buggy memchr() 12925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nbytes && (dst = memchr(buf, '\0', nbytes))) { 12945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *end = buf + nbytes; 12955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p, *q; 12965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = dst; p < end; p = q) { 12985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip a block of nulls */ 12995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (++p < end && *p == '\0') 13005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 13015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* find end of non-null block */ 13025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(q = memchr(p, '\0', end - p))) 13035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru q = end; 13045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memmove(dst, p, q - p); 13055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst += q - p; 13065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dst = '\0'; 13085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 131103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 131203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Like read(2), but if read fails due to non-blocking flag, 131303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * resets flag and restarts read. 13145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 131503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrassize_t 131603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrablocking_read(int fd, char *buf, size_t nbytes) 13175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 131803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ssize_t ret; 131903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool tried_reset = false; 13205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((ret = read(fd, buf, nbytes)) < 0) { 13225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tried_reset && errno == EAGAIN) { 13235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (reset_nonblock(fd) > 0) { 132403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tried_reset = true; 13255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 13265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errno = EAGAIN; 13285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 13305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 13315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 13325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 133403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 133503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Reset the non-blocking flag on the specified file descriptor. 13365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Returns -1 if there was an error, 0 if non-blocking wasn't set, 13375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 1 if it was. 13385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 13395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 13405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureset_nonblock(int fd) 13415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 13425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int flags; 13435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 13445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((flags = fcntl(fd, F_GETFL, 0)) < 0) 13455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags & O_NONBLOCK)) 13475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 13485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~O_NONBLOCK; 13495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fcntl(fd, F_SETFL, flags) < 0) 13505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 13515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 13525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 135403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* getcwd(3) equivalent, allocates from ATEMP but doesn't resize */ 13555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 135603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraksh_get_wd(void) 13575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1358c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH__NO_PATH_MAX 135903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *rv, *cp; 136003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 136103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp = get_current_dir_name())) { 136203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(rv, cp, ATEMP); 136303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra free_gnu_gcdn(cp); 13645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 136503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = NULL; 13665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 136703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *rv; 136803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 136903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!getcwd((rv = alloc(PATH_MAX + 1, ATEMP)), PATH_MAX)) { 137003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(rv, ATEMP); 137103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = NULL; 137203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 13735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 13745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 137503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 13765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 13775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1378c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef ELOOP 1379c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#define ELOOP E2BIG 1380c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1381c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser 138203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrachar * 138303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrado_realpath(const char *upath) 138403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 138503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *xp, *ip, *tp, *ipath, *ldest = NULL; 138603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XString xs; 138703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ptrdiff_t pos; 138803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 138903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int llen; 139003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct stat sb; 1391c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH__NO_PATH_MAX 139203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t ldestlen = 0; 139303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathlen sb.st_size 139403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathcnd (ldestlen < (pathlen + 1)) 139503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 139603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathlen PATH_MAX 139703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathcnd (!ldest) 139803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 139903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* max. recursion depth */ 140003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int symlinks = 32; 140103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 140203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (upath[0] == '/') { 140303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* upath is an absolute pathname */ 140403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(ipath, upath, ATEMP); 140503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 140603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* upath is a relative pathname, prepend cwd */ 140703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((tp = ksh_get_wd()) == NULL || tp[0] != '/') 140803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (NULL); 140903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ipath = shf_smprintf("%s%s%s", tp, "/", upath); 141003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(tp, ATEMP); 141103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 141203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 141303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ipath and upath are in memory at the same time -> unchecked */ 141403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP); 141503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 141603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* now jump into the deep of the loop */ 141703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto beginning_of_a_pathname; 141803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 141903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip) { 142003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip slashes in input */ 142103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 142203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 142303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 142403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 142503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 142603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get next pathname component from input */ 142703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = ip; 142803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip && *ip != '/') 142903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 143003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra len = ip - tp; 143103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 143203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check input for "." and ".." */ 143303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp[0] == '.') { 143403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (len == 1) 143503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just continue with the next one */ 143603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 143703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (len == 2 && tp[1] == '.') { 143803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* strip off last pathname component */ 143903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (xp > Xstring(xs, xp)) 144003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*--xp == '/') 144103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 144203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* then continue with the next one */ 144303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 144403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 144503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 144603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 144703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* store output position away, then append slash to output */ 144803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pos = Xsavepos(xs, xp); 144903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 1 for the '/' and len + 1 for tp and the NUL from below */ 145003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XcheckN(xs, xp, 1 + len + 1); 145103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 145203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 145303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append next pathname component to output */ 145403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(xp, tp, len); 145503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp += len; 145603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *xp = '\0'; 145703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 145803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* lstat the current output, see if it's a symlink */ 1459c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser if (mksh_lstat(Xstring(xs, xp), &sb)) { 146003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* lstat failed */ 146103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errno == ENOENT) { 146203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* because the pathname does not exist */ 146303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 146403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip any trailing slashes */ 146503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 146603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no more components left? */ 146703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 146803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we can still return successfully */ 146903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 147003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* more components left? fall through */ 147103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 147203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not ENOENT or not at the end of ipath */ 147303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 147403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 147503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 147603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check if we encountered a symlink? */ 147703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (S_ISLNK(sb.st_mode)) { 1478c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifndef MKSH__NO_SYMLINK 147903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* reached maximum recursion depth? */ 148003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!symlinks--) { 148103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* yep, prevent infinite loops */ 148203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ELOOP; 148303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 148403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 148503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 148603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get symlink(7) target */ 148703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (pathcnd) { 1488c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH__NO_PATH_MAX 148903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (notoktoadd(pathlen, 1)) { 149003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ENAMETOOLONG; 149103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 149203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 149303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 149403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ldest = aresize(ldest, pathlen + 1, ATEMP); 149503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 149603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra llen = readlink(Xstring(xs, xp), ldest, pathlen); 149703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (llen < 0) 149803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* oops... */ 149903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 150003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ldest[llen] = '\0'; 150103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 150203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 150303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * restart if symlink target is an absolute path, 150403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * otherwise continue with currently resolved prefix 150503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 150603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append rest of current input path to link target */ 150703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip); 150803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 150903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ip = ipath = tp; 151003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest[0] != '/') { 151103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* symlink target is a relative path */ 151203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp = Xrestpos(xs, xp, pos); 1513c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser } else 1514c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#endif 1515c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser { 151603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* symlink target is an absolute path */ 151703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp = Xstring(xs, xp); 151803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra beginning_of_a_pathname: 151903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* assert: (ip == ipath)[0] == '/' */ 152003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* assert: xp == xs.beg => start of path */ 152103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 152203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* exactly two leading slashes? (SUSv4 3.266) */ 152303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ip[1] == '/' && ip[2] != '/') { 152403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep them, e.g. for UNC pathnames */ 152503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 152603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 152703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 152803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 152903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* otherwise (no symlink) merely go on */ 153003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 153103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 153203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 153303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * either found the target and successfully resolved it, 153403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * or found its parent directory and may create it 153503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 153603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Xlength(xs, xp) == 0) 153703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 153803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if the resolved pathname is "", make it "/", 153903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * otherwise do not add a trailing slash 154003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 154103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 154203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '\0'); 154303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 154403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 154503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if source path had a trailing slash, check if target path 154603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * is not a non-directory existing file 154703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 154803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ip > ipath && ip[-1] == '/') { 154903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (stat(Xstring(xs, xp), &sb)) { 155003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errno != ENOENT) 155103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 155203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!S_ISDIR(sb.st_mode)) { 155303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ENOTDIR; 155403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 155503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 155603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* target now either does not exist or is a directory */ 155703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 155803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 155903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* return target path */ 156003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest != NULL) 156103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ldest, ATEMP); 156203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 156303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (Xclose(xs, xp)); 156403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 156503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra notfound: 156603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* save; freeing memory might trash it */ 156703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra llen = errno; 156803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest != NULL) 156903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ldest, ATEMP); 157003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 157103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 157203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = llen; 157303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (NULL); 157403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 157503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef pathlen 157603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef pathcnd 157703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 157803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 157903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 15805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Makes a filename into result using the following algorithm. 15815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - make result NULL 15825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if file starts with '/', append file to result & set cdpathp to NULL 15835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if file starts with ./ or ../ append cwd and file to result 15845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and set cdpathp to NULL 15855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx 15865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * then cwd is appended to result. 15875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the first element of cdpathp is appended to result 15885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - file is appended to result 15895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - cdpathp is set to the start of the next element in cdpathp (or NULL 15905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if there are no more elements. 15915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * The return value indicates whether a non-null element from cdpathp 15925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * was appended to result. 15935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 159403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 15955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumake_path(const char *cwd, const char *file, 159603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* pointer to colon-separated list */ 159703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char **cdpathp, 15985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString *xsp, 15995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *phys_pathp) 16005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int rval = 0; 16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool use_cdpath = true; 16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *plist; 160403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len, plen = 0; 16055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp = Xstring(*xsp, xp); 16065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!file) 16085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru file = null; 16095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (file[0] == '/') { 16115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *phys_pathp = 0; 16125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 16135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 16145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (file[0] == '.') { 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char c = file[1]; 16165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '.') 16185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = file[2]; 16195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '/' || c == '\0') 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru plist = *cdpathp; 16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!plist) 16255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (use_cdpath) { 16275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *pend; 16285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (pend = plist; *pend && *pend != ':'; pend++) 16305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 16315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru plen = pend - plist; 16325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cdpathp = *pend ? pend + 1 : NULL; 16335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((!use_cdpath || !plen || plist[0] != '/') && 16365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (cwd && *cwd)) { 16375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(cwd); 16385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, len); 16395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, cwd, len); 16405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += len; 16415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cwd[len - 1] != '/') 16425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xput(*xsp, xp, '/'); 16435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *phys_pathp = Xlength(*xsp, xp); 16455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (use_cdpath && plen) { 16465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, plen); 16475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, plist, plen); 16485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += plen; 16495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (plist[plen - 1] != '/') 16505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xput(*xsp, xp, '/'); 16515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rval = 1; 16525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(file) + 1; 16565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, len); 16575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, file, len); 16585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!use_cdpath) 16605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cdpathp = NULL; 16615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rval); 16635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 166503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*- 16665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Simplify pathnames containing "." and ".." entries. 166703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * 166803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * simplify_path(this) = that 166903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /a/b/c/./../d/.. /a/b 167003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * //./C/foo/bar/../baz //C/foo/baz 167103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/ /foo 167203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/../../bar /bar 167303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/./blah/.. /foo 167403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * . . 167503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * .. .. 167603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ./foo foo 167703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * foo/../../../bar ../../bar 16785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 16795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 168003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasimplify_path(char *p) 16815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 168203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *dp, *ip, *sp, *tp; 168303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 168403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool needslash; 16855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 168603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (*p) { 168703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0: 16885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 168903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '/': 169003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* exactly two leading slashes? (SUSv4 3.266) */ 169103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p[1] == '/' && p[2] != '/') 169203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep them, e.g. for UNC pathnames */ 169303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++p; 169403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 169503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 169603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra default: 169703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = false; 169803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 169903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp = ip = sp = p; 17005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 170103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip) { 170203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip slashes in input */ 170303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 170403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 170503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 17065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 17075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 170803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get next pathname component from input */ 170903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = ip; 171003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip && *ip != '/') 171103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 171203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra len = ip - tp; 171303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 171403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check input for "." and ".." */ 171503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp[0] == '.') { 171603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (len == 1) 171703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just continue with the next one */ 17185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 171903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (len == 2 && tp[1] == '.') { 172003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* parent level, but how? */ 172103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*p == '/') 172203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* absolute path, only one way */ 172303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto strip_last_component; 172403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (dp > sp) { 172503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* relative path, with subpaths */ 172603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = false; 172703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strip_last_component: 172803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* strip off last pathname component */ 172903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (dp > sp) 173003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*--dp == '/') 173103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 173203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 173303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* relative path, at its beginning */ 173403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (needslash) 173503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* or already dotdot-slash'd */ 173603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '/'; 173703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep dotdot-slash if not absolute */ 173803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '.'; 173903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '.'; 174003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 174103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = dp; 174203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 174303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* then continue with the next one */ 17445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 17455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 17475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 174803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (needslash) 174903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '/'; 17505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 175103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append next pathname component to output */ 175203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memmove(dp, tp, len); 175303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp += len; 175403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 175503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append slash if we continue */ 175603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 175703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* try next component */ 17585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 175903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (dp == p) 176003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* empty path -> dot */ 176103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = needslash ? '/' : '.'; 176203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 17635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 17645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 17655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 176603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraset_current_wd(const char *nwd) 17675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 176803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *allocd = NULL; 17695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 177003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (nwd == NULL) { 177103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = ksh_get_wd(); 177203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra nwd = allocd ? allocd : null; 177303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 177403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 177503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(current_wd, APERM); 177603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(current_wd, nwd, APERM); 177703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 177803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 177903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 178003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 178103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint 178203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_cd(const char **wp) 178303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 178403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int optc, rv, phys_path; 178503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool physical = tobool(Flag(FPHYSICAL)); 178603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* was a node from cdpath added in? */ 178703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int cdnode; 178803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* show where we went?, error for $PWD */ 178903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool printpath = false, eflag = false; 179003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct tbl *pwd_s, *oldpwd_s; 179103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XString xs; 179203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *dir, *allocd = NULL, *tryp, *pwd, *cdpath; 179303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 179403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((optc = ksh_getopt(wp, &builtin_opt, "eLP")) != -1) 179503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (optc) { 179603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'e': 179703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra eflag = true; 179803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 179903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'L': 180003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra physical = false; 180103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 180203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'P': 180303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra physical = true; 180403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 180503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '?': 180603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 180803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra wp += builtin_opt.optind; 180903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 181003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FRESTRICTED)) { 181103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("restricted shell - can't cd"); 181203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 181303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 181403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 181503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd_s = global("PWD"); 181603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra oldpwd_s = global("OLDPWD"); 181703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 181803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!wp[0]) { 181903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* No arguments - go home */ 182003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((dir = str_val(global("HOME"))) == null) { 182103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("no home directory (HOME not set)"); 182203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 182303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 182403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!wp[1]) { 182503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* One argument: - or dir */ 182603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(allocd, wp[0], ATEMP); 182703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ksh_isdash((dir = allocd))) { 182803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 182903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = NULL; 183003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dir = str_val(oldpwd_s); 183103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (dir == null) { 183203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("no OLDPWD"); 183303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 183403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 183503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra printpath = true; 183603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 183703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!wp[2]) { 183803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Two arguments - substitute arg1 in PWD for arg2 */ 183903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t ilen, olen, nlen, elen; 184003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 184103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 184203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!current_wd[0]) { 184303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't determine current directory"); 184403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 184503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 184603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 184703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * substitute arg1 for arg2 in current path. 184803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if the first substitution fails because the cd fails 184903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * we could try to find another substitution. For now 185003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * we don't 185103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 185203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp = strstr(current_wd, wp[0])) == NULL) { 185303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("bad substitution"); 185403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 185503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 185603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 185703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ilen = part of current_wd before wp[0] 185803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * elen = part of current_wd after wp[0] 185903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * because current_wd and wp[1] need to be in memory at the 186003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * same time beforehand the addition can stay unchecked 186103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 186203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ilen = cp - current_wd; 186303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra olen = strlen(wp[0]); 186403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra nlen = strlen(wp[1]); 186503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra elen = strlen(current_wd + ilen + olen) + 1; 186603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dir = allocd = alloc(ilen + nlen + elen, ATEMP); 186703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir, current_wd, ilen); 186803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir + ilen, wp[1], nlen); 186903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir + ilen + nlen, current_wd + ilen + olen, elen); 187003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra printpath = true; 187103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 187203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("too many arguments"); 187303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 187403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 187503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1876c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef MKSH__NO_PATH_MAX 187703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* only a first guess; make_path will enlarge xs if necessary */ 187803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XinitN(xs, 1024, ATEMP); 187903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 188003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XinitN(xs, PATH_MAX, ATEMP); 188103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 188203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 188303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cdpath = str_val(global("CDPATH")); 188403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra do { 188503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path); 188603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (physical) 188703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = chdir(tryp = Xstring(xs, xp) + phys_path); 188803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else { 188903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_path(Xstring(xs, xp)); 189003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = chdir(tryp = Xstring(xs, xp)); 189103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 189203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } while (rv < 0 && cdpath != NULL); 189303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 189403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (rv < 0) { 189503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (cdnode) 189603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", dir, "bad directory"); 189703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 1898c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser bi_errorf("%s: %s", tryp, cstrerror(errno)); 189903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 190003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 190103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 190203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 190303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 190403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 0; 190503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 190603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* allocd (above) => dir, which is no longer used */ 190703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 190803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = NULL; 190903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 191003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Clear out tracked aliases with relative paths */ 191103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra flushcom(false); 191203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 191303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 191403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set OLDPWD (note: unsetting OLDPWD does not disable this 191503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * setting in AT&T ksh) 191603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 191703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (current_wd[0]) 191803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Ignore failure (happens if readonly or integer) */ 191903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR); 192003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 192103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Xstring(xs, xp)[0] != '/') { 192203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = NULL; 192303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!physical) { 192403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto norealpath_PWD; 192503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if ((pwd = allocd = do_realpath(Xstring(xs, xp))) == NULL) { 192603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (eflag) 192703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 1; 192803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra norealpath_PWD: 192903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = Xstring(xs, xp); 193003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 193103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 193203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Set PWD */ 193303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (pwd) { 193403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *ptmp = pwd; 19355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 193603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra set_current_wd(ptmp); 193703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Ignore failure (happens if readonly or integer) */ 193803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(pwd_s, ptmp, KSH_RETURN_ERROR); 193903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 194003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra set_current_wd(null); 194103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = Xstring(xs, xp); 194203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* XXX unset $PWD? */ 194303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (eflag) 194403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 1; 19455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 194603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (printpath || cdnode) 194703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shprintf("%s\n", pwd); 194803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 194903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 195003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 195103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 19525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 195403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 1955c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#ifdef KSH_CHVT_CODE 19565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruextern void chvt_reinit(void); 19575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1959811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaserchvt(const Getopt *go) 19605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1961811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser const char *dv = go->optarg; 1962811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser char *cp = NULL; 19635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 19645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1965811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch (*dv) { 1966811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '-': 1967811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dv = "/dev/null"; 1968811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 1969811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case '!': 1970811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser ++dv; 1971811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser /* FALLTHROUGH */ 1972811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser default: { 1973811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser struct stat sb; 1974811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser 1975811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (stat(dv, &sb)) { 1976811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser cp = shf_smprintf("/dev/ttyC%s", dv); 1977811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dv = cp; 19785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stat(dv, &sb)) { 1979811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser memmove(cp + 1, cp, /* /dev/tty */ 8); 1980811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dv = cp + 1; 1981811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (stat(dv, &sb)) { 1982811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser errorf("%s: %s: %s", "chvt", 1983811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser "can't find tty", go->optarg); 1984811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 19855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(sb.st_mode & S_IFCHR)) 1988811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser errorf("%s: %s: %s", "chvt", "not a char device", dv); 1989811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#ifndef MKSH_DISABLE_REVOKE_WARNING 19905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_REVOKE 1991811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (revoke(dv)) 19925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 199303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s", "chvt", 199403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "new shell is potentially insecure, can't revoke", 1995811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser dv); 1996811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser#endif 1997811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 19985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1999427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) { 20005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sleep(1); 2001427d76ccc44aea287b51b233f0254a6107b2b3d1Elliott Hughes if ((fd = open(dv, O_RDWR | O_BINARY)) < 0) { 2002811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser errorf("%s: %s %s", "chvt", "can't open", dv); 2003811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 20045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2005811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (go->optarg[0] != '!') { 2006811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser switch (fork()) { 2007811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case -1: 2008811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser errorf("%s: %s %s", "chvt", "fork", "failed"); 2009811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser case 0: 2010811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser break; 2011811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser default: 2012811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser exit(0); 2013811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser } 20145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setsid() == -1) 201603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "setsid", "failed"); 2017811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser if (go->optarg[0] != '-') { 20185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ioctl(fd, TIOCSCTTY, NULL) == -1) 201903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "TIOCSCTTY", "failed"); 20205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tcflush(fd, TCIOFLUSH)) 202103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "TCIOFLUSH", "failed"); 20225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 0, false); 20245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 1, false); 20255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 2, false); 20265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fd > 2) 20275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 2028811a575c0f6a5ef00a921d14c1830ef5ae1bd796Thorsten Glaser rndset((unsigned long)chvt_rndsetup(go, sizeof(Getopt))); 20295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chvt_reinit(); 20305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 20325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef DEBUG 20345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 20355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrchr(char *p, int ch) 20365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (;; ++p) { 20385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*p == ch) 20395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 20405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*p) 20415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 20425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 20445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 20475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrstr(char *b, const char *l) 20485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char first, c; 20505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t n; 20515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((first = *l++) == '\0') 20535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b); 20545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = strlen(l); 20555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strstr_look: 20565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = *b++) != first) 20575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 20585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 20595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (strncmp(b, l, n)) 20605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto strstr_look; 20615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b - 1); 20625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 20645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2065c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser#if defined(MKSH_SMALL) && !defined(MKSH_SMALL_BUT_FAST) 20665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 2067c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstrndup_i(const char *src, size_t len, Area *ap) 20685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dst = NULL; 20705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (src != NULL) { 20725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst = alloc(len + 1, ap); 20735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(dst, src, len); 20745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst[len] = '\0'; 20755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dst); 20775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 2080c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaserstrdup_i(const char *src, Area *ap) 20815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2082c2dc5def5e2273bb1d78b4ba032a3903dd0f980cThorsten Glaser return (src == NULL ? NULL : strndup_i(src, strlen(src), ap)); 20835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 20855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_GETRUSAGE 20875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define INVTCK(r,t) do { \ 20885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r.tv_usec = ((t) % (1000000 / CLK_TCK)) * (1000000 / CLK_TCK); \ 20895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r.tv_sec = (t) / CLK_TCK; \ 20905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} while (/* CONSTCOND */ 0) 20915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 20935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetrusage(int what, struct rusage *ru) 20945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tms tms; 20965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru clock_t u, s; 20975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (/* ru == NULL || */ times(&tms) == (clock_t)-1) 20995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 21005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 21015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (what) { 21025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case RUSAGE_SELF: 21035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru u = tms.tms_utime; 21045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tms.tms_stime; 21055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case RUSAGE_CHILDREN: 21075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru u = tms.tms_cutime; 21085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tms.tms_cstime; 21095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 21115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errno = EINVAL; 21125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 21135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 21145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru INVTCK(ru->ru_utime, u); 21155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru INVTCK(ru->ru_stime, s); 21165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 21175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 21185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 21195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 21205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 21215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * process the string available via fg (get a char) 21225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and fp (put back a char) for backslash escapes, 21235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * assuming the first call to *fg gets the char di- 21245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * rectly after the backslash; return the character 21255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (0..0xFF), Unicode (wc + 0x100), or -1 if no known 21265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * escape sequence was found 21275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 21285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 21295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunbksl(bool cstyle, int (*fg)(void), void (*fp)(int)) 21305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 21315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int wc, i, c, fc; 21325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 21335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fc = (*fg)(); 21345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (fc) { 21355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'a': 21365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 21375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * according to the comments in pdksh, \007 seems 21385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to be more portable than \a (due to HP-UX cc, 21395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Ultrix cc, old pcc, etc.) so we avoid the escape 21405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * sequence altogether in mksh and assume ASCII 21415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 21425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 7; 21435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'b': 21455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\b'; 21465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'c': 21485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 21495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 21505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = (*fg)(); 21515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = CTRL(c); 21525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'E': 21545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'e': 21555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 033; 21565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'f': 21585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\f'; 21595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'n': 21615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\n'; 21625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'r': 21645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\r'; 21655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 't': 21675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\t'; 21685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'v': 21705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* assume ASCII here as well */ 21715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 11; 21725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '1': 21745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '2': 21755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '3': 21765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '4': 21775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '5': 21785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '6': 21795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '7': 21805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 21815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 21825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 21835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': 21845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cstyle) 21855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(fc); 21865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 21875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * look for an octal number with up to three 21885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * digits, not counting the leading zero; 21895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * convert it to a raw octet 21905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 21915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 0; 21925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 3; 21935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i--) 21945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = (*fg)()) >= '0' && c <= '7') 21955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = (wc << 3) + (c - '0'); 21965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 21975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(c); 21985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 22005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 22015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'U': 22025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 8; 220303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (/* CONSTCOND */ 0) 22045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 22055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'u': 22065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 4; 220703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (/* CONSTCOND */ 0) 22085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 22095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'x': 22105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = cstyle ? -1 : 2; 221103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /** 22125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * x: look for a hexadecimal number with up to 22135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * two (C style: arbitrary) digits; convert 22145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to raw octet (C style: Unicode if >0xFF) 22155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * u/U: look for a hexadecimal number with up to 22165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * four (U: eight) digits; convert to Unicode 22175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 22185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 0; 22195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i--) { 22205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc <<= 4; 22215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = (*fg)()) >= '0' && c <= '9') 22225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - '0'; 22235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c >= 'A' && c <= 'F') 22245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - 'A' + 10; 22255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c >= 'a' && c <= 'f') 22265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - 'a' + 10; 22275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 22285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc >>= 4; 22295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(c); 22305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 22315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 22325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 22335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cstyle && wc > 0xFF) || fc != 'x') 22345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Unicode marker */ 22355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += 0x100; 22365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 22375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '\'': 22385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 22395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 22405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\''; 22415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 22425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '\\': 22435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\\'; 22445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 22455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 22465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unknown_escape: 22475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(fc); 22485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 22495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 22505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 22515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (wc); 22525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2253