1 /* $OpenBSD: misc.c,v 1.25 2018/10/24 06:01:03 martijn Exp $ */ 2 /* $NetBSD: misc.c,v 1.6 1995/03/21 09:03:09 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1980, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <stdarg.h> 37 38 #include "csh.h" 39 #include "extern.h" 40 41 static int fdcmp(int); 42 static int renum(int, int); 43 44 int 45 any(char *s, int c) 46 { 47 if (!s) 48 return (0); /* Check for nil pointer */ 49 while (*s) 50 if (*s++ == c) 51 return (1); 52 return (0); 53 } 54 55 Char ** 56 blkend(Char **up) 57 { 58 59 while (*up) 60 up++; 61 return (up); 62 } 63 64 65 void 66 blkpr(FILE *fp, Char **av) 67 { 68 69 for (; *av; av++) { 70 (void) fprintf(fp, "%s", vis_str(*av)); 71 if (av[1]) 72 (void) fprintf(fp, " "); 73 } 74 } 75 76 int 77 blklen(Char **av) 78 { 79 int i = 0; 80 81 while (*av++) 82 i++; 83 return (i); 84 } 85 86 Char ** 87 blkcpy(Char **oav, Char **bv) 88 { 89 Char **av = oav; 90 91 while ((*av++ = *bv++) != NULL) 92 continue; 93 return (oav); 94 } 95 96 Char ** 97 blkcat(Char **up, Char **vp) 98 { 99 100 (void) blkcpy(blkend(up), vp); 101 return (up); 102 } 103 104 void 105 blkfree(Char **av0) 106 { 107 Char **av = av0; 108 109 if (!av0) 110 return; 111 for (; *av; av++) 112 free(* av); 113 free(av0); 114 } 115 116 Char ** 117 saveblk(Char **v) 118 { 119 Char **newv = xcalloc(blklen(v) + 1, sizeof(*newv)); 120 Char **onewv = newv; 121 122 while (*v) 123 *newv++ = Strsave(*v++); 124 return (onewv); 125 } 126 127 Char ** 128 blkspl(Char **up, Char **vp) 129 { 130 Char **wp = xcalloc(blklen(up) + blklen(vp) + 1, sizeof(*wp)); 131 132 (void) blkcpy(wp, up); 133 return (blkcat(wp, vp)); 134 } 135 136 Char 137 lastchr(Char *cp) 138 { 139 140 if (!cp) 141 return (0); 142 if (!*cp) 143 return (0); 144 while (cp[1]) 145 cp++; 146 return (*cp); 147 } 148 149 /* 150 * Returns 0 if fd is in use, 1 if fd is greater than the largest used file 151 * descriptor and -1 otherwise. 152 */ 153 static int 154 fdcmp(int fd) 155 { 156 int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY }; 157 int i, max; 158 159 max = -1; 160 for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) { 161 if (fd == fds[i]) 162 return (0); 163 if (fds[i] > max) 164 max = fds[i]; 165 } 166 if (fd > max) 167 return (1); 168 169 return (-1); 170 } 171 172 /* 173 * This routine is called after an error to close up 174 * any units which may have been left open accidentally. 175 */ 176 void 177 closem(void) 178 { 179 int f; 180 int max = sysconf(_SC_OPEN_MAX); 181 182 for (f = 0; f < max; f++) 183 switch (fdcmp(f)) { 184 case 0: 185 continue; 186 case 1: 187 closefrom(f); 188 return; 189 default: 190 close(f); 191 } 192 } 193 194 void 195 donefds(void) 196 { 197 (void) close(0); 198 (void) close(1); 199 (void) close(2); 200 201 didfds = 0; 202 } 203 204 /* 205 * Move descriptor i to j. 206 * If j is -1 then we just want to get i to a safe place, 207 * i.e. to a unit > 2. This also happens in dcopy. 208 */ 209 int 210 dmove(int i, int j) 211 { 212 213 if (i == j || i < 0) 214 return (i); 215 if (j >= 0) { 216 (void) dup2(i, j); 217 if (j != i) 218 (void) close(i); 219 return (j); 220 } 221 j = dcopy(i, j); 222 if (j != i) 223 (void) close(i); 224 return (j); 225 } 226 227 int 228 dcopy(int i, int j) 229 { 230 231 if (i == j || i < 0 || (j < 0 && i > 2)) 232 return (i); 233 if (j >= 0) { 234 (void) dup2(i, j); 235 return (j); 236 } 237 (void) close(j); 238 return (renum(i, j)); 239 } 240 241 static int 242 renum(int i, int j) 243 { 244 int k = dup(i); 245 246 if (k < 0) 247 return (-1); 248 if (j == -1 && k > 2) 249 return (k); 250 if (k != j) { 251 j = renum(k, j); 252 (void) close(k); 253 return (j); 254 } 255 return (k); 256 } 257 258 /* 259 * Left shift a command argument list, discarding 260 * the first c arguments. Used in "shift" commands 261 * as well as by commands like "repeat". 262 */ 263 void 264 lshift(Char **v, int c) 265 { 266 Char **u; 267 268 for (u = v; *u && --c >= 0; u++) 269 free(*u); 270 (void) blkcpy(v, u); 271 } 272 273 int 274 number(Char *cp) 275 { 276 if (!cp) 277 return(0); 278 if (*cp == '-') { 279 cp++; 280 if (!Isdigit(*cp)) 281 return (0); 282 cp++; 283 } 284 while (*cp && Isdigit(*cp)) 285 cp++; 286 return (*cp == 0); 287 } 288 289 Char ** 290 copyblk(Char **v) 291 { 292 Char **nv = xcalloc(blklen(v) + 1, sizeof(*nv)); 293 294 return (blkcpy(nv, v)); 295 } 296 297 Char * 298 strip(Char *cp) 299 { 300 Char *dp = cp; 301 302 if (!cp) 303 return (cp); 304 while ((*dp++ &= TRIM) != '\0') 305 continue; 306 return (cp); 307 } 308 309 Char * 310 quote(Char *cp) 311 { 312 Char *dp = cp; 313 314 if (!cp) 315 return (cp); 316 while (*dp != '\0') 317 *dp++ |= QUOTE; 318 return (cp); 319 } 320 321 void 322 udvar(Char *name) 323 { 324 325 setname(vis_str(name)); 326 stderror(ERR_NAME | ERR_UNDVAR); 327 } 328 329 int 330 prefix(Char *sub, Char *str) 331 { 332 333 for (;;) { 334 if (*sub == 0) 335 return (1); 336 if (*str == 0) 337 return (0); 338 if (*sub++ != *str++) 339 return (0); 340 } 341 } 342