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