Subversion Repositories HelenOS

Rev

Rev 2714 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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