From b4f53143b0e05fd3061cdf2e65e17a6a2904090b Mon Sep 17 00:00:00 2001 From: ridiculousfish Date: Fri, 24 Jul 2015 00:50:58 -0700 Subject: Migrate source files into src/ directory This change moves source files into a src/ directory, and puts object files into an obj/ directory. The Makefile and xcode project are updated accordingly. Fixes #1866 --- src/builtin_ulimit.cpp | 512 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 512 insertions(+) create mode 100644 src/builtin_ulimit.cpp (limited to 'src/builtin_ulimit.cpp') diff --git a/src/builtin_ulimit.cpp b/src/builtin_ulimit.cpp new file mode 100644 index 00000000..23524543 --- /dev/null +++ b/src/builtin_ulimit.cpp @@ -0,0 +1,512 @@ +/** \file builtin_ulimit.c Functions defining the ulimit builtin + +Functions used for implementing the ulimit builtin. + +*/ +#include "config.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fallback.h" +#include "util.h" + +#include "builtin.h" +#include "common.h" +#include "wgetopt.h" + + +/** + Struct describing a resource limit +*/ +struct resource_t +{ + /** + Resource id + */ + int resource; + /** + Description of resource + */ + const wchar_t *desc; + /** + Switch used on commandline to specify resource + */ + wchar_t switch_char; + /** + The implicit multiplier used when setting getting values + */ + int multiplier; +} +; + +/** + Array of resource_t structs, describing all known resource types. +*/ +static const struct resource_t resource_arr[] = +{ + { + RLIMIT_CORE, L"Maximum size of core files created", L'c', 1024 + } + , + { + RLIMIT_DATA, L"Maximum size of a process’s data segment", L'd', 1024 + } + , + { + RLIMIT_FSIZE, L"Maximum size of files created by the shell", L'f', 1024 + } + , +#ifdef RLIMIT_MEMLOCK + { + RLIMIT_MEMLOCK, L"Maximum size that may be locked into memory", L'l', 1024 + } + , +#endif +#ifdef RLIMIT_RSS + { + RLIMIT_RSS, L"Maximum resident set size", L'm', 1024 + } + , +#endif + { + RLIMIT_NOFILE, L"Maximum number of open file descriptors", L'n', 1 + } + , + { + RLIMIT_STACK, L"Maximum stack size", L's', 1024 + } + , + { + RLIMIT_CPU, L"Maximum amount of cpu time in seconds", L't', 1 + } + , +#ifdef RLIMIT_NPROC + { + RLIMIT_NPROC, L"Maximum number of processes available to a single user", L'u', 1 + } + , +#endif +#ifdef RLIMIT_AS + { + RLIMIT_AS, L"Maximum amount of virtual memory available to the shell", L'v', 1024 + } + , +#endif + { + 0, 0, 0, 0 + } +} +; + +/** + Get the implicit multiplication factor for the specified resource limit +*/ +static int get_multiplier(int what) +{ + int i; + + for (i=0; resource_arr[i].desc; i++) + { + if (resource_arr[i].resource == what) + { + return resource_arr[i].multiplier; + } + } + return -1; +} + +/** + Return the value for the specified resource limit. This function + does _not_ multiply the limit value by the multiplier constant used + by the commandline ulimit. +*/ +static rlim_t get(int resource, int hard) +{ + struct rlimit ls; + + getrlimit(resource, &ls); + + return hard ? ls.rlim_max:ls.rlim_cur; +} + +/** + Print the value of the specified resource limit +*/ +static void print(int resource, int hard) +{ + rlim_t l = get(resource, hard); + + if (l == RLIM_INFINITY) + stdout_buffer.append(L"unlimited\n"); + else + append_format(stdout_buffer, L"%d\n", l / get_multiplier(resource)); + +} + +/** + Print values of all resource limits +*/ +static void print_all(int hard) +{ + int i; + int w=0; + + for (i=0; resource_arr[i].desc; i++) + { + w=maxi(w, fish_wcswidth(resource_arr[i].desc)); + } + + for (i=0; resource_arr[i].desc; i++) + { + struct rlimit ls; + rlim_t l; + getrlimit(resource_arr[i].resource, &ls); + l = hard ? ls.rlim_max:ls.rlim_cur; + + const wchar_t *unit = ((resource_arr[i].resource==RLIMIT_CPU)?L"(seconds, ":(get_multiplier(resource_arr[i].resource)==1?L"(":L"(kB, ")); + + append_format(stdout_buffer, + L"%-*ls %10ls-%lc) ", + w, + resource_arr[i].desc, + unit, + resource_arr[i].switch_char); + + if (l == RLIM_INFINITY) + { + stdout_buffer.append(L"unlimited\n"); + } + else + { + append_format(stdout_buffer, L"%d\n", l/get_multiplier(resource_arr[i].resource)); + } + } + +} + +/** + Returns the description for the specified resource limit +*/ +static const wchar_t *get_desc(int what) +{ + int i; + + for (i=0; resource_arr[i].desc; i++) + { + if (resource_arr[i].resource == what) + { + return resource_arr[i].desc; + } + } + return L"Not a resource"; +} + +/** + Set the new value of the specified resource limit. This function + does _not_ multiply the limit value by the multiplier constant used + by the commandline ulimit. +*/ +static int set(int resource, int hard, int soft, rlim_t value) +{ + struct rlimit ls; + getrlimit(resource, &ls); + + if (hard) + { + ls.rlim_max = value; + } + + if (soft) + { + ls.rlim_cur = value; + + /* + Do not attempt to set the soft limit higher than the hard limit + */ + if ((value == RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY) || + (value != RLIM_INFINITY && ls.rlim_max != RLIM_INFINITY && value > ls.rlim_max)) + { + ls.rlim_cur = ls.rlim_max; + } + } + + if (setrlimit(resource, &ls)) + { + if (errno == EPERM) + append_format(stderr_buffer, L"ulimit: Permission denied when changing resource of type '%ls'\n", get_desc(resource)); + else + builtin_wperror(L"ulimit"); + return 1; + } + return 0; +} + +/** + The ulimit builtin, used for setting resource limits. Defined in + builtin_ulimit.c. +*/ +static int builtin_ulimit(parser_t &parser, wchar_t ** argv) +{ + int hard=0; + int soft=0; + + int what = RLIMIT_FSIZE; + int report_all = 0; + + int argc = builtin_count_args(argv); + + woptind=0; + + while (1) + { + static const struct woption + long_options[] = + { + { + L"all", no_argument, 0, 'a' + } + , + { + L"hard", no_argument, 0, 'H' + } + , + { + L"soft", no_argument, 0, 'S' + } + , + { + L"core-size", no_argument, 0, 'c' + } + , + { + L"data-size", no_argument, 0, 'd' + } + , + { + L"file-size", no_argument, 0, 'f' + } + , + { + L"lock-size", no_argument, 0, 'l' + } + , + { + L"resident-set-size", no_argument, 0, 'm' + } + , + { + L"file-descriptor-count", no_argument, 0, 'n' + } + , + { + L"stack-size", no_argument, 0, 's' + } + , + { + L"cpu-time", no_argument, 0, 't' + } + , + { + L"process-count", no_argument, 0, 'u' + } + , + { + L"virtual-memory-size", no_argument, 0, 'v' + } + , + { + L"help", no_argument, 0, 'h' + } + , + { + 0, 0, 0, 0 + } + } + ; + + + int opt_index = 0; + + int opt = wgetopt_long(argc, + argv, + L"aHScdflmnstuvh", + long_options, + &opt_index); + if (opt == -1) + break; + + switch (opt) + { + case 0: + if (long_options[opt_index].flag != 0) + break; + append_format(stderr_buffer, + BUILTIN_ERR_UNKNOWN, + argv[0], + long_options[opt_index].name); + builtin_print_help(parser, argv[0], stderr_buffer); + + return 1; + + case L'a': + report_all=1; + break; + + case L'H': + hard=1; + break; + + case L'S': + soft=1; + break; + + case L'c': + what=RLIMIT_CORE; + break; + + case L'd': + what=RLIMIT_DATA; + break; + + case L'f': + what=RLIMIT_FSIZE; + break; +#ifdef RLIMIT_MEMLOCK + case L'l': + what=RLIMIT_MEMLOCK; + break; +#endif + +#ifdef RLIMIT_RSS + case L'm': + what=RLIMIT_RSS; + break; +#endif + + case L'n': + what=RLIMIT_NOFILE; + break; + + case L's': + what=RLIMIT_STACK; + break; + + case L't': + what=RLIMIT_CPU; + break; + +#ifdef RLIMIT_NPROC + case L'u': + what=RLIMIT_NPROC; + break; +#endif + +#ifdef RLIMIT_AS + case L'v': + what=RLIMIT_AS; + break; +#endif + + case L'h': + builtin_print_help(parser, argv[0], stdout_buffer); + return 0; + + case L'?': + builtin_unknown_option(parser, argv[0], argv[woptind-1]); + return 1; + } + } + + if (report_all) + { + if (argc - woptind == 0) + { + print_all(hard); + } + else + { + stderr_buffer.append(argv[0]); + stderr_buffer.append(L": Too many arguments\n"); + builtin_print_help(parser, argv[0], stderr_buffer); + return 1; + } + + return 0; + } + + switch (argc - woptind) + { + case 0: + { + /* + Show current limit value + */ + print(what, hard); + break; + } + + case 1: + { + /* + Change current limit value + */ + rlim_t new_limit; + wchar_t *end; + + /* + Set both hard and soft limits if nothing else was specified + */ + if (!(hard+soft)) + { + hard=soft=1; + } + + if (wcscasecmp(argv[woptind], L"unlimited")==0) + { + new_limit = RLIM_INFINITY; + } + else if (wcscasecmp(argv[woptind], L"hard")==0) + { + new_limit = get(what, 1); + } + else if (wcscasecmp(argv[woptind], L"soft")==0) + { + new_limit = get(what, soft); + } + else + { + errno=0; + new_limit = wcstol(argv[woptind], &end, 10); + if (errno || *end) + { + append_format(stderr_buffer, + L"%ls: Invalid limit '%ls'\n", + argv[0], + argv[woptind]); + builtin_print_help(parser, argv[0], stderr_buffer); + return 1; + } + new_limit *= get_multiplier(what); + } + + return set(what, hard, soft, new_limit); + } + + default: + { + stderr_buffer.append(argv[0]); + stderr_buffer.append(L": Too many arguments\n"); + builtin_print_help(parser, argv[0], stderr_buffer); + return 1; + } + + } + return 0; +} -- cgit v1.2.3