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