Subversion Repositories HelenOS

Rev

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

Rev Author Line No. Line
2714 cejka 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
}