~ubuntu-branches/ubuntu/hardy/klibc/hardy-updates

« back to all changes in this revision

Viewing changes to dash/miscbltin.c

  • Committer: Bazaar Package Importer
  • Author(s): Jeff Bailey
  • Date: 2006-01-04 20:24:52 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20060104202452-ec4v3n829rymukuv
Tags: 1.1.15-0ubuntu1
* New upstream version.

* Patch to fix compilation on parisc64 kernels.

Show diffs side-by-side

added added

removed removed

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