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