15155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: misc.c,v 1.37 2009/04/19 20:34:05 sthen Exp $ */ 25155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* $OpenBSD: path.c,v 1.12 2005/03/30 17:16:37 deraadt Exp $ */ 35155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 45155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*- 503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Copyright (c) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 65155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Thorsten Glaser <tg@mirbsd.org> 75155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 85155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Provided that these terms and disclaimer and all copyright notices 95155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * are retained or reproduced in an accompanying document, permission 105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * is granted to deal in this work without restriction, including un- 115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * limited rights to use, publicly perform, distribute, sell, modify, 125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * merge, give away, or sublicence. 135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to 155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the utmost extent permitted by applicable law, neither express nor 165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * implied; without malicious intent or gross negligence. In no event 175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * may a licensor, author or contributor be held liable for indirect, 185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * direct, other damage, loss, or other issues arising in any way out 195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of dealing in the work, even if advised of the possibility of such 205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * damage or existence of a defect, except proven that it results out 215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * of said person's immediate fault when using the work as intended. 225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh.h" 255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_GETRUSAGE 265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <sys/times.h> 275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_GRP_H 295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include <grp.h> 305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra__RCSID("$MirOS: src/bin/mksh/misc.c,v 1.172 2011/09/07 15:24:18 tg Exp $"); 335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* type bits for unsigned char */ 3503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraunsigned char chtypes[UCHAR_MAX + 1]; 365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const unsigned char *pat_scan(const unsigned char *, 3803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const unsigned char *, bool); 395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int do_gmatch(const unsigned char *, const unsigned char *, 405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *, const unsigned char *); 415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const unsigned char *cclass(const unsigned char *, int); 425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef TIOCSCTTY 435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void chvt(const char *); 445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*XXX this should go away */ 4703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int make_path(const char *, const char *, char **, XString *, int *); 4803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 4903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef SETUID_CAN_FAIL_WITH_EAGAIN 5003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* we don't need to check for other codes, EPERM won't happen */ 5103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define DO_SETUID(func, argvec) do { \ 5203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((func argvec) && errno == EAGAIN) \ 5303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s failed with EAGAIN, probably due to a" \ 5403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra " too low process limit; aborting", #func); \ 5503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} while (/* CONSTCOND */ 0) 5603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 5703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define DO_SETUID(func, argvec) func argvec 5803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 5903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Fast character classes 625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusetctypes(const char *s, int t) 655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned int i; 675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (t & C_IFS) { 695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < UCHAR_MAX + 1; i++) 705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[i] &= ~C_IFS; 7103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* include \0 in C_IFS */ 7203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra chtypes[0] |= C_IFS; 735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (*s != 0) 755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[(unsigned char)*s++] |= t; 765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruinitctypes(void) 805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 'a'; c <= 'z'; c++) 845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[c] |= C_ALPHA; 855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 'A'; c <= 'Z'; c++) 865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes[c] |= C_ALPHA; 875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chtypes['_'] |= C_ALPHA; 885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("0123456789", C_DIGIT); 8903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* \0 added automatically */ 9003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setctypes(" \t\n|&;<>()", C_LEX1); 915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("*@#!$-?", C_VAR1); 925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes(" \t\n", C_IFSWS); 935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("=-+?", C_SUBOP1); 945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setctypes("\t\n \"#$&'()*;<=>?[\\]`|", C_QUOTE); 955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* called from XcheckN() to grow buffer */ 985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 9903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy CondraXcheck_grow_(XString *xsp, const char *xp, size_t more) 1005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *old_beg = xsp->beg; 1025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (more < xsp->len) 10403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra more = xsp->len; 10503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* (xsp->len + X_EXTRA) never overflows */ 10603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra checkoktoadd(more, xsp->len + X_EXTRA); 10703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xsp->beg = aresize(xsp->beg, (xsp->len += more) + X_EXTRA, xsp->areap); 1085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xsp->end = xsp->beg + xsp->len; 1095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (xsp->beg + (xp - old_beg)); 1105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHFLAGS_DEFNS 1135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh_flags.h" 1145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst struct shoption options[] = { 1165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define SHFLAGS_ITEMS 1175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#include "sh_flags.h" 1185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 1215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * translate -o option into F* constant (also used for test -o option) 1225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 1235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querusize_t 1245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruoption(const char *n) 1255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t i; 1275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((n[0] == '-' || n[0] == '+') && n[1] && !n[2]) { 1295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < NELEM(options); i++) 1305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].c == n[1]) 1315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (i); 1325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else for (i = 0; i < NELEM(options); i++) 1335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].name && strcmp(options[i].name, n) == 0) 1345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (i); 1355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((size_t)-1); 1375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustruct options_info { 1405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int opt_width; 1415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int opts[NELEM(options)]; 1425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru}; 1435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic char *options_fmt_entry(char *, size_t, int, const void *); 1455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void printoptions(bool); 1465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* format a single select menu item */ 1485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic char * 14903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraoptions_fmt_entry(char *buf, size_t buflen, int i, const void *arg) 1505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 1515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const struct options_info *oi = (const struct options_info *)arg; 1525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_snprintf(buf, buflen, "%-*s %s", 1545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi->opt_width, options[oi->opts[i]].name, 1555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(oi->opts[i]) ? "on" : "off"); 1565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (buf); 1575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 1605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprintoptions(bool verbose) 1615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 16203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t i = 0; 1635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (verbose) { 16503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ssize_t n = 0, len, octs = 0; 1665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct options_info oi; 1675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* verbose version */ 1695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_puts("Current option settings\n", shl_stdout); 1705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi.opt_width = 0; 17203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (i < NELEM(options)) { 1735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].name) { 1745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi.opts[n++] = i; 1755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(options[i].name); 1765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (len > octs) 1775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru octs = len; 1785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = utf_mbswidth(options[i].name); 1795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (len > oi.opt_width) 1805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oi.opt_width = len; 1815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++i; 1835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru print_columns(shl_stdout, n, options_fmt_entry, &oi, 1855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru octs + 4, oi.opt_width + 4, true); 1865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 18703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* short version like AT&T ksh93 */ 18803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shf_puts(Tset, shl_stdout); 1895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i < (int)NELEM(options)) { 1905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (Flag(i) && options[i].name) 19103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shprintf("%s %s %s", null, "-o", 19203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra options[i].name); 1935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++i; 1945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\n', shl_stdout); 1965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 1975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 1985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 1995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 2005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetoptions(void) 2015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t i; 20303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char m[(int)FNFLAGS + 1]; 2045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *cp = m; 2055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < NELEM(options); i++) 2075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].c && Flag(i)) 2085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cp++ = options[i].c; 2095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strndupx(cp, m, cp - m, ATEMP); 2105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (cp); 2115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* change a Flag(*) value; takes care of special actions */ 2145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 2155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchange_flag(enum sh_flag f, int what, unsigned int newval) 2165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unsigned char oldval; 2185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru oldval = Flag(f); 22003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* needed for tristates */ 22103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Flag(f) = newval ? 1 : 0; 2225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_UNEMPLOYED 2235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f == FMONITOR) { 2245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what != OF_CMDLINE && newval != oldval) 2255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru j_change(); 2265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 2275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (( 2295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI 2305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f == FVI || 2315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru f == FEMACS || f == FGMACS) && newval) { 2335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !MKSH_S_NOVI 2345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FVI) = 2355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FEMACS) = Flag(FGMACS) = 0; 2375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(f) = (unsigned char)newval; 2385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (f == FPRIVILEGED && oldval && !newval) { 2395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Turning off -p? */ 2405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 24103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX this can probably be optimised */ 24203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra kshegid = kshgid = getgid(); 24303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#if HAVE_SETRESUGID 24403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setresgid, (kshegid, kshegid, kshegid)); 2455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_SETGROUPS 24603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* setgroups doesn't EAGAIN on Linux */ 2475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setgroups(1, &kshegid); 2485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 24903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setresuid, (ksheuid, ksheuid, ksheuid)); 2505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 25103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* seteuid, setegid, setgid don't EAGAIN on Linux */ 2525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru seteuid(ksheuid = kshuid = getuid()); 25303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra DO_SETUID(setuid, (ksheuid)); 25403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setegid(kshegid); 2555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru setgid(kshegid); 2565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((f == FPOSIX || f == FSH) && newval) { 2585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FPOSIX) = Flag(FSH) = Flag(FBRACEEXPAND) = 0; 2595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(f) = (unsigned char)newval; 2605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Changing interactive flag? */ 2625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (f == FTALKING) { 2635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((what == OF_CMDLINE || what == OF_SET) && procpid == kshpid) 2645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FTALKING_I) = (unsigned char)newval; 2655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 2665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 26803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 26903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Parse command line and set command arguments. Returns the index of 2705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * non-option arguments, -1 if there is an error. 2715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 2725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 2735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruparse_args(const char **argv, 27403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* OF_CMDLINE or OF_SET */ 27503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int what, 2765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool *setargsp) 2775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 2785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru static char cmd_opts[NELEM(options) + 5]; /* o:T:\0 */ 2795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru static char set_opts[NELEM(options) + 6]; /* A:o;s\0 */ 2805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char set, *opts; 2815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *array = NULL; 2825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Getopt go; 2835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t i; 28403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int optc, arrayset = 0; 28503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool sortargs = false; 2865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* First call? Build option strings... */ 2885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cmd_opts[0] == '\0') { 2895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p = cmd_opts, *q = set_opts; 2905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 2915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* see cmd_opts[] declaration */ 2925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p++ = 'o'; 2935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p++ = ':'; 2945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) || defined(TIOCSCTTY) 2955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p++ = 'T'; 2965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p++ = ':'; 2975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 2985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* see set_opts[] declaration */ 2995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = 'A'; 3005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = ':'; 3015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = 'o'; 3025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = ';'; 3035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = 's'; 3045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < NELEM(options); i++) { 3065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].c) { 3075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].flags & OF_CMDLINE) 3085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p++ = options[i].c; 3095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (options[i].flags & OF_SET) 3105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q++ = options[i].c; 3115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *p = '\0'; 3145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *q = '\0'; 3155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_CMDLINE) { 3185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p = argv[0], *q; 31903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 32003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set FLOGIN before parsing options so user can clear 3215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * flag using +l. 3225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*p != '-') 3245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (q = p; *q; ) 3255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*q++ == '/') 3265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p = q; 3275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FLOGIN) = (*p == '-'); 3285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = cmd_opts; 3295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (what == OF_FIRSTTIME) { 3305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = cmd_opts; 3315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 3325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru opts = set_opts; 3335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_getopt_reset(&go, GF_ERROR|GF_PLUSOPT); 3345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((optc = ksh_getopt(argv, &go, opts)) != -1) { 3355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru set = (go.info & GI_PLUS) ? 0 : 1; 3365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (optc) { 3375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'A': 3385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 3395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru arrayset = set ? 1 : -1; 3415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru array = go.optarg; 3425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'o': 3455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 3465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go.optarg == NULL) { 34803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 34903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * lone -o: print options 3505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 3515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that on the command line, -o requires 3525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * an option (ie, can't get here if what is 3535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * OF_CMDLINE). 3545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru printoptions(set); 3565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = option(go.optarg); 3595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((i != (size_t)-1) && set == Flag(i)) 36003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 36103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Don't check the context if the flag 3625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * isn't changing - makes "set -o interactive" 3635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * work if you're already interactive. Needed 3645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if the output of "set +o" is to be used. 3655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 3665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 3675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if ((i != (size_t)-1) && (options[i].flags & what)) 3685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag((enum sh_flag)i, what, set); 3695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 37003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", go.optarg, "bad option"); 3715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 3725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !defined(MKSH_SMALL) || defined(TIOCSCTTY) 3765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'T': 3775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what != OF_FIRSTTIME) 3785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef TIOCSCTTY 3805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errorf("no TIOCSCTTY ioctl"); 3815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 3825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag(FTALKING, OF_CMDLINE, 1); 3835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chvt(go.optarg); 3845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 3865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 3875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 3895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 3905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 3915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 3925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_FIRSTTIME) 3935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* -s: sort positional params (AT&T ksh stupidity) */ 3955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (what == OF_SET && optc == 's') { 39603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sortargs = true; 3975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 3985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 3995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < NELEM(options); i++) 4005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optc == options[i].c && 4015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (what & options[i].flags)) { 4025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_flag((enum sh_flag)i, what, set); 4035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 4045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i == NELEM(options)) 4065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_errorf("parse_args: '%c'", optc); 4075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(go.info & GI_MINUSMINUS) && argv[go.optind] && 4105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (argv[go.optind][0] == '-' || argv[go.optind][0] == '+') && 4115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv[go.optind][1] == '\0') { 4125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* lone - clears -v and -x flags */ 4135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go.optind][0] == '-') 4145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Flag(FVERBOSE) = Flag(FXTRACE) = 0; 4155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* set skips lone - or + option */ 4165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go.optind++; 4175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setargsp) 4195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* -- means set $#/$* even if there are no arguments */ 4205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *setargsp = !arrayset && ((go.info & GI_MINUSMINUS) || 4215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv[go.optind]); 4225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 42303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (arrayset) { 42403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const char *ccp = NULL; 42503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 42603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*array) 42703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ccp = skip_varname(array, false); 42803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ccp || !(!ccp[0] || (ccp[0] == '+' && !ccp[1]))) { 42903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", array, "is not an identifier"); 43003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (-1); 43103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 4325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sortargs) { 4345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = go.optind; argv[i]; i++) 4355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 4365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru qsort(&argv[go.optind], i - go.optind, sizeof(void *), 4375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xstrcmp); 4385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 4395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (arrayset) 44003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra go.optind += set_array(array, tobool(arrayset > 0), 4415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru argv + go.optind); 4425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (go.optind); 4445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* parse a decimal number: returns 0 if string isn't a number, 1 otherwise */ 4475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 4485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetn(const char *s, int *ai) 4495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int i, c, rv = 0; 4515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool neg = false; 4525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 4545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *s++; 4555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (ksh_isspace(c)); 4565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '-') { 4575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru neg = true; 4585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *s++; 4595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '+') 4605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *s++; 4615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *ai = i = 0; 4625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 4635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ksh_isdigit(c)) 4645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto getn_out; 4655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i *= 10; 4665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i < *ai) 4675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* overflow */ 4685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto getn_out; 4695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i += c - '0'; 4705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *ai = i; 4715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while ((c = *s++)); 4725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rv = 1; 4735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru getn_out: 4755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (neg) 4765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *ai = -*ai; 4775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 4785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* getn() that prints error */ 4815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 4825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querubi_getn(const char *as, int *ai) 4835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 4845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int rv; 4855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 4865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(rv = getn(as, ai))) 48703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", as, "bad number"); 4885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rv); 4895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 4905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 49103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 49203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * pattern simplifications: 49303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - @(x) -> x (not @(x|y) though) 49403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - ** -> * 49503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 49603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic void * 49703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasimplify_gmatch_pattern(const unsigned char *sp) 49803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 49903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra uint8_t c; 50003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra unsigned char *cp, *dp; 50103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const unsigned char *ps, *se; 50203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 50303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cp = alloc(strlen((const void *)sp) + 1, ATEMP); 50403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto simplify_gmatch_pat1a; 50503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 50603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* foo@(b@(a)r)b@(a|a)z -> foobarb@(a|a)z */ 50703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_gmatch_pat1: 50803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = cp; 50903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_gmatch_pat1a: 51003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp = cp; 51103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra se = sp + strlen((const void *)sp); 51203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((c = *sp++)) { 51303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ISMAGIC(c)) { 51403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 51503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 51603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 51703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch ((c = *sp++)) { 51803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'@': 51903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @ */ 52003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|' ': 52103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check whether it has only one clause */ 52203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ps = pat_scan(sp, se, true); 52303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ps || ps[-1] != /*(*/ ')') 52403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* nope */ 52503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 52603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* copy inner clause until matching close */ 52703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ps -= 2; 52803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((const unsigned char *)sp < ps) 52903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = *sp++; 53003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip MAGIC and closing parenthesis */ 53103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp += 2; 53203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* copy the rest of the pattern */ 53303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memmove(dp, sp, strlen((const void *)sp) + 1); 53403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* redo from start */ 53503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto simplify_gmatch_pat1; 53603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 53703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 53803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 53903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 54003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 54103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 54203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* collapse adjacent asterisk wildcards */ 54303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = dp = cp; 54403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((c = *sp++)) { 54503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!ISMAGIC(c)) { 54603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 54703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 54803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 54903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch ((c = *sp++)) { 55003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '*': 55103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (ISMAGIC(sp[0]) && sp[1] == c) 55203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp += 2; 55303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 55403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 55503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = MAGIC; 55603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = c; 55703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 55803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 55903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 56003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* return the result, allocated from ATEMP */ 56103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (cp); 56203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 56303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 5645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* -------- gmatch.c -------- */ 5655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 5675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * int gmatch(string, pattern) 5685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * char *string, *pattern; 5695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 5705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Match a pattern as in sh(1). 5715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * pattern character are prefixed with MAGIC by expand. 5725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 5745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugmatchx(const char *s, const char *p, bool isfile) 5755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 5765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *se, *pe; 57703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *pnew; 57803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int rv; 5795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s == NULL || p == NULL) 5815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 5825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 5835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se = s + strlen(s); 5845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pe = p + strlen(p); 58503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 58603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * isfile is false iff no syntax check has been done on 5875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the pattern. If check fails, just to a strcmp(). 5885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 5895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!isfile && !has_globbing(p, pe)) { 5905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t len = pe - p + 1; 5915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char tbuf[64]; 5925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *t = len <= sizeof(tbuf) ? tbuf : alloc(len, ATEMP); 5935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru debunk(t, p, len); 5945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (!strcmp(t, s)); 5955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 59603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 59703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 59803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * since the do_gmatch() engine sucks so much, we must do some 59903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * pattern simplifications 60003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 60103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnew = simplify_gmatch_pattern((const unsigned char *)p); 60203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pe = pnew + strlen(pnew); 60303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 60403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = do_gmatch((const unsigned char *)s, (const unsigned char *)se, 60503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (const unsigned char *)pnew, (const unsigned char *)pe); 60603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(pnew, ATEMP); 60703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 6085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 61003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 61103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Returns if p is a syntacticly correct globbing pattern, false 6125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if it contains no pattern characters or if there is a syntax error. 6135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Syntax errors are: 6145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - [ with no closing ] 6155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - imbalanced $(...) expression 6165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - [...] and *(...) not nested (eg, [a$(b|]c), *(a[b|c]d)) 6175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/*XXX 61903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - if no magic, 62003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if dest given, copy to dst 62103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return ? 62203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - if magic && (no globbing || syntax error) 62303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * debunk to dst 62403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * return ? 62503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * - return ? 62603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 6275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 6285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruhas_globbing(const char *xp, const char *xpe) 6295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *p = (const unsigned char *) xp; 6315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *pe = (const unsigned char *) xpe; 6325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c; 6335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nest = 0, bnest = 0; 63403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool saw_glob = false; 63503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* inside [...] */ 63603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool in_bracket = false; 6375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; p < pe; p++) { 6395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*p)) 6405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 6415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = *++p) == '*' || c == '?') 64203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 6435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c == '[') { 6445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!in_bracket) { 64503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 64603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra in_bracket = true; 6475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(p[1]) && p[2] == NOT) 6485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 6495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(p[1]) && p[2] == ']') 6505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p += 2; 6515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 65203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*XXX Do we need to check ranges here? POSIX Q */ 6535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == ']') { 6545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) { 65503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (bnest) 65603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* [a*(b]) */ 6575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 65803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra in_bracket = false; 6595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if ((c & 0x80) && vstrchr("*+?@! ", c & 0x7f)) { 66103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra saw_glob = true; 6625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) 6635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bnest++; 6645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else 6655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest++; 6665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == '|') { 66703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (in_bracket && !bnest) 66803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* *(a[foo|bar]) */ 6695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 6705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (c == /*(*/ ')') { 6715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (in_bracket) { 67203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!bnest--) 67303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* *(a[b)c] */ 6745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 6755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (nest) 6765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest--; 6775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 6795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * else must be a MAGIC-MAGIC, or MAGIC-!, 6805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * MAGIC--, MAGIC-], MAGIC-{, MAGIC-, MAGIC-} 6815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 6825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 6835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (saw_glob && !in_bracket && !nest); 6845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 6855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Function must return either 0 or 1 (assumed by code for 0x80|'!') */ 6875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic int 6885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querudo_gmatch(const unsigned char *s, const unsigned char *se, 6895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *p, const unsigned char *pe) 6905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 6915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int sc, pc; 6925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *prest, *psub, *pnext; 6935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *srest; 6945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 6955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (s == NULL || p == NULL) 6965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 6975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (p < pe) { 6985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pc = *p++; 6995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sc = s < se ? *s : '\0'; 7005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s++; 7015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(pc)) { 7025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc != pc) 7035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 7055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (*p++) { 7075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '[': 7085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc == 0 || (p = cclass(p, sc)) == NULL) 7095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '?': 7135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc == 0) 7145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (UTFMODE) { 7165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru --s; 7175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s += utf_ptradj((const void *)s); 7185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '*': 7225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p == pe) 7235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 7255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 7265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, se, p, pe)) 7275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (s++ < se); 7295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /** 7325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * [*+?@!](pattern|pattern|..) 7335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * This is also needed for ${..%..}, etc. 7345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 73503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 73603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches one or more times */ 73703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'+': 73803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches zero or more times */ 73903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'*': 74003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 7415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 7435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* take care of zero matches */ 7445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p[-1] == (0x80 | '*') && 7455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(s, se, prest, pe)) 7465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 74803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 7495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (srest = s; srest <= se; srest++) { 7505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, pnext - 2) && 7515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (do_gmatch(srest, se, prest, pe) || 7525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (s != srest && do_gmatch(srest, 7535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru se, p - 2, pe)))) 7545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 7575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 76103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches zero or once */ 76203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'?': 76303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches one of the patterns */ 76403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'@': 76503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @ */ 76603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|' ': 76703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 7685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 7705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Take care of zero matches */ 7715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (p[-1] == (0x80 | '?') && 7725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(s, se, prest, pe)) 7735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 77503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 7765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru srest = prest == pe ? se : s; 7775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; srest <= se; srest++) { 7785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, pnext - 2) && 7795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(srest, se, prest, pe)) 7805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 7815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 7835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 7845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 7855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 78703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* matches none of the patterns */ 78803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0x80|'!': 78903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!(prest = pat_scan(p, pe, false))) 7905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 7915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s--; 7925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (srest = s; srest <= se; srest++) { 7935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int matched = 0; 7945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 7955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (psub = p; ; psub = pnext) { 79603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pnext = pat_scan(psub, pe, true); 7975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (do_gmatch(s, srest, psub, 7985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru pnext - 2)) { 7995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru matched = 1; 8005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (pnext == prest) 8035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!matched && 8065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do_gmatch(srest, se, prest, pe)) 8075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 8085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 8125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (sc != p[-1]) 8135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 8145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 8155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (s == se); 8185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic const unsigned char * 8215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querucclass(const unsigned char *p, int sub) 8225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int c, d, notp, found = 0; 8245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const unsigned char *orig_p = p; 8255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((notp = (ISMAGIC(*p) && *++p == NOT))) 8275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru p++; 8285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru do { 8295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p++; 8305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(c)) { 8315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = *p++; 8325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c & 0x80) && !ISMAGIC(c)) { 83303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* extended pattern matching: *+?@! */ 83403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra c &= 0x7F; 8355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* XXX the ( char isn't handled as part of [] */ 83603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (c == ' ') 83703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* simile for @: plain (..) */ 8385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = '(' /*)*/; 8395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 8425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* No closing ] - act as if the opening [ was quoted */ 8435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (sub == '[' ? orig_p : NULL); 8445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(p[0]) && p[1] == '-' && 8455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!ISMAGIC(p[2]) || p[3] != ']')) { 84603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* MAGIC- */ 84703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra p += 2; 8485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = *p++; 8495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ISMAGIC(d)) { 8505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = *p++; 8515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((d & 0x80) && !ISMAGIC(d)) 8525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d &= 0x7f; 8535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* POSIX says this is an invalid expression */ 8555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c > d) 8565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 8575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 8585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru d = c; 8595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == sub || (c <= sub && sub <= d)) 8605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru found = 1; 8615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } while (!(ISMAGIC(p[0]) && p[1] == ']')); 8625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ((found != notp) ? p+2 : NULL); 8645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Look for next ) or | (if match_sep) in *(foo|bar) pattern */ 86703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic const unsigned char * 86803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrapat_scan(const unsigned char *p, const unsigned char *pe, bool match_sep) 8695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int nest = 0; 8715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (; p < pe; p++) { 8735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!ISMAGIC(*p)) 8745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 8755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*++p == /*(*/ ')' && nest-- == 0) || 8765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*p == '|' && match_sep && nest == 0)) 8775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p + 1); 8785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((*p & 0x80) && vstrchr("*+?@! ", *p & 0x7f)) 8795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nest++; 8805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 8815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 8825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 8855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruxstrcmp(const void *p1, const void *p2) 8865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (strcmp(*(const char * const *)p1, *(const char * const *)p2)); 8885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 8895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 8905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Initialise a Getopt structure */ 8915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 8925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_getopt_reset(Getopt *go, int flags) 8935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 8945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind = 1; 8955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 8965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 8975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->flags = flags; 8985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info = 0; 8995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[1] = '\0'; 9005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 9015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 90303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 90403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * getopt() used for shell built-in commands, the getopts command, and 9055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * command line options. 9065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * A leading ':' in options means don't print errors, instead return '?' 9075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * or ':' and set go->optarg to the offending option character. 9085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * If GF_ERROR is set (and option doesn't start with :), errors result in 9095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * a call to bi_errorf(). 9105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 9115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Non-standard features: 9125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - ';' is like ':' in options, except the argument is optional 9135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (if it isn't present, optarg is set to 0). 9145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'set -o'. 9155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - ',' is like ':' in options, except the argument always immediately 9165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * follows the option character (optarg is set to the null string if 9175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the option is missing). 9185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'read -u2', 'print -u2' and fc -40. 9195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - '#' is like ':' in options, expect that the argument is optional 9205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and must start with a digit. If the argument doesn't start with a 9215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * digit, it is assumed to be missing and normal option processing 9225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * continues (optarg is set to 0 if the option is missing). 9235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Used for 'typeset -LZ4'. 9245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - accepts +c as well as -c IF the GF_PLUSOPT flag is present. If an 9255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * option starting with + is accepted, the GI_PLUS flag will be set 9265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * in go->info. 9275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 9295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruksh_getopt(const char **argv, Getopt *go, const char *optionsp) 9305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 9315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char c; 9325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *o; 9335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->p == 0 || (c = argv[go->optind - 1][go->p]) == '\0') { 9355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *arg = argv[go->optind], flag = arg ? *arg : '\0'; 9365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 9375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 1; 9385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (flag == '-' && arg[1] == '-' && arg[2] == '\0') { 9395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind++; 9405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 9415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info |= GI_MINUSMINUS; 9425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 9435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (arg == NULL || 94503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ((flag != '-' ) && 94603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* neither a - nor a + (if + allowed) */ 9475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (!(go->flags & GF_PLUSOPT) || flag != '+')) || 9485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (c = arg[1]) == '\0') { 9495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 9505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 9515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optind++; 9535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info &= ~(GI_MINUS|GI_PLUS); 9545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->info |= flag == '-' ? GI_MINUS : GI_PLUS; 9555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p++; 9575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '?' || c == ':' || c == ';' || c == ',' || c == '#' || 9585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru !(o = cstrchr(optionsp, c))) { 9595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optionsp[0] == ':') { 9605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[0] = c; 9615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = go->buf; 9625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 96303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s%s-%c: %s", 9645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (go->flags & GF_NONAME) ? "" : argv[0], 96503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (go->flags & GF_NONAME) ? "" : ": ", c, 96603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "unknown option"); 9675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->flags & GF_ERROR) 9685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorfz(); 9695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ('?'); 9715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 97203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /** 97303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * : means argument must be present, may be part of option argument 9745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * or the next argument 9755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * ; same as : but argument may be missing 9765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * , means argument is part of option argument, and may be null. 9775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 9785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*++o == ':' || *o == ';') { 9795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind - 1][go->p]) 9805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 9815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (argv[go->optind]) 9825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind++]; 9835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (*o == ';') 9845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 9855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 9865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (optionsp[0] == ':') { 9875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->buf[0] = c; 9885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = go->buf; 9895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (':'); 9905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 99103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(true, "%s%s-%c: %s", 9925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (go->flags & GF_NONAME) ? "" : argv[0], 99303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra (go->flags & GF_NONAME) ? "" : ": ", c, 99403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "requires an argument"); 9955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (go->flags & GF_ERROR) 9965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bi_errorfz(); 9975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return ('?'); 9985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 9995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (*o == ',') { 10015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* argument is attached to option character, even if null */ 10025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 10035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (*o == '#') { 100503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 100603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * argument is optional and may be attached or unattached 10075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * but must start with a digit. optarg is set to 0 if the 10085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * argument is missing. 10095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind - 1][go->p]) { 10115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ksh_isdigit(argv[go->optind - 1][go->p])) { 10125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind - 1] + go->p; 10135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 10165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 10175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (argv[go->optind] && ksh_isdigit(argv[go->optind][0])) { 10185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = argv[go->optind++]; 10195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->p = 0; 10205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 10215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru go->optarg = NULL; 10225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (c); 10255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 102703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 102803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * print variable/alias value using necessary quotes 10295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (POSIX says they should be suitable for re-entry...) 10305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * No trailing newline is printed. 10315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprint_value_quoted(const char *s) 10345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 10355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru const char *p; 103603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool inquote = false; 10375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 103803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* first, check whether any quotes are needed */ 10395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = s; *p; p++) 10405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ctype(*p, C_QUOTE)) 10415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 10425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*p) { 104303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* nope, use the shortcut */ 10445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_puts(s, shl_stdout); 10455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 10465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 104703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 104803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* quote via state machine */ 10495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = s; *p; p++) { 10505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*p == '\'') { 105103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 105203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * multiple '''s or any ' at beginning of string 105303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * look nicer this way than when simply substituting 105403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 105503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (inquote) { 10565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\'', shl_stdout); 105703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra inquote = false; 105803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 10595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\\', shl_stdout); 10605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else if (!inquote) { 10615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\'', shl_stdout); 106203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra inquote = true; 10635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc(*p, shl_stdout); 10655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (inquote) 10675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putc('\'', shl_stdout); 10685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 10695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 10715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Print things in columns and rows - func() is called to format 10725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * the i-th element 10735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 10745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 10755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruprint_columns(struct shf *shf, int n, 107603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *(*func)(char *, size_t, int, const void *), 107703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra const void *arg, size_t max_oct, size_t max_colz, bool prefcol) 10785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 107903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int i, r, c, rows, cols, nspace, max_col; 10805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *str; 10815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 10825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (n <= 0) { 10835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifndef MKSH_SMALL 10845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru internal_warningf("print_columns called with n=%d <= 0", n); 10855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 10865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 10875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 10885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 108903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (max_colz > 2147483647) { 109003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifndef MKSH_SMALL 109103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra internal_warningf("print_columns called with max_col=%zu > INT_MAX", 109203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra max_colz); 109303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 109403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return; 109503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 109603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra max_col = (int)max_colz; 109703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 10985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ++max_oct; 10995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru str = alloc(max_oct, ATEMP); 11005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* ensure x_cols is valid first */ 11025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (x_cols < MIN_COLS) 11035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru change_winsz(); 11045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 11065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * We use (max_col + 1) to consider the space separator. 11075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Note that no space is printed after the last column 11085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to avoid problems with terminals that have auto-wrap. 11095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cols = x_cols / (max_col + 1); 11115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* if we can only print one column anyway, skip the goo */ 11135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cols < 2) { 11145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (i = 0; i < n; ++i) 11155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%s \n", 11165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*func)(str, max_oct, i, arg)); 11175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto out; 11185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rows = (n + cols - 1) / cols; 11215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (prefcol && cols > rows) { 11225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = rows; 11235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rows = cols > n ? n : cols; 11245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru cols = i; 11255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru max_col = -max_col; 11285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nspace = (x_cols + max_col * cols) / cols; 11295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nspace <= 0) 11305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru nspace = 1; 11315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (r = 0; r < rows; r++) { 11325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (c = 0; c < cols; c++) { 11335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = c * rows + r; 11345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (i < n) { 11355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%*s", max_col, 11365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*func)(str, max_oct, i, arg)); 11375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c + 1 < cols) 11385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_fprintf(shf, "%*s", nspace, null); 11395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru shf_putchar('\n', shf); 11425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru out: 11445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru afree(str, ATEMP); 11455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* Strip any nul bytes from buf - returns new length (nbytes - # of nuls) */ 11485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 11495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrip_nuls(char *buf, int nbytes) 11505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 11515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dst; 11525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 115303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 115403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * nbytes check because some systems (older FreeBSDs) have a 115503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * buggy memchr() 11565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 11575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (nbytes && (dst = memchr(buf, '\0', nbytes))) { 11585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *end = buf + nbytes; 11595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *p, *q; 11605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (p = dst; p < end; p = q) { 11625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* skip a block of nulls */ 11635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (++p < end && *p == '\0') 11645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 11655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* find end of non-null block */ 11665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(q = memchr(p, '\0', end - p))) 11675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru q = end; 11685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memmove(dst, p, q - p); 11695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst += q - p; 11705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *dst = '\0'; 11725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 117503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 117603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Like read(2), but if read fails due to non-blocking flag, 117703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * resets flag and restarts read. 11785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 117903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrassize_t 118003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrablocking_read(int fd, char *buf, size_t nbytes) 11815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 118203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ssize_t ret; 118303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool tried_reset = false; 11845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 11855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((ret = read(fd, buf, nbytes)) < 0) { 11865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!tried_reset && errno == EAGAIN) { 11875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (reset_nonblock(fd) > 0) { 118803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tried_reset = true; 11895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 11905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errno = EAGAIN; 11925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 11945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 11955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (ret); 11965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 11975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 119803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* 119903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Reset the non-blocking flag on the specified file descriptor. 12005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Returns -1 if there was an error, 0 if non-blocking wasn't set, 12015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * 1 if it was. 12025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 12035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 12045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querureset_nonblock(int fd) 12055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int flags; 12075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 12085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((flags = fcntl(fd, F_GETFL, 0)) < 0) 12095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(flags & O_NONBLOCK)) 12115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 12125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru flags &= ~O_NONBLOCK; 12135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fcntl(fd, F_SETFL, flags) < 0) 12145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 12155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (1); 12165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 121803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* getcwd(3) equivalent, allocates from ATEMP but doesn't resize */ 12195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 122003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraksh_get_wd(void) 12215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 12225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef NO_PATH_MAX 122303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *rv, *cp; 122403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 122503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp = get_current_dir_name())) { 122603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(rv, cp, ATEMP); 122703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra free_gnu_gcdn(cp); 12285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else 122903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = NULL; 12305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#else 123103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *rv; 123203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 123303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!getcwd((rv = alloc(PATH_MAX + 1, ATEMP)), PATH_MAX)) { 123403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(rv, ATEMP); 123503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = NULL; 123603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 12375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 12385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 123903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 12405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 12415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 124203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrachar * 124303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrado_realpath(const char *upath) 124403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 124503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *xp, *ip, *tp, *ipath, *ldest = NULL; 124603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XString xs; 124703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ptrdiff_t pos; 124803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 124903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int llen; 125003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct stat sb; 125103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef NO_PATH_MAX 125203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t ldestlen = 0; 125303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathlen sb.st_size 125403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathcnd (ldestlen < (pathlen + 1)) 125503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 125603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathlen PATH_MAX 125703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define pathcnd (!ldest) 125803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 125903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* max. recursion depth */ 126003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int symlinks = 32; 126103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 126203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (upath[0] == '/') { 126303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* upath is an absolute pathname */ 126403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(ipath, upath, ATEMP); 126503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 126603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* upath is a relative pathname, prepend cwd */ 126703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((tp = ksh_get_wd()) == NULL || tp[0] != '/') 126803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (NULL); 126903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ipath = shf_smprintf("%s%s%s", tp, "/", upath); 127003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(tp, ATEMP); 127103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 127203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 127303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* ipath and upath are in memory at the same time -> unchecked */ 127403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xinit(xs, xp, strlen(ip = ipath) + 1, ATEMP); 127503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 127603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* now jump into the deep of the loop */ 127703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto beginning_of_a_pathname; 127803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 127903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip) { 128003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip slashes in input */ 128103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 128203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 128303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 128403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 128503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 128603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get next pathname component from input */ 128703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = ip; 128803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip && *ip != '/') 128903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 129003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra len = ip - tp; 129103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 129203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check input for "." and ".." */ 129303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp[0] == '.') { 129403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (len == 1) 129503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just continue with the next one */ 129603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 129703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (len == 2 && tp[1] == '.') { 129803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* strip off last pathname component */ 129903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (xp > Xstring(xs, xp)) 130003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*--xp == '/') 130103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 130203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* then continue with the next one */ 130303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra continue; 130403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 130503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 130603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 130703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* store output position away, then append slash to output */ 130803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pos = Xsavepos(xs, xp); 130903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 1 for the '/' and len + 1 for tp and the NUL from below */ 131003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XcheckN(xs, xp, 1 + len + 1); 131103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 131203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 131303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append next pathname component to output */ 131403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(xp, tp, len); 131503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp += len; 131603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *xp = '\0'; 131703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 131803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* lstat the current output, see if it's a symlink */ 131903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (lstat(Xstring(xs, xp), &sb)) { 132003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* lstat failed */ 132103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errno == ENOENT) { 132203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* because the pathname does not exist */ 132303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 132403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip any trailing slashes */ 132503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 132603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* no more components left? */ 132703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 132803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* we can still return successfully */ 132903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 133003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* more components left? fall through */ 133103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 133203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* not ENOENT or not at the end of ipath */ 133303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 133403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 133503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 133603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check if we encountered a symlink? */ 133703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (S_ISLNK(sb.st_mode)) { 133803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* reached maximum recursion depth? */ 133903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!symlinks--) { 134003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* yep, prevent infinite loops */ 134103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ELOOP; 134203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 134303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 134403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 134503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get symlink(7) target */ 134603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (pathcnd) { 134703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef NO_PATH_MAX 134803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (notoktoadd(pathlen, 1)) { 134903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ENAMETOOLONG; 135003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 135103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 135203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 135303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ldest = aresize(ldest, pathlen + 1, ATEMP); 135403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 135503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra llen = readlink(Xstring(xs, xp), ldest, pathlen); 135603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (llen < 0) 135703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* oops... */ 135803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 135903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ldest[llen] = '\0'; 136003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 136103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 136203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * restart if symlink target is an absolute path, 136303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * otherwise continue with currently resolved prefix 136403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 136503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append rest of current input path to link target */ 136603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = shf_smprintf("%s%s%s", ldest, *ip ? "/" : "", ip); 136703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 136803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ip = ipath = tp; 136903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest[0] != '/') { 137003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* symlink target is a relative path */ 137103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp = Xrestpos(xs, xp, pos); 137203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 137303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* symlink target is an absolute path */ 137403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra xp = Xstring(xs, xp); 137503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra beginning_of_a_pathname: 137603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* assert: (ip == ipath)[0] == '/' */ 137703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* assert: xp == xs.beg => start of path */ 137803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 137903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* exactly two leading slashes? (SUSv4 3.266) */ 138003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ip[1] == '/' && ip[2] != '/') { 138103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep them, e.g. for UNC pathnames */ 138203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 138303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 138403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 138503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 138603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* otherwise (no symlink) merely go on */ 138703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 138803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 138903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 139003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * either found the target and successfully resolved it, 139103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * or found its parent directory and may create it 139203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 139303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Xlength(xs, xp) == 0) 139403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 139503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if the resolved pathname is "", make it "/", 139603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * otherwise do not add a trailing slash 139703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 139803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '/'); 139903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xput(xs, xp, '\0'); 140003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 140103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 140203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if source path had a trailing slash, check if target path 140303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * is not a non-directory existing file 140403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 140503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ip > ipath && ip[-1] == '/') { 140603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (stat(Xstring(xs, xp), &sb)) { 140703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (errno != ENOENT) 140803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 140903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!S_ISDIR(sb.st_mode)) { 141003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = ENOTDIR; 141103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto notfound; 141203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 141303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* target now either does not exist or is a directory */ 141403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 141503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 141603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* return target path */ 141703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest != NULL) 141803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ldest, ATEMP); 141903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 142003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (Xclose(xs, xp)); 142103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 142203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra notfound: 142303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* save; freeing memory might trash it */ 142403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra llen = errno; 142503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ldest != NULL) 142603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ldest, ATEMP); 142703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(ipath, ATEMP); 142803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 142903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errno = llen; 143003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (NULL); 143103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 143203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef pathlen 143303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#undef pathcnd 143403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 143503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 143603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/** 14375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Makes a filename into result using the following algorithm. 14385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - make result NULL 14395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if file starts with '/', append file to result & set cdpathp to NULL 14405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if file starts with ./ or ../ append cwd and file to result 14415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and set cdpathp to NULL 14425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - if the first element of cdpathp doesnt start with a '/' xx or '.' xx 14435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * then cwd is appended to result. 14445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - the first element of cdpathp is appended to result 14455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - file is appended to result 14465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * - cdpathp is set to the start of the next element in cdpathp (or NULL 14475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * if there are no more elements. 14485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * The return value indicates whether a non-null element from cdpathp 14495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * was appended to result. 14505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 145103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrastatic int 14525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querumake_path(const char *cwd, const char *file, 145303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* pointer to colon-separated list */ 145403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char **cdpathp, 14555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XString *xsp, 14565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int *phys_pathp) 14575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 14585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int rval = 0; 14595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru bool use_cdpath = true; 14605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *plist; 146103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len, plen = 0; 14625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *xp = Xstring(*xsp, xp); 14635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!file) 14655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru file = null; 14665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (file[0] == '/') { 14685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *phys_pathp = 0; 14695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 14705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 14715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (file[0] == '.') { 14725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char c = file[1]; 14735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '.') 14755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = file[2]; 14765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '/' || c == '\0') 14775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 14785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru plist = *cdpathp; 14815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!plist) 14825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru use_cdpath = false; 14835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (use_cdpath) { 14845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *pend; 14855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (pend = plist; *pend && *pend != ':'; pend++) 14875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ; 14885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru plen = pend - plist; 14895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cdpathp = *pend ? pend + 1 : NULL; 14905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 14915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 14925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((!use_cdpath || !plen || plist[0] != '/') && 14935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (cwd && *cwd)) { 14945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(cwd); 14955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, len); 14965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, cwd, len); 14975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += len; 14985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cwd[len - 1] != '/') 14995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xput(*xsp, xp, '/'); 15005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *phys_pathp = Xlength(*xsp, xp); 15025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (use_cdpath && plen) { 15035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, plen); 15045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, plist, plen); 15055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru xp += plen; 15065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (plist[plen - 1] != '/') 15075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru Xput(*xsp, xp, '/'); 15085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru rval = 1; 15095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 15115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru len = strlen(file) + 1; 15135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru XcheckN(*xsp, xp, len); 15145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(xp, file, len); 15155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!use_cdpath) 15175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru *cdpathp = NULL; 15185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 15195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (rval); 15205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 15215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 152203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/*- 15235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Simplify pathnames containing "." and ".." entries. 152403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * 152503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * simplify_path(this) = that 152603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /a/b/c/./../d/.. /a/b 152703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * //./C/foo/bar/../baz //C/foo/baz 152803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/ /foo 152903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/../../bar /bar 153003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * /foo/./blah/.. /foo 153103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * . . 153203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * .. .. 153303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ./foo foo 153403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * foo/../../../bar ../../bar 15355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 15365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 153703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrasimplify_path(char *p) 15385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 153903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *dp, *ip, *sp, *tp; 154003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t len; 154103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool needslash; 15425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 154303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (*p) { 154403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 0: 15455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return; 154603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '/': 154703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* exactly two leading slashes? (SUSv4 3.266) */ 154803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (p[1] == '/' && p[2] != '/') 154903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep them, e.g. for UNC pathnames */ 155003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++p; 155103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 155203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 155303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra default: 155403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = false; 155503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 155603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp = ip = sp = p; 15575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 155803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip) { 155903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* skip slashes in input */ 156003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip == '/') 156103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 156203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!*ip) 15635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 15645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 156503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* get next pathname component from input */ 156603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra tp = ip; 156703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (*ip && *ip != '/') 156803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ++ip; 156903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra len = ip - tp; 157003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 157103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* check input for "." and ".." */ 157203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (tp[0] == '.') { 157303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (len == 1) 157403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* just continue with the next one */ 15755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 157603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (len == 2 && tp[1] == '.') { 157703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* parent level, but how? */ 157803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*p == '/') 157903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* absolute path, only one way */ 158003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto strip_last_component; 158103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else if (dp > sp) { 158203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* relative path, with subpaths */ 158303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = false; 158403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strip_last_component: 158503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* strip off last pathname component */ 158603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while (dp > sp) 158703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (*--dp == '/') 158803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 158903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 159003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* relative path, at its beginning */ 159103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (needslash) 159203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* or already dotdot-slash'd */ 159303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '/'; 159403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* keep dotdot-slash if not absolute */ 159503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '.'; 159603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '.'; 159703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 159803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra sp = dp; 159903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 160003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* then continue with the next one */ 16015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru continue; 16025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 16045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 160503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (needslash) 160603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = '/'; 16075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 160803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append next pathname component to output */ 160903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memmove(dp, tp, len); 161003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dp += len; 161103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 161203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* append slash if we continue */ 161303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra needslash = true; 161403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* try next component */ 16155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 161603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (dp == p) 161703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* empty path -> dot */ 161803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp++ = needslash ? '/' : '.'; 161903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra *dp = '\0'; 16205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 16215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 16225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruvoid 162303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraset_current_wd(const char *nwd) 16245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 162503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *allocd = NULL; 16265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 162703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (nwd == NULL) { 162803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = ksh_get_wd(); 162903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra nwd = allocd ? allocd : null; 163003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 163103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 163203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(current_wd, APERM); 163303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(current_wd, nwd, APERM); 163403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 163503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 163603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra} 163703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 163803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraint 163903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condrac_cd(const char **wp) 164003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra{ 164103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int optc, rv, phys_path; 164203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool physical = tobool(Flag(FPHYSICAL)); 164303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* was a node from cdpath added in? */ 164403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra int cdnode; 164503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* show where we went?, error for $PWD */ 164603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bool printpath = false, eflag = false; 164703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra struct tbl *pwd_s, *oldpwd_s; 164803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XString xs; 164903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *dir, *allocd = NULL, *tryp, *pwd, *cdpath; 165003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 165103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra while ((optc = ksh_getopt(wp, &builtin_opt, "eLP")) != -1) 165203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra switch (optc) { 165303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'e': 165403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra eflag = true; 165503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 165603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'L': 165703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra physical = false; 165803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 165903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case 'P': 166003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra physical = true; 166103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra break; 166203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra case '?': 166303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 166403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 166503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra wp += builtin_opt.optind; 166603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 166703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Flag(FRESTRICTED)) { 166803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("restricted shell - can't cd"); 166903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 167003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 167103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 167203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd_s = global("PWD"); 167303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra oldpwd_s = global("OLDPWD"); 167403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 167503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!wp[0]) { 167603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* No arguments - go home */ 167703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((dir = str_val(global("HOME"))) == null) { 167803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("no home directory (HOME not set)"); 167903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 168003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 168103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!wp[1]) { 168203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* One argument: - or dir */ 168303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra strdupx(allocd, wp[0], ATEMP); 168403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (ksh_isdash((dir = allocd))) { 168503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 168603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = NULL; 168703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dir = str_val(oldpwd_s); 168803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (dir == null) { 168903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("no OLDPWD"); 169003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 169103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 169203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra printpath = true; 169303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 169403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!wp[2]) { 169503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Two arguments - substitute arg1 in PWD for arg2 */ 169603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra size_t ilen, olen, nlen, elen; 169703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *cp; 169803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 169903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (!current_wd[0]) { 170003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("can't determine current directory"); 170103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 170203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 170303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 170403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * substitute arg1 for arg2 in current path. 170503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * if the first substitution fails because the cd fails 170603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * we could try to find another substitution. For now 170703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * we don't 170803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 170903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if ((cp = strstr(current_wd, wp[0])) == NULL) { 171003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("bad substitution"); 171103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 171203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 171303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /*- 171403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * ilen = part of current_wd before wp[0] 171503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * elen = part of current_wd after wp[0] 171603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * because current_wd and wp[1] need to be in memory at the 171703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * same time beforehand the addition can stay unchecked 171803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 171903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra ilen = cp - current_wd; 172003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra olen = strlen(wp[0]); 172103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra nlen = strlen(wp[1]); 172203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra elen = strlen(current_wd + ilen + olen) + 1; 172303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra dir = allocd = alloc(ilen + nlen + elen, ATEMP); 172403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir, current_wd, ilen); 172503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir + ilen, wp[1], nlen); 172603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra memcpy(dir + ilen + nlen, current_wd + ilen + olen, elen); 172703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra printpath = true; 172803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 172903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("too many arguments"); 173003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 173103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 173203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 173303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#ifdef NO_PATH_MAX 173403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* only a first guess; make_path will enlarge xs if necessary */ 173503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XinitN(xs, 1024, ATEMP); 173603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#else 173703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra XinitN(xs, PATH_MAX, ATEMP); 173803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#endif 173903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 174003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cdpath = str_val(global("CDPATH")); 174103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra do { 174203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra cdnode = make_path(current_wd, dir, &cdpath, &xs, &phys_path); 174303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (physical) 174403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = chdir(tryp = Xstring(xs, xp) + phys_path); 174503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else { 174603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra simplify_path(Xstring(xs, xp)); 174703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = chdir(tryp = Xstring(xs, xp)); 174803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 174903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } while (rv < 0 && cdpath != NULL); 175003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 175103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (rv < 0) { 175203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (cdnode) 175303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", dir, "bad directory"); 175403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra else 175503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra bi_errorf("%s: %s", tryp, strerror(errno)); 175603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 175703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 175803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (2); 175903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 176003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 176103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 0; 176203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 176303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* allocd (above) => dir, which is no longer used */ 176403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 176503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra allocd = NULL; 176603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 176703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Clear out tracked aliases with relative paths */ 176803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra flushcom(false); 176903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 177003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* 177103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * Set OLDPWD (note: unsetting OLDPWD does not disable this 177203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra * setting in AT&T ksh) 177303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra */ 177403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (current_wd[0]) 177503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Ignore failure (happens if readonly or integer) */ 177603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(oldpwd_s, current_wd, KSH_RETURN_ERROR); 177703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 177803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (Xstring(xs, xp)[0] != '/') { 177903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = NULL; 178003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if (!physical) { 178103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra goto norealpath_PWD; 178203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else if ((pwd = allocd = do_realpath(Xstring(xs, xp))) == NULL) { 178303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (eflag) 178403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 1; 178503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra norealpath_PWD: 178603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = Xstring(xs, xp); 178703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 178803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 178903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Set PWD */ 179003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (pwd) { 179103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra char *ptmp = pwd; 17925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 179303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra set_current_wd(ptmp); 179403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* Ignore failure (happens if readonly or integer) */ 179503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra setstr(pwd_s, ptmp, KSH_RETURN_ERROR); 179603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } else { 179703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra set_current_wd(null); 179803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra pwd = Xstring(xs, xp); 179903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /* XXX unset $PWD? */ 180003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (eflag) 180103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rv = 1; 18025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 180303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (printpath || cdnode) 180403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra shprintf("%s\n", pwd); 180503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 180603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra afree(allocd, ATEMP); 180703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra Xfree(xs, xp); 180803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra return (rv); 18095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 18105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 181103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 18125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef TIOCSCTTY 18135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruextern void chvt_reinit(void); 18145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustatic void 18165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchvt(const char *fn) 18175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 18185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char dv[20]; 18195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct stat sb; 18205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int fd; 18215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*fn == '-') { 18235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(dv, "-/dev/null", sizeof("-/dev/null")); 18245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fn = dv + 1; 18255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } else { 18265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stat(fn, &sb)) { 18275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(dv, "/dev/ttyC", 9); 18285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strlcpy(dv + 9, fn, sizeof(dv) - 9); 18295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stat(dv, &sb)) { 18305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strlcpy(dv + 8, fn, sizeof(dv) - 8); 18315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (stat(dv, &sb)) 183203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", 183303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "can't find tty", fn); 18345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fn = dv; 18365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!(sb.st_mode & S_IFCHR)) 183803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s %s %s", "chvt: not a char", "device", fn); 18395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((sb.st_uid != 0) && chown(fn, 0, 0)) 184003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s", "chvt", "can't chown root", fn); 18415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (((sb.st_mode & 07777) != 0600) && chmod(fn, (mode_t)0600)) 184203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s", "chvt", "can't chmod 0600", fn); 18435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if HAVE_REVOKE 18445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (revoke(fn)) 18455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 184603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra warningf(false, "%s: %s %s", "chvt", 184703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra "new shell is potentially insecure, can't revoke", 184803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra fn); 18495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fd = open(fn, O_RDWR)) == -1) { 18515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru sleep(1); 18525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((fd = open(fn, O_RDWR)) == -1) 185303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "can't open", fn); 18545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (fork()) { 18565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case -1: 185703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "fork", "failed"); 18585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 0: 18595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 18605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 18615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru exit(0); 18625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (setsid() == -1) 186403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "setsid", "failed"); 18655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fn != dv + 1) { 18665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (ioctl(fd, TIOCSCTTY, NULL) == -1) 186703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "TIOCSCTTY", "failed"); 18685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (tcflush(fd, TCIOFLUSH)) 186903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra errorf("%s: %s %s", "chvt", "TCIOFLUSH", "failed"); 18705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 18715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 0, false); 18725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 1, false); 18735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru ksh_dup2(fd, 2, false); 18745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (fd > 2) 18755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru close(fd); 187603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra { 187703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra register uint32_t h; 187803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra 187903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZATInit(h); 188003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZATUpdateMem(h, &rndsetupstate, sizeof(rndsetupstate)); 188103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra NZAATFinish(h); 188203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra rndset((long)h); 188303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra } 18845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru chvt_reinit(); 18855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 18865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 18875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 18885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef DEBUG 188903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define assert_eq(name, a, b) char name[a == b ? 1 : -1] 189003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra#define assert_ge(name, a, b) char name[a >= b ? 1 : -1] 189103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_ge(intsize_is_okay, sizeof(int), 4); 189203ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(intsizes_are_okay, sizeof(int), sizeof(unsigned int)); 189303ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_ge(longsize_is_okay, sizeof(long), sizeof(int)); 189403ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(arisize_is_okay, sizeof(mksh_ari_t), 4); 189503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(uarisize_is_okay, sizeof(mksh_uari_t), 4); 189603ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(sizesizes_are_okay, sizeof(size_t), sizeof(ssize_t)); 189703ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(ptrsizes_are_okay, sizeof(ptrdiff_t), sizeof(void *)); 189803ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_eq(ptrsize_is_sizet, sizeof(ptrdiff_t), sizeof(size_t)); 189903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra/* formatting routines assume this */ 190003ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condraassert_ge(ptr_fits_in_long, sizeof(long), sizeof(size_t)); 19015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 19035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrchr(char *p, int ch) 19045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru for (;; ++p) { 19065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (*p == ch) 19075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (p); 19085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!*p) 19095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 19105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* NOTREACHED */ 19125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 19155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrstr(char *b, const char *l) 19165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char first, c; 19185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t n; 19195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((first = *l++) == '\0') 19215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b); 19225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = strlen(l); 19235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru strstr_look: 19245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = *b++) != first) 19255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 19265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 19275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (strncmp(b, l, n)) 19285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto strstr_look; 19295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b - 1); 19305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 19325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_STRCASESTR 19345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruconst char * 19355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustristr(const char *b, const char *l) 19365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char first, c; 19385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru size_t n; 19395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((first = *l++), ((first = ksh_tolower(first)) == '\0')) 19415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b); 19425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru n = strlen(l); 19435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru stristr_look: 19445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while ((c = *b++), ((c = ksh_tolower(c)) != first)) 19455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (c == '\0') 19465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (NULL); 19475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (strncasecmp(b, l, n)) 19485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto stristr_look; 19495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (b - 1); 19505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 19525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#ifdef MKSH_SMALL 19545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 19555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrndup_(const char *src, size_t len, Area *ap) 19565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru char *dst = NULL; 19585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (src != NULL) { 19605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst = alloc(len + 1, ap); 19615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru memcpy(dst, src, len); 19625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru dst[len] = '\0'; 19635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 19645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (dst); 19655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruchar * 19685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querustrdup_(const char *src, Area *ap) 19695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (src == NULL ? NULL : strndup_(src, strlen(src), ap)); 19715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 19725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 19735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#if !HAVE_GETRUSAGE 19755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#define INVTCK(r,t) do { \ 19765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r.tv_usec = ((t) % (1000000 / CLK_TCK)) * (1000000 / CLK_TCK); \ 19775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru r.tv_sec = (t) / CLK_TCK; \ 19785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} while (/* CONSTCOND */ 0) 19795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 19815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Querugetrusage(int what, struct rusage *ru) 19825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 19835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru struct tms tms; 19845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru clock_t u, s; 19855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (/* ru == NULL || */ times(&tms) == (clock_t)-1) 19875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 19885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 19895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (what) { 19905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case RUSAGE_SELF: 19915155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru u = tms.tms_utime; 19925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tms.tms_stime; 19935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 19945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case RUSAGE_CHILDREN: 19955155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru u = tms.tms_cutime; 19965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru s = tms.tms_cstime; 19975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 19985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 19995155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru errno = EINVAL; 20005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 20015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru INVTCK(ru->ru_utime, u); 20035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru INVTCK(ru->ru_stime, s); 20045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (0); 20055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 20065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru#endif 20075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru/* 20095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * process the string available via fg (get a char) 20105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * and fp (put back a char) for backslash escapes, 20115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * assuming the first call to *fg gets the char di- 20125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * rectly after the backslash; return the character 20135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * (0..0xFF), Unicode (wc + 0x100), or -1 if no known 20145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * escape sequence was found 20155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 20165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruint 20175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queruunbksl(bool cstyle, int (*fg)(void), void (*fp)(int)) 20185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru{ 20195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru int wc, i, c, fc; 20205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 20215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru fc = (*fg)(); 20225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru switch (fc) { 20235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'a': 20245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 20255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * according to the comments in pdksh, \007 seems 20265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to be more portable than \a (due to HP-UX cc, 20275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * Ultrix cc, old pcc, etc.) so we avoid the escape 20285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * sequence altogether in mksh and assume ASCII 20295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 20305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 7; 20315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'b': 20335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\b'; 20345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'c': 20365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 20375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 20385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru c = (*fg)(); 20395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = CTRL(c); 20405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20415155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'E': 20425155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'e': 20435155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 033; 20445155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20455155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'f': 20465155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\f'; 20475155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20485155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'n': 20495155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\n'; 20505155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20515155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'r': 20525155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\r'; 20535155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20545155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 't': 20555155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\t'; 20565155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20575155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'v': 20585155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* assume ASCII here as well */ 20595155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 11; 20605155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20615155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '1': 20625155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '2': 20635155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '3': 20645155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '4': 20655155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '5': 20665155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '6': 20675155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '7': 20685155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 20695155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 20705155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 20715155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '0': 20725155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (cstyle) 20735155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(fc); 20745155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* 20755155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * look for an octal number with up to three 20765155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * digits, not counting the leading zero; 20775155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * convert it to a raw octet 20785155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 20795155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 0; 20805155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 3; 20815155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i--) 20825155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = (*fg)()) >= '0' && c <= '7') 20835155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = (wc << 3) + (c - '0'); 20845155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 20855155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(c); 20865155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20875155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 20885155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 20895155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'U': 20905155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 8; 209103ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (/* CONSTCOND */ 0) 20925155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 20935155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'u': 20945155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = 4; 209503ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra if (/* CONSTCOND */ 0) 20965155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* FALLTHROUGH */ 20975155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case 'x': 20985155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru i = cstyle ? -1 : 2; 209903ebf06f4e1112a0e9533b93062d169232c4cbfeGeremy Condra /** 21005155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * x: look for a hexadecimal number with up to 21015155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * two (C style: arbitrary) digits; convert 21025155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * to raw octet (C style: Unicode if >0xFF) 21035155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * u/U: look for a hexadecimal number with up to 21045155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru * four (U: eight) digits; convert to Unicode 21055155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru */ 21065155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = 0; 21075155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru while (i--) { 21085155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc <<= 4; 21095155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((c = (*fg)()) >= '0' && c <= '9') 21105155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - '0'; 21115155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c >= 'A' && c <= 'F') 21125155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - 'A' + 10; 21135155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else if (c >= 'a' && c <= 'f') 21145155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += c - 'a' + 10; 21155155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru else { 21165155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc >>= 4; 21175155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(c); 21185155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21195155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 21205155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 21215155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if ((cstyle && wc > 0xFF) || fc != 'x') 21225155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru /* Unicode marker */ 21235155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc += 0x100; 21245155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21255155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '\'': 21265155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru if (!cstyle) 21275155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru goto unknown_escape; 21285155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\''; 21295155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21305155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru case '\\': 21315155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru wc = '\\'; 21325155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru break; 21335155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru default: 21345155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru unknown_escape: 21355155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru (*fp)(fc); 21365155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (-1); 21375155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru } 21385155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru 21395155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru return (wc); 21405155f1c7438ef540d7b25eb70aa1639579795b07Jean-Baptiste Queru} 2141