1/* $NetBSD: misc.c,v 1.18 2006/03/17 22:48:10 christos 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.18 2006/03/17 22:48:10 christos 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 = (char *)xmalloc((size_t)((n - s) * sizeof(char))); 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 xfree((ptr_t) * av); 139 xfree((ptr_t) av0); 140} 141 142Char ** 143saveblk(Char **v) 144{ 145 Char **newv, **onewv; 146 147 if (v == NULL) 148 return NULL; 149 150 newv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **)); 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 = (char *) xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(char))); 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 = (Char **)xcalloc((size_t)(blklen(up) + blklen(vp) + 1), 208 sizeof(Char **)); 209 (void)blkcpy(wp, up); 210 return (blkcat(wp, vp)); 211} 212 213Char 214lastchr(Char *cp) 215{ 216 if (!cp) 217 return (0); 218 if (!*cp) 219 return (0); 220 while (cp[1]) 221 cp++; 222 return (*cp); 223} 224 225/* 226 * This routine is called after an error to close up 227 * any units which may have been left open accidentally. 228 */ 229void 230closem(void) 231{ 232 int f; 233 int nofile; 234 235#ifdef F_CLOSEM 236 nofile = FOLDSTD + 1; 237 if (fcntl(nofile, F_CLOSEM, 0) == -1) 238#endif 239 nofile = NOFILE; 240 241 for (f = 0; f < nofile; f++) 242 if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD && 243 f != FSHTTY) 244 (void) close(f); 245} 246 247void 248donefds(void) 249{ 250 (void)close(0); 251 (void)close(1); 252 (void)close(2); 253 254 didfds = 0; 255} 256 257/* 258 * Move descriptor i to j. 259 * If j is -1 then we just want to get i to a safe place, 260 * i.e. to a unit > 2. This also happens in dcopy. 261 */ 262int 263dmove(int i, int j) 264{ 265 if (i == j || i < 0) 266 return (i); 267 if (j >= 0) { 268 (void)dup2(i, j); 269 if (j != i) 270 (void)close(i); 271 return (j); 272 } 273 j = dcopy(i, j); 274 if (j != i) 275 (void)close(i); 276 return (j); 277} 278 279int 280dcopy(int i, int j) 281{ 282 if (i == j || i < 0 || (j < 0 && i > 2)) 283 return (i); 284 if (j >= 0) { 285 (void)dup2(i, j); 286 return (j); 287 } 288 return (renum(i, j)); 289} 290 291static int 292renum(int i, int j) 293{ 294 int k; 295 296 k = dup(i); 297 if (k < 0) 298 return (-1); 299 if (j == -1 && k > 2) 300 return (k); 301 if (k != j) { 302 j = renum(k, j); 303 (void)close(k); 304 return (j); 305 } 306 return (k); 307} 308 309/* 310 * Left shift a command argument list, discarding 311 * the first c arguments. Used in "shift" commands 312 * as well as by commands like "repeat". 313 */ 314void 315lshift(Char **v, int c) 316{ 317 Char **u; 318 319 for (u = v; *u && --c >= 0; u++) 320 xfree((ptr_t) *u); 321 (void)blkcpy(v, u); 322} 323 324int 325number(Char *cp) 326{ 327 if (!cp) 328 return(0); 329 if (*cp == '-') { 330 cp++; 331 if (!Isdigit(*cp)) 332 return (0); 333 cp++; 334 } 335 while (*cp && Isdigit(*cp)) 336 cp++; 337 return (*cp == 0); 338} 339 340Char ** 341copyblk(Char **v) 342{ 343 Char **nv; 344 345 nv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **)); 346 347 return (blkcpy(nv, v)); 348} 349 350#ifndef SHORT_STRINGS 351char * 352strend(char *cp) 353{ 354 if (!cp) 355 return (cp); 356 while (*cp) 357 cp++; 358 return (cp); 359} 360 361#endif /* SHORT_STRINGS */ 362 363Char * 364strip(Char *cp) 365{ 366 Char *dp; 367 368 dp = cp; 369 if (!cp) 370 return (cp); 371 while ((*dp++ &= TRIM) != '\0') 372 continue; 373 return (cp); 374} 375 376Char * 377quote(Char *cp) 378{ 379 Char *dp; 380 381 dp = cp; 382 if (!cp) 383 return (cp); 384 while (*dp != '\0') 385 *dp++ |= QUOTE; 386 return (cp); 387} 388 389void 390udvar(Char *name) 391{ 392 setname(vis_str(name)); 393 stderror(ERR_NAME | ERR_UNDVAR); 394 /* NOTREACHED */ 395} 396 397int 398prefix(Char *sub, Char *str) 399{ 400 for (;;) { 401 if (*sub == 0) 402 return (1); 403 if (*str == 0) 404 return (0); 405 if (*sub++ != *str++) 406 return (0); 407 } 408} 409