1 /* $NetBSD: misc.c,v 1.16 2004/01/06 00:20:16 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.16 2004/01/06 00:20:16 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(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(char *s) 67 { 68 char *n, *p; 69 70 if (s == NULL) 71 s = ""; 72 for (p = s; *p++;) 73 continue; 74 n = p = (char *)xmalloc((size_t)((p - s) * sizeof(char))); 75 while ((*p++ = *s++) != '\0') 76 continue; 77 return (n); 78 } 79 80 Char ** 81 blkend(Char **up) 82 { 83 while (*up) 84 up++; 85 return (up); 86 } 87 88 89 void 90 blkpr(FILE *fp, Char **av) 91 { 92 for (; *av; av++) { 93 (void)fprintf(fp, "%s", vis_str(*av)); 94 if (av[1]) 95 (void)fprintf(fp, " "); 96 } 97 } 98 99 int 100 blklen(Char **av) 101 { 102 int i; 103 104 i = 0; 105 while (*av++) 106 i++; 107 return (i); 108 } 109 110 Char ** 111 blkcpy(Char **oav, Char **bv) 112 { 113 Char **av; 114 115 av = oav; 116 while ((*av++ = *bv++) != NULL) 117 continue; 118 return (oav); 119 } 120 121 Char ** 122 blkcat(Char **up, Char **vp) 123 { 124 (void)blkcpy(blkend(up), vp); 125 return (up); 126 } 127 128 void 129 blkfree(Char **av0) 130 { 131 Char **av; 132 133 av = av0; 134 if (!av0) 135 return; 136 for (; *av; av++) 137 xfree((ptr_t) * av); 138 xfree((ptr_t) av0); 139 } 140 141 Char ** 142 saveblk(Char **v) 143 { 144 Char **newv, **onewv; 145 146 newv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **)); 147 onewv = newv; 148 while (*v) 149 *newv++ = Strsave(*v++); 150 return (onewv); 151 } 152 153 #ifdef NOTUSED 154 char * 155 strstr(char *s, char *t) 156 { 157 do { 158 char *ss; 159 char *tt; 160 161 ss = s; 162 tt = t; 163 164 do 165 if (*tt == '\0') 166 return (s); 167 while (*ss++ == *tt++); 168 } while (*s++ != '\0'); 169 return (NULL); 170 } 171 172 #endif /* NOTUSED */ 173 174 #ifndef SHORT_STRINGS 175 char * 176 strspl(char *cp, char *dp) 177 { 178 char *ep, *p, *q; 179 180 if (!cp) 181 cp = ""; 182 if (!dp) 183 dp = ""; 184 for (p = cp; *p++;) 185 continue; 186 for (q = dp; *q++;) 187 continue; 188 ep = (char *) xmalloc((size_t)(((p - cp) + (q - dp) - 1) * sizeof(char))); 189 for (p = ep, q = cp; *p++ = *q++;) 190 continue; 191 for (p--, q = dp; *p++ = *q++;) 192 continue; 193 return (ep); 194 } 195 196 #endif 197 198 Char ** 199 blkspl(Char **up, Char **vp) 200 { 201 Char **wp; 202 203 wp = (Char **)xcalloc((size_t)(blklen(up) + blklen(vp) + 1), 204 sizeof(Char **)); 205 (void)blkcpy(wp, up); 206 return (blkcat(wp, vp)); 207 } 208 209 Char 210 lastchr(Char *cp) 211 { 212 if (!cp) 213 return (0); 214 if (!*cp) 215 return (0); 216 while (cp[1]) 217 cp++; 218 return (*cp); 219 } 220 221 /* 222 * This routine is called after an error to close up 223 * any units which may have been left open accidentally. 224 */ 225 void 226 closem(void) 227 { 228 int f; 229 int nofile; 230 231 #ifdef F_CLOSEM 232 nofile = FOLDSTD + 1; 233 if (fcntl(nofile, F_CLOSEM, 0) == -1) 234 #endif 235 nofile = NOFILE; 236 237 for (f = 0; f < nofile; f++) 238 if (f != SHIN && f != SHOUT && f != SHERR && f != OLDSTD && 239 f != FSHTTY) 240 (void) close(f); 241 } 242 243 void 244 donefds(void) 245 { 246 (void)close(0); 247 (void)close(1); 248 (void)close(2); 249 250 didfds = 0; 251 } 252 253 /* 254 * Move descriptor i to j. 255 * If j is -1 then we just want to get i to a safe place, 256 * i.e. to a unit > 2. This also happens in dcopy. 257 */ 258 int 259 dmove(int i, int j) 260 { 261 if (i == j || i < 0) 262 return (i); 263 if (j >= 0) { 264 (void)dup2(i, j); 265 if (j != i) 266 (void)close(i); 267 return (j); 268 } 269 j = dcopy(i, j); 270 if (j != i) 271 (void)close(i); 272 return (j); 273 } 274 275 int 276 dcopy(int i, int j) 277 { 278 if (i == j || i < 0 || (j < 0 && i > 2)) 279 return (i); 280 if (j >= 0) { 281 (void)dup2(i, j); 282 return (j); 283 } 284 (void)close(j); 285 return (renum(i, j)); 286 } 287 288 static int 289 renum(int i, int j) 290 { 291 int k; 292 293 k = dup(i); 294 if (k < 0) 295 return (-1); 296 if (j == -1 && k > 2) 297 return (k); 298 if (k != j) { 299 j = renum(k, j); 300 (void)close(k); 301 return (j); 302 } 303 return (k); 304 } 305 306 /* 307 * Left shift a command argument list, discarding 308 * the first c arguments. Used in "shift" commands 309 * as well as by commands like "repeat". 310 */ 311 void 312 lshift(Char **v, int c) 313 { 314 Char **u; 315 316 for (u = v; *u && --c >= 0; u++) 317 xfree((ptr_t) *u); 318 (void)blkcpy(v, u); 319 } 320 321 int 322 number(Char *cp) 323 { 324 if (!cp) 325 return(0); 326 if (*cp == '-') { 327 cp++; 328 if (!Isdigit(*cp)) 329 return (0); 330 cp++; 331 } 332 while (*cp && Isdigit(*cp)) 333 cp++; 334 return (*cp == 0); 335 } 336 337 Char ** 338 copyblk(Char **v) 339 { 340 Char **nv; 341 342 nv = (Char **)xcalloc((size_t)(blklen(v) + 1), sizeof(Char **)); 343 344 return (blkcpy(nv, v)); 345 } 346 347 #ifndef SHORT_STRINGS 348 char * 349 strend(char *cp) 350 { 351 if (!cp) 352 return (cp); 353 while (*cp) 354 cp++; 355 return (cp); 356 } 357 358 #endif /* SHORT_STRINGS */ 359 360 Char * 361 strip(Char *cp) 362 { 363 Char *dp; 364 365 dp = cp; 366 if (!cp) 367 return (cp); 368 while ((*dp++ &= TRIM) != '\0') 369 continue; 370 return (cp); 371 } 372 373 Char * 374 quote(Char *cp) 375 { 376 Char *dp; 377 378 dp = cp; 379 if (!cp) 380 return (cp); 381 while (*dp != '\0') 382 *dp++ |= QUOTE; 383 return (cp); 384 } 385 386 void 387 udvar(Char *name) 388 { 389 setname(vis_str(name)); 390 stderror(ERR_NAME | ERR_UNDVAR); 391 /* NOTREACHED */ 392 } 393 394 int 395 prefix(Char *sub, Char *str) 396 { 397 for (;;) { 398 if (*sub == 0) 399 return (1); 400 if (*str == 0) 401 return (0); 402 if (*sub++ != *str++) 403 return (0); 404 } 405 } 406