~ubuntu-branches/ubuntu/precise/zsh/precise

« back to all changes in this revision

Viewing changes to .pc/debian-changes-4.3.10-15/Src/Builtins/rlimits.c

  • Committer: Bazaar Package Importer
  • Author(s): Angel Abad
  • Date: 2011-01-09 23:10:24 UTC
  • mfrom: (2.1.25 sid)
  • Revision ID: james.westby@ubuntu.com-20110109231024-7egfs040r26fq7fa
Tags: 4.3.11-1ubuntu1
* Merge from debian unstable. (LP: #700695) Remaining changes:
  - debian/zshrc: Enable completions by default, unless
    skip_global_compinit is set

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * rlimits.c - resource limit builtins
3
 
 *
4
 
 * This file is part of zsh, the Z shell.
5
 
 *
6
 
 * Copyright (c) 1992-1997 Paul Falstad
7
 
 * All rights reserved.
8
 
 *
9
 
 * Permission is hereby granted, without written agreement and without
10
 
 * license or royalty fees, to use, copy, modify, and distribute this
11
 
 * software and to distribute modified versions of this software for any
12
 
 * purpose, provided that the above copyright notice and the following
13
 
 * two paragraphs appear in all copies of this software.
14
 
 *
15
 
 * In no event shall Paul Falstad or the Zsh Development Group be liable
16
 
 * to any party for direct, indirect, special, incidental, or consequential
17
 
 * damages arising out of the use of this software and its documentation,
18
 
 * even if Paul Falstad and the Zsh Development Group have been advised of
19
 
 * the possibility of such damage.
20
 
 *
21
 
 * Paul Falstad and the Zsh Development Group specifically disclaim any
22
 
 * warranties, including, but not limited to, the implied warranties of
23
 
 * merchantability and fitness for a particular purpose.  The software
24
 
 * provided hereunder is on an "as is" basis, and Paul Falstad and the
25
 
 * Zsh Development Group have no obligation to provide maintenance,
26
 
 * support, updates, enhancements, or modifications.
27
 
 *
28
 
 */
29
 
 
30
 
#include "rlimits.mdh"
31
 
#include "rlimits.pro"
32
 
 
33
 
#if defined(HAVE_GETRLIMIT) && defined(RLIM_INFINITY)
34
 
 
35
 
enum {
36
 
    ZLIMTYPE_MEMORY,
37
 
    ZLIMTYPE_NUMBER,
38
 
    ZLIMTYPE_TIME,
39
 
    ZLIMTYPE_UNKNOWN
40
 
};
41
 
 
42
 
/* Generated rec array containing limits required for the limit builtin.     *
43
 
 * They must appear in this array in numerical order of the RLIMIT_* macros. */
44
 
 
45
 
# include "rlimits.h"
46
 
 
47
 
static rlim_t
48
 
zstrtorlimt(const char *s, char **t, int base)
49
 
{
50
 
    rlim_t ret = 0;
51
 
 
52
 
    if (strcmp(s, "unlimited") == 0) {
53
 
        if (t)
54
 
            *t = (char *) s + 9;
55
 
        return RLIM_INFINITY;
56
 
    }
57
 
# if defined(RLIM_T_IS_QUAD_T) || defined(RLIM_T_IS_LONG_LONG) || defined(RLIM_T_IS_UNSIGNED)
58
 
    if (!base) {
59
 
        if (*s != '0')
60
 
            base = 10;
61
 
        else if (*++s == 'x' || *s == 'X')
62
 
            base = 16, s++;
63
 
        else
64
 
            base = 8;
65
 
    } 
66
 
    if (base <= 10)
67
 
        for (; *s >= '0' && *s < ('0' + base); s++)
68
 
            ret = ret * base + *s - '0';
69
 
    else
70
 
        for (; idigit(*s) || (*s >= 'a' && *s < ('a' + base - 10))
71
 
             || (*s >= 'A' && *s < ('A' + base - 10)); s++)
72
 
            ret = ret * base + (idigit(*s) ? (*s - '0') : (*s & 0x1f) + 9);
73
 
    if (t)
74
 
        *t = (char *)s;
75
 
# else /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */
76
 
    ret = zstrtol(s, t, base);
77
 
# endif /* !RLIM_T_IS_QUAD_T && !RLIM_T_IS_LONG_LONG && !RLIM_T_IS_UNSIGNED */
78
 
    return ret;
79
 
}
80
 
 
81
 
/**/
82
 
static void
83
 
showlimitvalue(int lim, rlim_t val)
84
 
{
85
 
    /* display limit for resource number lim */
86
 
    if (lim < ZSH_NLIMITS)
87
 
        printf("%-16s", recs[lim]);
88
 
    else
89
 
    {
90
 
        /* Unknown limit, hence unknown units. */
91
 
        printf("%-16d", lim);
92
 
    }
93
 
    if (val == RLIM_INFINITY)
94
 
        printf("unlimited\n");
95
 
    else if (lim >= ZSH_NLIMITS)
96
 
    {
97
 
# ifdef RLIM_T_IS_QUAD_T
98
 
        printf("%qd\n", val);
99
 
# else
100
 
#  ifdef RLIM_T_IS_LONG_LONG
101
 
        printf("%lld\n", val);
102
 
#  else
103
 
#   ifdef RLIM_T_IS_UNSIGNED
104
 
        printf("%lu\n", val);
105
 
#   else
106
 
        printf("%ld\n", val);
107
 
#   endif /* RLIM_T_IS_UNSIGNED */
108
 
#  endif /* RLIM_T_IS_LONG_LONG */
109
 
# endif /* RLIM_T_IS_QUAD_T */
110
 
    }
111
 
    else if (limtype[lim] == ZLIMTYPE_TIME) {
112
 
        /* time-type resource -- display as hours, minutes and
113
 
           seconds. */
114
 
        printf("%d:%02d:%02d\n", (int)(val / 3600),
115
 
               (int)(val / 60) % 60, (int)(val % 60));
116
 
    } else if (limtype[lim] == ZLIMTYPE_NUMBER ||
117
 
               limtype[lim] == ZLIMTYPE_UNKNOWN) {
118
 
        /* pure numeric resource */
119
 
        printf("%d\n", (int)val);
120
 
    } else if (val >= 1024L * 1024L)
121
 
        /* memory resource -- display with `K' or `M' modifier */
122
 
# ifdef RLIM_T_IS_QUAD_T
123
 
        printf("%qdMB\n", val / (1024L * 1024L));
124
 
    else
125
 
        printf("%qdkB\n", val / 1024L);
126
 
# else
127
 
#  ifdef RLIM_T_IS_LONG_LONG
128
 
    printf("%lldMB\n", val / (1024L * 1024L));
129
 
    else
130
 
        printf("%lldkB\n", val / 1024L);
131
 
#  else
132
 
#   ifdef RLIM_T_IS_UNSIGNED
133
 
    printf("%luMB\n", val / (1024L * 1024L));
134
 
    else
135
 
        printf("%lukB\n", val / 1024L);
136
 
#   else
137
 
    printf("%ldMB\n", val / (1024L * 1024L));
138
 
    else
139
 
        printf("%ldkB\n", val / 1024L);
140
 
#   endif /* RLIM_T_IS_UNSIGNED */
141
 
#  endif /* RLIM_T_IS_LONG_LONG */
142
 
# endif /* RLIM_T_IS_QUAD_T */
143
 
}
144
 
 
145
 
/* Display resource limits.  hard indicates whether `hard' or `soft'  *
146
 
 * limits should be displayed.  lim specifies the limit, or may be -1 *
147
 
 * to show all.                                                       */
148
 
 
149
 
/**/
150
 
static int
151
 
showlimits(char *nam, int hard, int lim)
152
 
{
153
 
    int rt;
154
 
 
155
 
    if (lim >= ZSH_NLIMITS)
156
 
    {
157
 
        /*
158
 
         * Not configured into the shell.  Ask the OS
159
 
         * explicitly for this limit.
160
 
         */
161
 
        struct rlimit vals;
162
 
        if (getrlimit(lim, &vals) < 0)
163
 
        {
164
 
            zwarnnam(nam, "can't read limit: %e", errno);
165
 
            return 1;
166
 
        }
167
 
        showlimitvalue(lim, hard ? vals.rlim_max : vals.rlim_cur);
168
 
    }
169
 
    else if (lim != -1)
170
 
    {
171
 
        showlimitvalue(lim, hard ? limits[lim].rlim_max :
172
 
                       limits[lim].rlim_cur);
173
 
    }
174
 
    else
175
 
    {
176
 
        /* main loop over resource types */
177
 
        for (rt = 0; rt != ZSH_NLIMITS; rt++)
178
 
            showlimitvalue(rt, (hard) ? limits[rt].rlim_max :
179
 
                           limits[rt].rlim_cur);
180
 
    }
181
 
 
182
 
    return 0;
183
 
}
184
 
 
185
 
/* Display a resource limit, in ulimit style.  lim specifies which   *
186
 
 * limit should be displayed, and hard indicates whether the hard or *
187
 
 * soft limit should be displayed.                                   */
188
 
 
189
 
/**/
190
 
static int
191
 
printulimit(char *nam, int lim, int hard, int head)
192
 
{
193
 
    rlim_t limit;
194
 
 
195
 
    /* get the limit in question */
196
 
    if (lim >= ZSH_NLIMITS)
197
 
    {
198
 
        struct rlimit vals;
199
 
 
200
 
        if (getrlimit(lim, &vals) < 0)
201
 
        {
202
 
            zwarnnam(nam, "can't read limit: %e", errno);
203
 
            return 1;
204
 
        }
205
 
        limit = (hard) ? vals.rlim_max : vals.rlim_cur;
206
 
    }
207
 
    else
208
 
        limit = (hard) ? limits[lim].rlim_max : limits[lim].rlim_cur;
209
 
    /* display the appropriate heading */
210
 
    switch (lim) {
211
 
    case RLIMIT_CORE:
212
 
        if (head)
213
 
            printf("-c: core file size (blocks)    ");
214
 
        if (limit != RLIM_INFINITY)
215
 
            limit /= 512;
216
 
        break;
217
 
    case RLIMIT_DATA:
218
 
        if (head)
219
 
            printf("-d: data seg size (kbytes)     ");
220
 
        if (limit != RLIM_INFINITY)
221
 
            limit /= 1024;
222
 
        break;
223
 
    case RLIMIT_FSIZE:
224
 
        if (head)
225
 
            printf("-f: file size (blocks)         ");
226
 
        if (limit != RLIM_INFINITY)
227
 
            limit /= 512;
228
 
        break;
229
 
# ifdef HAVE_RLIMIT_SIGPENDING
230
 
    case RLIMIT_SIGPENDING:
231
 
        if (head)
232
 
            printf("-i: pending signals            ");
233
 
        break;
234
 
# endif
235
 
# ifdef HAVE_RLIMIT_MEMLOCK
236
 
    case RLIMIT_MEMLOCK:
237
 
        if (head)
238
 
            printf("-l: locked-in-memory size (kb) ");
239
 
        if (limit != RLIM_INFINITY)
240
 
            limit /= 1024;
241
 
        break;
242
 
# endif /* HAVE_RLIMIT_MEMLOCK */
243
 
/* If RLIMIT_VMEM and RLIMIT_RSS are defined and equal, avoid *
244
 
 * duplicate case statement.  Observed on QNX Neutrino 6.1.0. */
245
 
# if defined(HAVE_RLIMIT_RSS) && !defined(RLIMIT_VMEM_IS_RSS) && !defined(RLIMIT_RSS_IS_AS)
246
 
    case RLIMIT_RSS:
247
 
        if (head)
248
 
            printf("-m: resident set size (kbytes) ");
249
 
        if (limit != RLIM_INFINITY)
250
 
            limit /= 1024;
251
 
        break;
252
 
# endif /* HAVE_RLIMIT_RSS */
253
 
# if defined(HAVE_RLIMIT_VMEM) && defined(HAVE_RLIMIT_RSS) && defined(RLIMIT_VMEM_IS_RSS)
254
 
    case RLIMIT_VMEM:
255
 
        if (head)
256
 
            printf("-m: memory size (kb)           ");
257
 
        if (limit != RLIM_INFINITY)
258
 
            limit /= 1024;
259
 
        break;
260
 
# endif /* HAVE_RLIMIT_VMEM */
261
 
# ifdef HAVE_RLIMIT_NOFILE
262
 
    case RLIMIT_NOFILE:
263
 
        if (head)
264
 
            printf("-n: file descriptors           ");
265
 
        break;
266
 
# endif /* HAVE_RLIMIT_NOFILE */
267
 
# ifdef HAVE_RLIMIT_MSGQUEUE
268
 
    case RLIMIT_MSGQUEUE:
269
 
        if (head)
270
 
            printf("-q: bytes in POSIX msg queues  ");
271
 
        break;
272
 
# endif
273
 
    case RLIMIT_STACK:
274
 
        if (head)
275
 
            printf("-s: stack size (kbytes)        ");
276
 
        if (limit != RLIM_INFINITY)
277
 
            limit /= 1024;
278
 
        break;
279
 
    case RLIMIT_CPU:
280
 
        if (head)
281
 
            printf("-t: cpu time (seconds)         ");
282
 
        break;
283
 
# ifdef HAVE_RLIMIT_NPROC
284
 
    case RLIMIT_NPROC:
285
 
        if (head)
286
 
            printf("-u: processes                  ");
287
 
        break;
288
 
# endif /* HAVE_RLIMIT_NPROC */
289
 
# if defined(HAVE_RLIMIT_VMEM) && (!defined(HAVE_RLIMIT_RSS) || !defined(RLIMIT_VMEM_IS_RSS))
290
 
    case RLIMIT_VMEM:
291
 
        if (head)
292
 
            printf("-v: virtual memory size (kb)   ");
293
 
        if (limit != RLIM_INFINITY)
294
 
            limit /= 1024;
295
 
        break;
296
 
# endif /* HAVE_RLIMIT_VMEM */
297
 
# if defined HAVE_RLIMIT_AS && !defined(RLIMIT_VMEM_IS_AS)
298
 
    case RLIMIT_AS:
299
 
        if (head)
300
 
            printf("-v: address space (kb)         ");
301
 
        if (limit != RLIM_INFINITY)
302
 
            limit /= 1024;
303
 
        break;
304
 
# endif /* HAVE_RLIMIT_AS */
305
 
# ifdef HAVE_RLIMIT_LOCKS
306
 
    case RLIMIT_LOCKS:
307
 
        if (head)
308
 
            printf("-x: file locks                 ");
309
 
        break;
310
 
# endif /* HAVE_RLIMIT_LOCKS */
311
 
# ifdef HAVE_RLIMIT_AIO_MEM
312
 
    case RLIMIT_AIO_MEM:
313
 
        if (head)
314
 
            printf("-N %2d: AIO locked-in-memory (kb) ", RLIMIT_AIO_MEM);
315
 
        if (limit != RLIM_INFINITY)
316
 
            limit /= 1024;
317
 
        break;
318
 
# endif /* HAVE_RLIMIT_AIO_MEM */
319
 
# ifdef HAVE_RLIMIT_AIO_OPS
320
 
    case RLIMIT_AIO_OPS:
321
 
        if (head)
322
 
            printf("-N %2d: AIO operations          ", RLIMIT_AIO_OPS);
323
 
        break;
324
 
# endif /* HAVE_RLIMIT_AIO_OPS */
325
 
# ifdef HAVE_RLIMIT_TCACHE
326
 
    case RLIMIT_TCACHE:
327
 
        if (head)
328
 
            printf("-N %2d: cached threads          ", RLIMIT_TCACHE);
329
 
        break;
330
 
# endif /* HAVE_RLIMIT_TCACHE */
331
 
# ifdef HAVE_RLIMIT_SBSIZE
332
 
    case RLIMIT_SBSIZE:
333
 
        if (head)
334
 
            printf("-N %2d: socket buffer size (kb) ", RLIMIT_SBSIZE);
335
 
        if (limit != RLIM_INFINITY)
336
 
            limit /= 1024;
337
 
        break;
338
 
# endif /* HAVE_RLIMIT_SBSIZE */
339
 
# ifdef HAVE_RLIMIT_PTHREAD
340
 
    case RLIMIT_PTHREAD:
341
 
        if (head)
342
 
            printf("-N %2d: threads per process     ", RLIMIT_PTHREAD);
343
 
        break;
344
 
# endif /* HAVE_RLIMIT_PTHREAD */
345
 
# ifdef HAVE_RLIMIT_NICE
346
 
    case RLIMIT_NICE:
347
 
        if (head)
348
 
            printf("-e: max nice                   ");
349
 
        break;
350
 
# endif /* HAVE_RLIMIT_NICE */
351
 
# ifdef HAVE_RLIMIT_RTPRIO
352
 
    case RLIMIT_RTPRIO:
353
 
        if (head)
354
 
            printf("-r: max rt priority            ");
355
 
        break;
356
 
# endif /* HAVE_RLIMIT_RTPRIO */
357
 
    default:
358
 
        if (head)
359
 
            printf("-N %2d:                         ", lim);
360
 
        break;
361
 
    }
362
 
    /* display the limit */
363
 
    if (limit == RLIM_INFINITY)
364
 
        printf("unlimited\n");
365
 
    else {
366
 
# ifdef RLIM_T_IS_QUAD_T
367
 
        printf("%qd\n", limit);
368
 
# else
369
 
#  ifdef RLIM_T_IS_LONG_LONG
370
 
        printf("%lld\n", limit);
371
 
#  else
372
 
#   ifdef RLIM_T_IS_UNSIGNED
373
 
        printf("%lu\n", limit);
374
 
#   else
375
 
        printf("%ld\n", limit);
376
 
#   endif /* RLIM_T_IS_UNSIGNED */
377
 
#  endif /* RLIM_T_IS_LONG_LONG */
378
 
# endif /* RLIM_T_IS_QUAD_T */
379
 
    }
380
 
 
381
 
    return 0;
382
 
}
383
 
 
384
 
/**/
385
 
static int
386
 
do_limit(char *nam, int lim, rlim_t val, int hard, int soft, int set)
387
 
{
388
 
    if (lim >= ZSH_NLIMITS) {
389
 
        struct rlimit vals;
390
 
        if (getrlimit(lim, &vals) < 0)
391
 
        {
392
 
            /* best guess about error */
393
 
            zwarnnam(nam, "can't read limit: %e", errno);
394
 
            return 1;
395
 
        }
396
 
        if (hard)
397
 
        {
398
 
            if (val > vals.rlim_max && geteuid()) {
399
 
                zwarnnam(nam, "can't raise hard limits");
400
 
                return 1;
401
 
            }
402
 
            vals.rlim_max = val;
403
 
            /*
404
 
             * not show if all systems will do this silently, but
405
 
             * best be safe...
406
 
             */
407
 
            if (val < vals.rlim_cur)
408
 
                vals.rlim_cur = val;
409
 
        }
410
 
        if (soft || !hard) {
411
 
            if (val > vals.rlim_max) {
412
 
                zwarnnam(nam, "limit exceeds hard limit");
413
 
                return 1;
414
 
            }
415
 
            else
416
 
                vals.rlim_cur = val;
417
 
        }
418
 
        if (!set)
419
 
        {
420
 
            zwarnnam(nam,
421
 
                     "warning: unrecognised limit %d, use -s to set",
422
 
                     lim);
423
 
            return 1;
424
 
        }
425
 
        else if (setrlimit(lim, &vals) < 0)
426
 
        {
427
 
            zwarnnam(nam, "setrlimit failed: %e", errno);
428
 
            return 1;
429
 
        }
430
 
    } else {
431
 
        /* new limit is valid and has been interpreted; apply it to the
432
 
        specified resource */
433
 
        if (hard) {
434
 
            /* can only raise hard limits if running as root */
435
 
            if (val > current_limits[lim].rlim_max && geteuid()) {
436
 
                zwarnnam(nam, "can't raise hard limits");
437
 
                return 1;
438
 
            } else {
439
 
                limits[lim].rlim_max = val;
440
 
                if (val < limits[lim].rlim_cur)
441
 
                    limits[lim].rlim_cur = val;
442
 
            }
443
 
        }
444
 
        if (soft || !hard) {
445
 
            if (val > limits[lim].rlim_max) {
446
 
                /* no idea about this difference, don't intend to worry */
447
 
                if (*nam == 'u')
448
 
                {
449
 
                    /* ulimit does this */
450
 
                    if (val > current_limits[lim].rlim_max && geteuid()) {
451
 
                        zwarnnam(nam, "value exceeds hard limit");
452
 
                        return 1;
453
 
                    }
454
 
                    limits[lim].rlim_max = limits[lim].rlim_cur = val;
455
 
                } else {
456
 
                    /* but limit does this */
457
 
                    zwarnnam(nam, "limit exceeds hard limit");
458
 
                    return 1;
459
 
                }
460
 
            } else
461
 
                limits[lim].rlim_cur = val;
462
 
            if (set && zsetlimit(lim, "limit"))
463
 
                return 1;
464
 
        }
465
 
    }
466
 
    return 0;
467
 
}
468
 
 
469
 
/* limit: set or show resource limits.  The variable hard indicates *
470
 
 * whether `hard' or `soft' resource limits are being set/shown.    */
471
 
 
472
 
/**/
473
 
static int
474
 
bin_limit(char *nam, char **argv, Options ops, UNUSED(int func))
475
 
{
476
 
    char *s;
477
 
    int hard, limnum, lim;
478
 
    rlim_t val;
479
 
    int ret = 0;
480
 
 
481
 
    hard = OPT_ISSET(ops,'h');
482
 
    if (OPT_ISSET(ops,'s') && !*argv)
483
 
        return setlimits(NULL);
484
 
    /* without arguments, display limits */
485
 
    if (!*argv)
486
 
        return showlimits(nam, hard, -1);
487
 
    while ((s = *argv++)) {
488
 
        /* Search for the appropriate resource name.  When a name matches (i.e. *
489
 
         * starts with) the argument, the lim variable changes from -1 to the   *
490
 
         * number of the resource.  If another match is found, lim goes to -2.  */
491
 
        if (idigit(*s))
492
 
        {
493
 
            lim = (int)zstrtol(s, NULL, 10);
494
 
        }
495
 
        else
496
 
            for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++)
497
 
                if (!strncmp(recs[limnum], s, strlen(s))) {
498
 
                    if (lim != -1)
499
 
                        lim = -2;
500
 
                    else
501
 
                        lim = limnum;
502
 
                }
503
 
        /* lim==-1 indicates that no matches were found.       *
504
 
         * lim==-2 indicates that multiple matches were found. */
505
 
        if (lim < 0) {
506
 
            zwarnnam(nam,
507
 
                     (lim == -2) ? "ambiguous resource specification: %s"
508
 
                     : "no such resource: %s", s);
509
 
            return 1;
510
 
        }
511
 
        /* without value for limit, display the current limit */
512
 
        if (!(s = *argv++))
513
 
            return showlimits(nam, hard, lim);
514
 
        if (lim >= ZSH_NLIMITS)
515
 
        {
516
 
            val = zstrtorlimt(s, &s, 10);
517
 
            if (*s)
518
 
            {
519
 
                /* unknown limit, no idea how to scale */
520
 
                zwarnnam(nam, "unknown scaling factor: %s", s);
521
 
                return 1;
522
 
            }
523
 
        }
524
 
        else if (limtype[lim] == ZLIMTYPE_TIME) {
525
 
            /* time-type resource -- may be specified as seconds, or minutes or *
526
 
             * hours with the `m' and `h' modifiers, and `:' may be used to add *
527
 
             * together more than one of these.  It's easier to understand from *
528
 
             * the code:                                                        */
529
 
            val = zstrtorlimt(s, &s, 10);
530
 
            if (*s) {
531
 
                if ((*s == 'h' || *s == 'H') && !s[1])
532
 
                    val *= 3600L;
533
 
                else if ((*s == 'm' || *s == 'M') && !s[1])
534
 
                    val *= 60L;
535
 
                else if (*s == ':')
536
 
                    val = val * 60 + zstrtorlimt(s + 1, &s, 10);
537
 
                else {
538
 
                    zwarnnam(nam, "unknown scaling factor: %s", s);
539
 
                    return 1;
540
 
                }
541
 
            }
542
 
        } else if (limtype[lim] == ZLIMTYPE_NUMBER || limtype[lim] == ZLIMTYPE_UNKNOWN) {
543
 
            /* pure numeric resource -- only a straight decimal number is
544
 
            permitted. */
545
 
            char *t = s;
546
 
            val = zstrtorlimt(t, &s, 10);
547
 
            if (s == t) {
548
 
                zwarnnam(nam, "limit must be a number");
549
 
                return 1;
550
 
            }
551
 
        } else {
552
 
            /* memory-type resource -- `k' and `M' modifiers are permitted,
553
 
            meaning (respectively) 2^10 and 2^20. */
554
 
            val = zstrtorlimt(s, &s, 10);
555
 
            if (!*s || ((*s == 'k' || *s == 'K') && !s[1])) {
556
 
                if (val != RLIM_INFINITY)
557
 
                    val *= 1024L;
558
 
            } else if ((*s == 'M' || *s == 'm') && !s[1])
559
 
                val *= 1024L * 1024;
560
 
            else {
561
 
                zwarnnam(nam, "unknown scaling factor: %s", s);
562
 
                return 1;
563
 
            }
564
 
        }
565
 
        if (do_limit(nam, lim, val, hard, !hard, OPT_ISSET(ops, 's')))
566
 
            ret++;
567
 
    }
568
 
    return ret;
569
 
}
570
 
 
571
 
/**/
572
 
static int
573
 
do_unlimit(char *nam, int lim, int hard, int soft, int set, int euid)
574
 
{
575
 
    /* remove specified limit */
576
 
    if (lim >= ZSH_NLIMITS) {
577
 
        struct rlimit vals;
578
 
        if (getrlimit(lim, &vals) < 0)
579
 
        {
580
 
            zwarnnam(nam, "can't read limit: %e", errno);
581
 
            return 1;
582
 
        }
583
 
        if (hard) {
584
 
            if (euid && vals.rlim_max != RLIM_INFINITY) {
585
 
                zwarnnam(nam, "can't remove hard limits");
586
 
                return 1;
587
 
            } else
588
 
                vals.rlim_max = RLIM_INFINITY;
589
 
        }
590
 
        if (!hard || soft)
591
 
            vals.rlim_cur = vals.rlim_max;
592
 
        if (!set) {
593
 
            zwarnnam(nam,
594
 
                     "warning: unrecognised limit %d, use -s to set", lim);
595
 
            return 1;
596
 
        } else if (setrlimit(lim, &vals) < 0) {
597
 
            zwarnnam(nam, "setrlimit failed: %e", errno);
598
 
            return 1;
599
 
        }
600
 
    } else {
601
 
        if (hard) {
602
 
            if (euid && current_limits[lim].rlim_max != RLIM_INFINITY) {
603
 
                zwarnnam(nam, "can't remove hard limits");
604
 
                return 1;
605
 
            } else
606
 
                limits[lim].rlim_max = RLIM_INFINITY;
607
 
        }
608
 
        if (!hard || soft)
609
 
            limits[lim].rlim_cur = limits[lim].rlim_max;
610
 
        if (set && zsetlimit(lim, nam))
611
 
            return 1;
612
 
    }
613
 
    return 0;
614
 
}
615
 
 
616
 
/* unlimit: remove resource limits.  Much of this code is the same as *
617
 
 * that in bin_limit().                                               */
618
 
 
619
 
/**/
620
 
static int
621
 
bin_unlimit(char *nam, char **argv, Options ops, UNUSED(int func))
622
 
{
623
 
    int hard, limnum, lim;
624
 
    int ret = 0;
625
 
    uid_t euid = geteuid();
626
 
 
627
 
    hard = OPT_ISSET(ops,'h');
628
 
    /* Without arguments, remove all limits. */
629
 
    if (!*argv) {
630
 
        for (limnum = 0; limnum != RLIM_NLIMITS; limnum++) {
631
 
            if (hard) {
632
 
                if (euid && current_limits[limnum].rlim_max != RLIM_INFINITY)
633
 
                    ret++;
634
 
                else
635
 
                    limits[limnum].rlim_max = RLIM_INFINITY;
636
 
            } else
637
 
                limits[limnum].rlim_cur = limits[limnum].rlim_max;
638
 
        }
639
 
        if (OPT_ISSET(ops,'s'))
640
 
            ret += setlimits(nam);
641
 
        if (ret)
642
 
            zwarnnam(nam, "can't remove hard limits");
643
 
    } else {
644
 
        for (; *argv; argv++) {
645
 
            /* Search for the appropriate resource name.  When a name     *
646
 
             * matches (i.e. starts with) the argument, the lim variable  *
647
 
             * changes from -1 to the number of the resource.  If another *
648
 
             * match is found, lim goes to -2.                            */
649
 
            if (idigit(**argv)) {
650
 
                lim = (int)zstrtol(*argv, NULL, 10);
651
 
            } else {
652
 
                for (lim = -1, limnum = 0; limnum < ZSH_NLIMITS; limnum++)
653
 
                    if (!strncmp(recs[limnum], *argv, strlen(*argv))) {
654
 
                        if (lim != -1)
655
 
                            lim = -2;
656
 
                        else
657
 
                            lim = limnum;
658
 
                    }
659
 
            }
660
 
            /* lim==-1 indicates that no matches were found.       *
661
 
             * lim==-2 indicates that multiple matches were found. */
662
 
            if (lim < 0) {
663
 
                zwarnnam(nam,
664
 
                         (lim == -2) ? "ambiguous resource specification: %s"
665
 
                         : "no such resource: %s", *argv);
666
 
                return 1;
667
 
            }
668
 
            else if (do_unlimit(nam, lim, hard, !hard, OPT_ISSET(ops, 's'),
669
 
                                euid))
670
 
                ret++;
671
 
        }
672
 
    }
673
 
    return ret;
674
 
}
675
 
 
676
 
/* ulimit: set or display resource limits */
677
 
 
678
 
/**/
679
 
static int
680
 
bin_ulimit(char *name, char **argv, UNUSED(Options ops), UNUSED(int func))
681
 
{
682
 
    int res, resmask = 0, hard = 0, soft = 0, nres = 0, all = 0, ret = 0;
683
 
    char *options;
684
 
 
685
 
    do {
686
 
        options = *argv;
687
 
        if (options && *options == '-' && !options[1]) {
688
 
            zwarnnam(name, "missing option letter");
689
 
            return 1;
690
 
        }
691
 
        res = -1;
692
 
        if (options && *options == '-') {
693
 
            argv++;
694
 
            while (*++options) {
695
 
                if(*options == Meta)
696
 
                    *++options ^= 32;
697
 
                res = -1;
698
 
                switch (*options) {
699
 
                case 'H':
700
 
                    hard = 1;
701
 
                    continue;
702
 
                case 'S':
703
 
                    soft = 1;
704
 
                    continue;
705
 
                case 'N':
706
 
                    if (options[1]) {
707
 
                        res = (int)zstrtol(options+1, NULL, 10);
708
 
                    } else if (*argv) {
709
 
                        res = (int)zstrtol(*argv++, NULL, 10);
710
 
                    } else {
711
 
                        zwarnnam(name, "number required after -N");
712
 
                        return 1;
713
 
                    }
714
 
                    /*
715
 
                     * fake it so it looks like we just finished an option...
716
 
                     */
717
 
                    while (options[1])
718
 
                        options++;
719
 
                    break;
720
 
                case 'a':
721
 
                    if (resmask) {
722
 
                        zwarnnam(name, "no limits allowed with -a");
723
 
                        return 1;
724
 
                    }
725
 
                    all = 1;
726
 
                    resmask = (1 << RLIM_NLIMITS) - 1;
727
 
                    nres = RLIM_NLIMITS;
728
 
                    continue;
729
 
                case 't':
730
 
                    res = RLIMIT_CPU;
731
 
                    break;
732
 
                case 'f':
733
 
                    res = RLIMIT_FSIZE;
734
 
                    break;
735
 
                case 'd':
736
 
                    res = RLIMIT_DATA;
737
 
                    break;
738
 
                case 's':
739
 
                    res = RLIMIT_STACK;
740
 
                    break;
741
 
                case 'c':
742
 
                    res = RLIMIT_CORE;
743
 
                    break;
744
 
# ifdef HAVE_RLIMIT_RSS
745
 
                case 'm':
746
 
                    res = RLIMIT_RSS;
747
 
                    break;
748
 
# endif /* HAVE_RLIMIT_RSS */
749
 
# ifdef HAVE_RLIMIT_MEMLOCK
750
 
                case 'l':
751
 
                    res = RLIMIT_MEMLOCK;
752
 
                    break;
753
 
# endif /* HAVE_RLIMIT_MEMLOCK */
754
 
# ifdef HAVE_RLIMIT_NOFILE
755
 
                case 'n':
756
 
                    res = RLIMIT_NOFILE;
757
 
                    break;
758
 
# endif /* HAVE_RLIMIT_NOFILE */
759
 
# ifdef HAVE_RLIMIT_NPROC
760
 
                case 'u':
761
 
                    res = RLIMIT_NPROC;
762
 
                    break;
763
 
# endif /* HAVE_RLIMIT_NPROC */
764
 
# if defined(HAVE_RLIMIT_VMEM) || defined(HAVE_RLIMIT_AS)
765
 
                case 'v':
766
 
#  ifdef HAVE_RLIMIT_VMEM
767
 
                    res = RLIMIT_VMEM;
768
 
#  else
769
 
                    res = RLIMIT_AS;
770
 
#  endif
771
 
                    break;
772
 
# endif /* HAVE_RLIMIT_VMEM */
773
 
# ifdef HAVE_RLIMIT_LOCKS
774
 
                case 'x':
775
 
                    res = RLIMIT_LOCKS;
776
 
                    break;
777
 
# endif
778
 
# ifdef HAVE_RLIMIT_SIGPENDING
779
 
                case 'i':
780
 
                    res = RLIMIT_SIGPENDING;
781
 
                    break;
782
 
# endif
783
 
# ifdef HAVE_RLIMIT_MSGQUEUE
784
 
                case 'q':
785
 
                    res = RLIMIT_MSGQUEUE;
786
 
                    break;
787
 
# endif
788
 
# ifdef HAVE_RLIMIT_NICE
789
 
                case 'e':
790
 
                    res = RLIMIT_NICE;
791
 
                    break;
792
 
# endif
793
 
# ifdef HAVE_RLIMIT_RTPRIO
794
 
                case 'r':
795
 
                    res = RLIMIT_RTPRIO;
796
 
                    break;
797
 
# endif
798
 
                default:
799
 
                    /* unrecognised limit */
800
 
                    zwarnnam(name, "bad option: -%c", *options);
801
 
                    return 1;
802
 
                }
803
 
                if (options[1]) {
804
 
                    resmask |= 1 << res;
805
 
                    nres++;
806
 
                }
807
 
                if (all && res != -1) {
808
 
                    zwarnnam(name, "no limits allowed with -a");
809
 
                    return 1;
810
 
                }
811
 
            }
812
 
        }
813
 
        if (!*argv || **argv == '-') {
814
 
            if (res < 0) {
815
 
                if (*argv || nres)
816
 
                    continue;
817
 
                else
818
 
                    res = RLIMIT_FSIZE;
819
 
            }
820
 
            resmask |= 1 << res;
821
 
            nres++;
822
 
            continue;
823
 
        }
824
 
        if (all) {
825
 
            zwarnnam(name, "no arguments allowed after -a");
826
 
            return 1;
827
 
        }
828
 
        if (res < 0)
829
 
            res = RLIMIT_FSIZE;
830
 
        if (strcmp(*argv, "unlimited")) {
831
 
            /* set limit to specified value */
832
 
            rlim_t limit;
833
 
 
834
 
            limit = zstrtorlimt(*argv, NULL, 10);
835
 
            /* scale appropriately */
836
 
            switch (res) {
837
 
            case RLIMIT_FSIZE:
838
 
            case RLIMIT_CORE:
839
 
                limit *= 512;
840
 
                break;
841
 
            case RLIMIT_DATA:
842
 
            case RLIMIT_STACK:
843
 
# ifdef HAVE_RLIMIT_RSS
844
 
            case RLIMIT_RSS:
845
 
# endif /* HAVE_RLIMIT_RSS */
846
 
# ifdef HAVE_RLIMIT_MEMLOCK
847
 
            case RLIMIT_MEMLOCK:
848
 
# endif /* HAVE_RLIMIT_MEMLOCK */
849
 
/* If RLIMIT_VMEM and RLIMIT_RSS are defined and equal, avoid *
850
 
 * duplicate case statement.  Observed on QNX Neutrino 6.1.0. */
851
 
# if defined(HAVE_RLIMIT_VMEM) && !defined(RLIMIT_VMEM_IS_RSS)
852
 
            case RLIMIT_VMEM:
853
 
# endif /* HAVE_RLIMIT_VMEM */
854
 
/* ditto RLIMIT_VMEM and RLIMIT_AS */
855
 
# if defined(HAVE_RLIMIT_AS) && !defined(RLIMIT_VMEM_IS_AS) && !defined(RLIMIT_RSS_IS_AS)
856
 
            case RLIMIT_AS:
857
 
# endif /* HAVE_RLIMIT_AS */
858
 
# ifdef HAVE_RLIMIT_AIO_MEM
859
 
            case RLIMIT_AIO_MEM:
860
 
# endif /* HAVE_RLIMIT_AIO_MEM */
861
 
                limit *= 1024;
862
 
                break;
863
 
            }
864
 
            if (do_limit(name, res, limit, hard, soft, 1))
865
 
                ret++;
866
 
        } else {
867
 
            if (do_unlimit(name, res, hard, soft, 1, geteuid()))
868
 
                ret++;
869
 
        }
870
 
        argv++;
871
 
    } while (*argv);
872
 
    for (res = 0; resmask; res++, resmask >>= 1)
873
 
        if ((resmask & 1) && printulimit(name, res, hard, nres > 1))
874
 
            ret++;
875
 
    return ret;
876
 
}
877
 
 
878
 
#else /* !HAVE_GETRLIMIT || !RLIM_INFINITY */
879
 
 
880
 
# define bin_limit   bin_notavail
881
 
# define bin_ulimit  bin_notavail
882
 
# define bin_unlimit bin_notavail
883
 
 
884
 
#endif /* !HAVE_GETRLIMIT || !RLIM_INFINITY */
885
 
 
886
 
static struct builtin bintab[] = {
887
 
    BUILTIN("limit",   0, bin_limit,   0, -1, 0, "sh", NULL),
888
 
    BUILTIN("ulimit",  0, bin_ulimit,  0, -1, 0, NULL, NULL),
889
 
    BUILTIN("unlimit", 0, bin_unlimit, 0, -1, 0, "hs", NULL),
890
 
};
891
 
 
892
 
static struct features module_features = {
893
 
    bintab, sizeof(bintab)/sizeof(*bintab),
894
 
    NULL, 0,
895
 
    NULL, 0,
896
 
    NULL, 0,
897
 
    0
898
 
};
899
 
 
900
 
/**/
901
 
int
902
 
setup_(UNUSED(Module m))
903
 
{
904
 
    return 0;
905
 
}
906
 
 
907
 
/**/
908
 
int
909
 
features_(Module m, char ***features)
910
 
{
911
 
    *features = featuresarray(m, &module_features);
912
 
    return 0;
913
 
}
914
 
 
915
 
/**/
916
 
int
917
 
enables_(Module m, int **enables)
918
 
{
919
 
    return handlefeatures(m, &module_features, enables);
920
 
}
921
 
 
922
 
/**/
923
 
int
924
 
boot_(Module m)
925
 
{
926
 
    return 0;
927
 
}
928
 
 
929
 
/**/
930
 
int
931
 
cleanup_(Module m)
932
 
{
933
 
    return setfeatureenables(m, &module_features, NULL);
934
 
    return 0;
935
 
}
936
 
 
937
 
/**/
938
 
int
939
 
finish_(UNUSED(Module m))
940
 
{
941
 
    return 0;
942
 
}