1 /* $OpenBSD: misc.c,v 1.20 2017/06/20 16:44:06 anton Exp $ */ 2 /* $NetBSD: misc.c,v 1.6 1995/03/21 09:03:09 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1980, 1991, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. Neither the name of the University nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 */ 32 33 #include <sys/types.h> 34 #include <stdlib.h> 35 #include <unistd.h> 36 #include <stdarg.h> 37 38 #include "csh.h" 39 #include "extern.h" 40 41 static int fdcmp(int); 42 static int renum(int, int); 43 44 int 45 any(char *s, int c) 46 { 47 if (!s) 48 return (0); /* Check for nil pointer */ 49 while (*s) 50 if (*s++ == c) 51 return (1); 52 return (0); 53 } 54 55 char * 56 strsave(char *s) 57 { 58 char *n; 59 char *p; 60 61 if (s == NULL) 62 s = ""; 63 for (p = s; *p++;) 64 continue; 65 n = p = xreallocarray(NULL, (p - s), sizeof(char)); 66 while ((*p++ = *s++) != '\0') 67 continue; 68 return (n); 69 } 70 71 Char ** 72 blkend(Char **up) 73 { 74 75 while (*up) 76 up++; 77 return (up); 78 } 79 80 81 void 82 blkpr(FILE *fp, Char **av) 83 { 84 85 for (; *av; av++) { 86 (void) fprintf(fp, "%s", vis_str(*av)); 87 if (av[1]) 88 (void) fprintf(fp, " "); 89 } 90 } 91 92 int 93 blklen(Char **av) 94 { 95 int i = 0; 96 97 while (*av++) 98 i++; 99 return (i); 100 } 101 102 Char ** 103 blkcpy(Char **oav, Char **bv) 104 { 105 Char **av = oav; 106 107 while ((*av++ = *bv++) != NULL) 108 continue; 109 return (oav); 110 } 111 112 Char ** 113 blkcat(Char **up, Char **vp) 114 { 115 116 (void) blkcpy(blkend(up), vp); 117 return (up); 118 } 119 120 void 121 blkfree(Char **av0) 122 { 123 Char **av = av0; 124 125 if (!av0) 126 return; 127 for (; *av; av++) 128 free(* av); 129 free(av0); 130 } 131 132 Char ** 133 saveblk(Char **v) 134 { 135 Char **newv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 136 Char **onewv = newv; 137 138 while (*v) 139 *newv++ = Strsave(*v++); 140 return (onewv); 141 } 142 143 Char ** 144 blkspl(Char **up, Char **vp) 145 { 146 Char **wp = xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 147 sizeof(Char **)); 148 149 (void) blkcpy(wp, up); 150 return (blkcat(wp, vp)); 151 } 152 153 Char 154 lastchr(Char *cp) 155 { 156 157 if (!cp) 158 return (0); 159 if (!*cp) 160 return (0); 161 while (cp[1]) 162 cp++; 163 return (*cp); 164 } 165 166 /* 167 * Returns 0 if fd is in use, 1 if fd is greater than the largest used file 168 * descriptor and -1 otherwise. 169 */ 170 static int 171 fdcmp(int fd) 172 { 173 int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY }; 174 int i, max; 175 176 max = -1; 177 for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) { 178 if (fd == fds[i]) 179 return (0); 180 if (fds[i] > max) 181 max = fds[i]; 182 } 183 if (fd > max) 184 return (1); 185 186 return (-1); 187 } 188 189 /* 190 * This routine is called after an error to close up 191 * any units which may have been left open accidentally. 192 */ 193 void 194 closem(void) 195 { 196 int f; 197 int max = sysconf(_SC_OPEN_MAX); 198 199 for (f = 0; f < max; f++) 200 switch (fdcmp(f)) { 201 case 0: 202 continue; 203 case 1: 204 closefrom(f); 205 return; 206 default: 207 close(f); 208 } 209 } 210 211 void 212 donefds(void) 213 { 214 (void) close(0); 215 (void) close(1); 216 (void) close(2); 217 218 didfds = 0; 219 } 220 221 /* 222 * Move descriptor i to j. 223 * If j is -1 then we just want to get i to a safe place, 224 * i.e. to a unit > 2. This also happens in dcopy. 225 */ 226 int 227 dmove(int i, int j) 228 { 229 230 if (i == j || i < 0) 231 return (i); 232 if (j >= 0) { 233 (void) dup2(i, j); 234 if (j != i) 235 (void) close(i); 236 return (j); 237 } 238 j = dcopy(i, j); 239 if (j != i) 240 (void) close(i); 241 return (j); 242 } 243 244 int 245 dcopy(int i, int j) 246 { 247 248 if (i == j || i < 0 || (j < 0 && i > 2)) 249 return (i); 250 if (j >= 0) { 251 (void) dup2(i, j); 252 return (j); 253 } 254 (void) close(j); 255 return (renum(i, j)); 256 } 257 258 static int 259 renum(int i, int j) 260 { 261 int k = dup(i); 262 263 if (k < 0) 264 return (-1); 265 if (j == -1 && k > 2) 266 return (k); 267 if (k != j) { 268 j = renum(k, j); 269 (void) close(k); 270 return (j); 271 } 272 return (k); 273 } 274 275 /* 276 * Left shift a command argument list, discarding 277 * the first c arguments. Used in "shift" commands 278 * as well as by commands like "repeat". 279 */ 280 void 281 lshift(Char **v, int c) 282 { 283 Char **u; 284 285 for (u = v; *u && --c >= 0; u++) 286 free(*u); 287 (void) blkcpy(v, u); 288 } 289 290 int 291 number(Char *cp) 292 { 293 if (!cp) 294 return(0); 295 if (*cp == '-') { 296 cp++; 297 if (!Isdigit(*cp)) 298 return (0); 299 cp++; 300 } 301 while (*cp && Isdigit(*cp)) 302 cp++; 303 return (*cp == 0); 304 } 305 306 Char ** 307 copyblk(Char **v) 308 { 309 Char **nv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 310 311 return (blkcpy(nv, v)); 312 } 313 314 Char * 315 strip(Char *cp) 316 { 317 Char *dp = cp; 318 319 if (!cp) 320 return (cp); 321 while ((*dp++ &= TRIM) != '\0') 322 continue; 323 return (cp); 324 } 325 326 Char * 327 quote(Char *cp) 328 { 329 Char *dp = cp; 330 331 if (!cp) 332 return (cp); 333 while (*dp != '\0') 334 *dp++ |= QUOTE; 335 return (cp); 336 } 337 338 void 339 udvar(Char *name) 340 { 341 342 setname(vis_str(name)); 343 stderror(ERR_NAME | ERR_UNDVAR); 344 } 345 346 int 347 prefix(Char *sub, Char *str) 348 { 349 350 for (;;) { 351 if (*sub == 0) 352 return (1); 353 if (*str == 0) 354 return (0); 355 if (*sub++ != *str++) 356 return (0); 357 } 358 } 359