1 /* $NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 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 35 static char sccsid[] = "@(#)misc.c 8.1 (Berkeley) 5/31/93"; 36 #else 37 __RCSID("$NetBSD: misc.c,v 1.20 2013/07/16 17:47:43 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 52 static int renum(int, int); 53 54 int 55 any(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 65 char * 66 strsave(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 = xmalloc((size_t)(n - s) * sizeof(*p)); 76 while ((*p++ = *s++) != '\0') 77 continue; 78 return (r); 79 } 80 81 Char ** 82 blkend(Char **up) 83 { 84 while (*up) 85 up++; 86 return (up); 87 } 88 89 90 void 91 blkpr(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 100 int 101 blklen(Char **av) 102 { 103 int i; 104 105 i = 0; 106 while (*av++) 107 i++; 108 return (i); 109 } 110 111 Char ** 112 blkcpy(Char **oav, Char **bv) 113 { 114 Char **av; 115 116 av = oav; 117 while ((*av++ = *bv++) != NULL) 118 continue; 119 return (oav); 120 } 121 122 Char ** 123 blkcat(Char **up, Char **vp) 124 { 125 (void)blkcpy(blkend(up), vp); 126 return (up); 127 } 128 129 void 130 blkfree(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 142 Char ** 143 saveblk(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 158 char * 159 strstr(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 179 char * 180 strspl(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 = xmalloc((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 202 Char ** 203 blkspl(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 212 Char 213 lastchr(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 */ 228 void 229 closem(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 246 void 247 donefds(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 */ 261 int 262 dmove(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 278 int 279 dcopy(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 290 static int 291 renum(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 */ 313 void 314 lshift(Char **v, size_t c) 315 { 316 Char **u; 317 318 for (u = v; *u && c-- > 0; u++) 319 xfree((ptr_t) *u); 320 (void)blkcpy(v, u); 321 } 322 323 int 324 number(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 339 Char ** 340 copyblk(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 350 char * 351 strend(char *cp) 352 { 353 if (!cp) 354 return (cp); 355 while (*cp) 356 cp++; 357 return (cp); 358 } 359 360 #endif /* SHORT_STRINGS */ 361 362 Char * 363 strip(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 375 Char * 376 quote(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 388 void 389 udvar(Char *name) 390 { 391 setname(vis_str(name)); 392 stderror(ERR_NAME | ERR_UNDVAR); 393 /* NOTREACHED */ 394 } 395 396 int 397 prefix(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