1 /* $OpenBSD: misc.c,v 1.24 2018/09/18 17:48:22 millert 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 blkend(Char **up) 57 { 58 59 while (*up) 60 up++; 61 return (up); 62 } 63 64 65 void 66 blkpr(FILE *fp, Char **av) 67 { 68 69 for (; *av; av++) { 70 (void) fprintf(fp, "%s", vis_str(*av)); 71 if (av[1]) 72 (void) fprintf(fp, " "); 73 } 74 } 75 76 int 77 blklen(Char **av) 78 { 79 int i = 0; 80 81 while (*av++) 82 i++; 83 return (i); 84 } 85 86 Char ** 87 blkcpy(Char **oav, Char **bv) 88 { 89 Char **av = oav; 90 91 while ((*av++ = *bv++) != NULL) 92 continue; 93 return (oav); 94 } 95 96 Char ** 97 blkcat(Char **up, Char **vp) 98 { 99 100 (void) blkcpy(blkend(up), vp); 101 return (up); 102 } 103 104 void 105 blkfree(Char **av0) 106 { 107 Char **av = av0; 108 109 if (!av0) 110 return; 111 for (; *av; av++) 112 free(* av); 113 free(av0); 114 } 115 116 Char ** 117 saveblk(Char **v) 118 { 119 Char **newv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 120 Char **onewv = newv; 121 122 while (*v) 123 *newv++ = Strsave(*v++); 124 return (onewv); 125 } 126 127 Char ** 128 blkspl(Char **up, Char **vp) 129 { 130 Char **wp = xcalloc((size_t) (blklen(up) + blklen(vp) + 1), 131 sizeof(Char **)); 132 133 (void) blkcpy(wp, up); 134 return (blkcat(wp, vp)); 135 } 136 137 Char 138 lastchr(Char *cp) 139 { 140 141 if (!cp) 142 return (0); 143 if (!*cp) 144 return (0); 145 while (cp[1]) 146 cp++; 147 return (*cp); 148 } 149 150 /* 151 * Returns 0 if fd is in use, 1 if fd is greater than the largest used file 152 * descriptor and -1 otherwise. 153 */ 154 static int 155 fdcmp(int fd) 156 { 157 int fds[] = { SHIN, SHOUT, SHERR, OLDSTD, FSHTTY }; 158 int i, max; 159 160 max = -1; 161 for (i = 0; i < sizeof(fds)/sizeof(fds[0]); i++) { 162 if (fd == fds[i]) 163 return (0); 164 if (fds[i] > max) 165 max = fds[i]; 166 } 167 if (fd > max) 168 return (1); 169 170 return (-1); 171 } 172 173 /* 174 * This routine is called after an error to close up 175 * any units which may have been left open accidentally. 176 */ 177 void 178 closem(void) 179 { 180 int f; 181 int max = sysconf(_SC_OPEN_MAX); 182 183 for (f = 0; f < max; f++) 184 switch (fdcmp(f)) { 185 case 0: 186 continue; 187 case 1: 188 closefrom(f); 189 return; 190 default: 191 close(f); 192 } 193 } 194 195 void 196 donefds(void) 197 { 198 (void) close(0); 199 (void) close(1); 200 (void) close(2); 201 202 didfds = 0; 203 } 204 205 /* 206 * Move descriptor i to j. 207 * If j is -1 then we just want to get i to a safe place, 208 * i.e. to a unit > 2. This also happens in dcopy. 209 */ 210 int 211 dmove(int i, int j) 212 { 213 214 if (i == j || i < 0) 215 return (i); 216 if (j >= 0) { 217 (void) dup2(i, j); 218 if (j != i) 219 (void) close(i); 220 return (j); 221 } 222 j = dcopy(i, j); 223 if (j != i) 224 (void) close(i); 225 return (j); 226 } 227 228 int 229 dcopy(int i, int j) 230 { 231 232 if (i == j || i < 0 || (j < 0 && i > 2)) 233 return (i); 234 if (j >= 0) { 235 (void) dup2(i, j); 236 return (j); 237 } 238 (void) close(j); 239 return (renum(i, j)); 240 } 241 242 static int 243 renum(int i, int j) 244 { 245 int k = dup(i); 246 247 if (k < 0) 248 return (-1); 249 if (j == -1 && k > 2) 250 return (k); 251 if (k != j) { 252 j = renum(k, j); 253 (void) close(k); 254 return (j); 255 } 256 return (k); 257 } 258 259 /* 260 * Left shift a command argument list, discarding 261 * the first c arguments. Used in "shift" commands 262 * as well as by commands like "repeat". 263 */ 264 void 265 lshift(Char **v, int c) 266 { 267 Char **u; 268 269 for (u = v; *u && --c >= 0; u++) 270 free(*u); 271 (void) blkcpy(v, u); 272 } 273 274 int 275 number(Char *cp) 276 { 277 if (!cp) 278 return(0); 279 if (*cp == '-') { 280 cp++; 281 if (!Isdigit(*cp)) 282 return (0); 283 cp++; 284 } 285 while (*cp && Isdigit(*cp)) 286 cp++; 287 return (*cp == 0); 288 } 289 290 Char ** 291 copyblk(Char **v) 292 { 293 Char **nv = xcalloc((size_t) (blklen(v) + 1), sizeof(Char **)); 294 295 return (blkcpy(nv, v)); 296 } 297 298 Char * 299 strip(Char *cp) 300 { 301 Char *dp = cp; 302 303 if (!cp) 304 return (cp); 305 while ((*dp++ &= TRIM) != '\0') 306 continue; 307 return (cp); 308 } 309 310 Char * 311 quote(Char *cp) 312 { 313 Char *dp = cp; 314 315 if (!cp) 316 return (cp); 317 while (*dp != '\0') 318 *dp++ |= QUOTE; 319 return (cp); 320 } 321 322 void 323 udvar(Char *name) 324 { 325 326 setname(vis_str(name)); 327 stderror(ERR_NAME | ERR_UNDVAR); 328 } 329 330 int 331 prefix(Char *sub, Char *str) 332 { 333 334 for (;;) { 335 if (*sub == 0) 336 return (1); 337 if (*str == 0) 338 return (0); 339 if (*sub++ != *str++) 340 return (0); 341 } 342 } 343