miscbltin.c revision 17987
1118459Smtm/*- 2118459Smtm * Copyright (c) 1991, 1993 3118459Smtm * The Regents of the University of California. All rights reserved. 4118459Smtm * 5118459Smtm * This code is derived from software contributed to Berkeley by 6118459Smtm * Kenneth Almquist. 7118459Smtm * 8118459Smtm * Redistribution and use in source and binary forms, with or without 9118459Smtm * modification, are permitted provided that the following conditions 10118459Smtm * are met: 11118459Smtm * 1. Redistributions of source code must retain the above copyright 12118459Smtm * notice, this list of conditions and the following disclaimer. 13118459Smtm * 2. Redistributions in binary form must reproduce the above copyright 14118459Smtm * notice, this list of conditions and the following disclaimer in the 15118459Smtm * documentation and/or other materials provided with the distribution. 16118459Smtm * 3. All advertising materials mentioning features or use of this software 17118459Smtm * must display the following acknowledgement: 18118459Smtm * This product includes software developed by the University of 19118459Smtm * California, Berkeley and its contributors. 20118459Smtm * 4. Neither the name of the University nor the names of its contributors 21118459Smtm * may be used to endorse or promote products derived from this software 22118459Smtm * without specific prior written permission. 23118459Smtm * 24118459Smtm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25118459Smtm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26118459Smtm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27118459Smtm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28118459Smtm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29118459Smtm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30118459Smtm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31118459Smtm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32118459Smtm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33118459Smtm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34118459Smtm * SUCH DAMAGE. 35118459Smtm * 36118459Smtm * $Id: miscbltin.c,v 1.4 1995/10/21 00:47:30 joerg Exp $ 37 */ 38 39#ifndef lint 40static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 5/4/95"; 41#endif /* not lint */ 42 43/* 44 * Miscelaneous builtins. 45 */ 46 47#include <sys/types.h> 48#include <sys/stat.h> 49#include <sys/time.h> 50#include <sys/resource.h> 51#include <unistd.h> 52#include <ctype.h> 53 54#include "shell.h" 55#include "options.h" 56#include "var.h" 57#include "output.h" 58#include "memalloc.h" 59#include "error.h" 60#include "mystring.h" 61 62#undef eflag 63 64extern char **argptr; /* argument list for builtin command */ 65 66 67/* 68 * The read builtin. The -e option causes backslashes to escape the 69 * following character. 70 * 71 * This uses unbuffered input, which may be avoidable in some cases. 72 */ 73 74int 75readcmd(argc, argv) 76 int argc; 77 char **argv; 78{ 79 char **ap; 80 int backslash; 81 char c; 82 int eflag; 83 char *prompt; 84 char *ifs; 85 char *p; 86 int startword; 87 int status; 88 int i; 89 90 eflag = 0; 91 prompt = NULL; 92 while ((i = nextopt("ep:")) != '\0') { 93 if (i == 'p') 94 prompt = optarg; 95 else 96 eflag = 1; 97 } 98 if (prompt && isatty(0)) { 99 out2str(prompt); 100 flushall(); 101 } 102 if (*(ap = argptr) == NULL) 103 error("arg count"); 104 if ((ifs = bltinlookup("IFS", 1)) == NULL) 105 ifs = nullstr; 106 status = 0; 107 startword = 1; 108 backslash = 0; 109 STARTSTACKSTR(p); 110 for (;;) { 111 if (read(0, &c, 1) != 1) { 112 status = 1; 113 break; 114 } 115 if (c == '\0') 116 continue; 117 if (backslash) { 118 backslash = 0; 119 if (c != '\n') 120 STPUTC(c, p); 121 continue; 122 } 123 if (eflag && c == '\\') { 124 backslash++; 125 continue; 126 } 127 if (c == '\n') 128 break; 129 if (startword && *ifs == ' ' && strchr(ifs, c)) { 130 continue; 131 } 132 startword = 0; 133 if (backslash && c == '\\') { 134 if (read(0, &c, 1) != 1) { 135 status = 1; 136 break; 137 } 138 STPUTC(c, p); 139 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 140 STACKSTRNUL(p); 141 setvar(*ap, stackblock(), 0); 142 ap++; 143 startword = 1; 144 STARTSTACKSTR(p); 145 } else { 146 STPUTC(c, p); 147 } 148 } 149 STACKSTRNUL(p); 150 setvar(*ap, stackblock(), 0); 151 while (*++ap != NULL) 152 setvar(*ap, nullstr, 0); 153 return status; 154} 155 156 157 158int 159umaskcmd(argc, argv) 160 int argc; 161 char **argv; 162{ 163 char *ap; 164 int mask; 165 int i; 166 int symbolic_mode = 0; 167 168 while ((i = nextopt("S")) != '\0') { 169 symbolic_mode = 1; 170 } 171 172 INTOFF; 173 mask = umask(0); 174 umask(mask); 175 INTON; 176 177 if ((ap = *argptr) == NULL) { 178 if (symbolic_mode) { 179 char u[4], g[4], o[4]; 180 181 i = 0; 182 if ((mask & S_IRUSR) == 0) 183 u[i++] = 'r'; 184 if ((mask & S_IWUSR) == 0) 185 u[i++] = 'w'; 186 if ((mask & S_IXUSR) == 0) 187 u[i++] = 'x'; 188 u[i] = '\0'; 189 190 i = 0; 191 if ((mask & S_IRGRP) == 0) 192 g[i++] = 'r'; 193 if ((mask & S_IWGRP) == 0) 194 g[i++] = 'w'; 195 if ((mask & S_IXGRP) == 0) 196 g[i++] = 'x'; 197 g[i] = '\0'; 198 199 i = 0; 200 if ((mask & S_IROTH) == 0) 201 o[i++] = 'r'; 202 if ((mask & S_IWOTH) == 0) 203 o[i++] = 'w'; 204 if ((mask & S_IXOTH) == 0) 205 o[i++] = 'x'; 206 o[i] = '\0'; 207 208 out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 209 } else { 210 out1fmt("%.4o\n", mask); 211 } 212 } else { 213 if (isdigit(*ap)) { 214 mask = 0; 215 do { 216 if (*ap >= '8' || *ap < '0') 217 error("Illegal number: %s", argv[1]); 218 mask = (mask << 3) + (*ap - '0'); 219 } while (*++ap != '\0'); 220 umask(mask); 221 } else { 222 void *set; 223 if ((set = setmode (ap)) == 0) 224 error("Illegal number: %s", ap); 225 226 mask = getmode (set, ~mask & 0777); 227 umask(~mask & 0777); 228 } 229 } 230 return 0; 231} 232 233/* 234 * ulimit builtin 235 * 236 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 237 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 238 * ash by J.T. Conklin. 239 * 240 * Public domain. 241 */ 242 243struct limits { 244 const char *name; 245 int cmd; 246 int factor; /* multiply by to get rlim_{cur,max} values */ 247 char option; 248}; 249 250static const struct limits limits[] = { 251#ifdef RLIMIT_CPU 252 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 253#endif 254#ifdef RLIMIT_FSIZE 255 { "file(512-blocks)", RLIMIT_FSIZE, 512, 'f' }, 256#endif 257#ifdef RLIMIT_DATA 258 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 259#endif 260#ifdef RLIMIT_STACK 261 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 262#endif 263#ifdef RLIMIT_CORE 264 { "coredump(512-blocks)", RLIMIT_CORE, 512, 'c' }, 265#endif 266#ifdef RLIMIT_RSS 267 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 268#endif 269#ifdef RLIMIT_MEMLOCK 270 { "lockedmem(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 271#endif 272#ifdef RLIMIT_NPROC 273 { "process(processes)", RLIMIT_NPROC, 1, 'u' }, 274#endif 275#ifdef RLIMIT_NOFILE 276 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 277#endif 278#ifdef RLIMIT_VMEM 279 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 280#endif 281#ifdef RLIMIT_SWAP 282 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 283#endif 284 { (char *) 0, 0, 0, '\0' } 285}; 286 287int 288ulimitcmd(argc, argv) 289 int argc; 290 char **argv; 291{ 292 register int c; 293 quad_t val; 294 enum { SOFT = 0x1, HARD = 0x2 } 295 how = SOFT | HARD; 296 const struct limits *l; 297 int set, all = 0; 298 int optc, what; 299 struct rlimit limit; 300 301 what = 'f'; 302 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 303 switch (optc) { 304 case 'H': 305 how = HARD; 306 break; 307 case 'S': 308 how = SOFT; 309 break; 310 case 'a': 311 all = 1; 312 break; 313 default: 314 what = optc; 315 } 316 317 for (l = limits; l->name && l->option != what; l++) 318 ; 319 if (!l->name) 320 error("ulimit: internal error (%c)\n", what); 321 322 set = *argptr ? 1 : 0; 323 if (set) { 324 char *p = *argptr; 325 326 if (all || argptr[1]) 327 error("ulimit: too many arguments\n"); 328 if (strcmp(p, "unlimited") == 0) 329 val = RLIM_INFINITY; 330 else { 331 val = (quad_t) 0; 332 333 while ((c = *p++) >= '0' && c <= '9') 334 { 335 val = (val * 10) + (long)(c - '0'); 336 if (val < (quad_t) 0) 337 break; 338 } 339 if (c) 340 error("ulimit: bad number\n"); 341 val *= l->factor; 342 } 343 } 344 if (all) { 345 for (l = limits; l->name; l++) { 346 getrlimit(l->cmd, &limit); 347 if (how & SOFT) 348 val = limit.rlim_cur; 349 else if (how & HARD) 350 val = limit.rlim_max; 351 352 out1fmt("%-20s ", l->name); 353 if (val == RLIM_INFINITY) 354 out1fmt("unlimited\n"); 355 else 356 { 357 val /= l->factor; 358 out1fmt("%ld\n", (long) val); 359 } 360 } 361 return 0; 362 } 363 364 getrlimit(l->cmd, &limit); 365 if (set) { 366 if (how & SOFT) 367 limit.rlim_cur = val; 368 if (how & HARD) 369 limit.rlim_max = val; 370 if (setrlimit(l->cmd, &limit) < 0) 371 error("ulimit: bad limit\n"); 372 } else { 373 if (how & SOFT) 374 val = limit.rlim_cur; 375 else if (how & HARD) 376 val = limit.rlim_max; 377 } 378 379 if (!set) { 380 if (val == RLIM_INFINITY) 381 out1fmt("unlimited\n"); 382 else 383 { 384 val /= l->factor; 385 out1fmt("%ld\n", (long) val); 386 } 387 } 388 return 0; 389} 390