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