1 /*- 2 * Copyright (c) 1991, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Kenneth Almquist. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)miscbltin.c 8.4 (Berkeley) 05/04/95"; 13 #endif /* not lint */ 14 15 /* 16 * Miscelaneous builtins. 17 */ 18 19 #include <sys/types.h> 20 #include <sys/stat.h> 21 #include <sys/time.h> 22 #include <sys/resource.h> 23 #include <unistd.h> 24 #include <ctype.h> 25 26 #include "shell.h" 27 #include "options.h" 28 #include "var.h" 29 #include "output.h" 30 #include "memalloc.h" 31 #include "error.h" 32 #include "mystring.h" 33 34 #undef eflag 35 36 extern char **argptr; /* argument list for builtin command */ 37 38 39 /* 40 * The read builtin. The -e option causes backslashes to escape the 41 * following character. 42 * 43 * This uses unbuffered input, which may be avoidable in some cases. 44 */ 45 46 int 47 readcmd(argc, argv) 48 int argc; 49 char **argv; 50 { 51 char **ap; 52 int backslash; 53 char c; 54 int eflag; 55 char *prompt; 56 char *ifs; 57 char *p; 58 int startword; 59 int status; 60 int i; 61 62 eflag = 0; 63 prompt = NULL; 64 while ((i = nextopt("ep:")) != '\0') { 65 if (i == 'p') 66 prompt = optarg; 67 else 68 eflag = 1; 69 } 70 if (prompt && isatty(0)) { 71 out2str(prompt); 72 flushall(); 73 } 74 if (*(ap = argptr) == NULL) 75 error("arg count"); 76 if ((ifs = bltinlookup("IFS", 1)) == NULL) 77 ifs = nullstr; 78 status = 0; 79 startword = 1; 80 backslash = 0; 81 STARTSTACKSTR(p); 82 for (;;) { 83 if (read(0, &c, 1) != 1) { 84 status = 1; 85 break; 86 } 87 if (c == '\0') 88 continue; 89 if (backslash) { 90 backslash = 0; 91 if (c != '\n') 92 STPUTC(c, p); 93 continue; 94 } 95 if (eflag && c == '\\') { 96 backslash++; 97 continue; 98 } 99 if (c == '\n') 100 break; 101 if (startword && *ifs == ' ' && strchr(ifs, c)) { 102 continue; 103 } 104 startword = 0; 105 if (backslash && c == '\\') { 106 if (read(0, &c, 1) != 1) { 107 status = 1; 108 break; 109 } 110 STPUTC(c, p); 111 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) { 112 STACKSTRNUL(p); 113 setvar(*ap, stackblock(), 0); 114 ap++; 115 startword = 1; 116 STARTSTACKSTR(p); 117 } else { 118 STPUTC(c, p); 119 } 120 } 121 STACKSTRNUL(p); 122 setvar(*ap, stackblock(), 0); 123 while (*++ap != NULL) 124 setvar(*ap, nullstr, 0); 125 return status; 126 } 127 128 129 130 int 131 umaskcmd(argc, argv) 132 int argc; 133 char **argv; 134 { 135 char *ap; 136 int mask; 137 int i; 138 int symbolic_mode = 0; 139 140 while ((i = nextopt("S")) != '\0') { 141 symbolic_mode = 1; 142 } 143 144 INTOFF; 145 mask = umask(0); 146 umask(mask); 147 INTON; 148 149 if ((ap = *argptr) == NULL) { 150 if (symbolic_mode) { 151 char u[4], g[4], o[4]; 152 153 i = 0; 154 if ((mask & S_IRUSR) == 0) 155 u[i++] = 'r'; 156 if ((mask & S_IWUSR) == 0) 157 u[i++] = 'w'; 158 if ((mask & S_IXUSR) == 0) 159 u[i++] = 'x'; 160 u[i] = '\0'; 161 162 i = 0; 163 if ((mask & S_IRGRP) == 0) 164 g[i++] = 'r'; 165 if ((mask & S_IWGRP) == 0) 166 g[i++] = 'w'; 167 if ((mask & S_IXGRP) == 0) 168 g[i++] = 'x'; 169 g[i] = '\0'; 170 171 i = 0; 172 if ((mask & S_IROTH) == 0) 173 o[i++] = 'r'; 174 if ((mask & S_IWOTH) == 0) 175 o[i++] = 'w'; 176 if ((mask & S_IXOTH) == 0) 177 o[i++] = 'x'; 178 o[i] = '\0'; 179 180 out1fmt("u=%s,g=%s,o=%s\n", u, g, o); 181 } else { 182 out1fmt("%.4o\n", mask); 183 } 184 } else { 185 if (isdigit(*ap)) { 186 mask = 0; 187 do { 188 if (*ap >= '8' || *ap < '0') 189 error("Illegal number: %s", argv[1]); 190 mask = (mask << 3) + (*ap - '0'); 191 } while (*++ap != '\0'); 192 umask(mask); 193 } else { 194 void *set; 195 if ((set = setmode (ap)) == 0) 196 error("Illegal number: %s", ap); 197 198 mask = getmode (set, ~mask & 0777); 199 umask(~mask & 0777); 200 } 201 } 202 return 0; 203 } 204 205 /* 206 * ulimit builtin 207 * 208 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and 209 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with 210 * ash by J.T. Conklin. 211 * 212 * Public domain. 213 */ 214 215 struct limits { 216 const char *name; 217 int cmd; 218 int factor; /* multiply by to get rlim_{cur,max} values */ 219 char option; 220 }; 221 222 static const struct limits limits[] = { 223 #ifdef RLIMIT_CPU 224 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 225 #endif 226 #ifdef RLIMIT_FSIZE 227 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, 228 #endif 229 #ifdef RLIMIT_DATA 230 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 231 #endif 232 #ifdef RLIMIT_STACK 233 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 234 #endif 235 #ifdef RLIMIT_CORE 236 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, 237 #endif 238 #ifdef RLIMIT_RSS 239 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 240 #endif 241 #ifdef RLIMIT_MEMLOCK 242 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 243 #endif 244 #ifdef RLIMIT_NPROC 245 { "process(processes)", RLIMIT_NPROC, 1, 'p' }, 246 #endif 247 #ifdef RLIMIT_NOFILE 248 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 249 #endif 250 #ifdef RLIMIT_VMEM 251 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 252 #endif 253 #ifdef RLIMIT_SWAP 254 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 255 #endif 256 { (char *) 0, 0, 0, '\0' } 257 }; 258 259 int 260 ulimitcmd(argc, argv) 261 int argc; 262 char **argv; 263 { 264 register int c; 265 quad_t val; 266 enum { SOFT = 0x1, HARD = 0x2 } 267 how = SOFT | HARD; 268 const struct limits *l; 269 int set, all = 0; 270 int optc, what; 271 struct rlimit limit; 272 273 what = 'f'; 274 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 275 switch (optc) { 276 case 'H': 277 how = HARD; 278 break; 279 case 'S': 280 how = SOFT; 281 break; 282 case 'a': 283 all = 1; 284 break; 285 default: 286 what = optc; 287 } 288 289 for (l = limits; l->name && l->option != what; l++) 290 ; 291 if (!l->name) 292 error("ulimit: internal error (%c)\n", what); 293 294 set = *argptr ? 1 : 0; 295 if (set) { 296 char *p = *argptr; 297 298 if (all || argptr[1]) 299 error("ulimit: too many arguments\n"); 300 if (strcmp(p, "unlimited") == 0) 301 val = RLIM_INFINITY; 302 else { 303 val = (quad_t) 0; 304 305 while ((c = *p++) >= '0' && c <= '9') 306 { 307 val = (val * 10) + (long)(c - '0'); 308 if (val < (quad_t) 0) 309 break; 310 } 311 if (c) 312 error("ulimit: bad number\n"); 313 val *= l->factor; 314 } 315 } 316 if (all) { 317 for (l = limits; l->name; l++) { 318 getrlimit(l->cmd, &limit); 319 if (how & SOFT) 320 val = limit.rlim_cur; 321 else if (how & HARD) 322 val = limit.rlim_max; 323 324 out1fmt("%-20s ", l->name); 325 if (val == RLIM_INFINITY) 326 out1fmt("unlimited\n"); 327 else 328 { 329 val /= l->factor; 330 out1fmt("%ld\n", (long) val); 331 } 332 } 333 return 0; 334 } 335 336 getrlimit(l->cmd, &limit); 337 if (set) { 338 if (how & SOFT) 339 limit.rlim_cur = val; 340 if (how & HARD) 341 limit.rlim_max = val; 342 if (setrlimit(l->cmd, &limit) < 0) 343 error("ulimit: bad limit\n"); 344 } else { 345 if (how & SOFT) 346 val = limit.rlim_cur; 347 else if (how & HARD) 348 val = limit.rlim_max; 349 } 350 351 if (!set) { 352 if (val == RLIM_INFINITY) 353 out1fmt("unlimited\n"); 354 else 355 { 356 val /= l->factor; 357 out1fmt("%ld\n", (long) val); 358 } 359 } 360 return 0; 361 } 362