admins.html: simplify Libera.Chat URL
[girocco.git] / src / ulimit512.c
blob05c3e6e1204b0ad0e00ae00f3866e8bc8ffb5c7f
1 /*
3 ulimit512.c - provide ulimit -f with 512-byte units on the command line
4 Copyright (C) 2018,2020 Kyle J. McKay. All rights reserved.
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License
8 as published by the Free Software Foundation; either version 2
9 of the License, or (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 #define VERSION \
23 "ulimit512 version 1.0.0\n" \
24 "Copyright (C) 2018,2020 Kyle J. McKay <mackyle at gmail dot com>\n" \
25 "License GPLv2+: GNU GPL version 2 or later.\n" \
26 "<http://gnu.org/licenses/gpl2.html>\n" \
27 "This is free software: you are free to change and redistribute it.\n" \
28 "There is NO WARRANTY, to the extent permitted by law.\n"
30 #define USAGE \
31 "Usage: ulimit512 [option...] [<command> [<arg>...]]\n" \
32 " --help/-h show this help\n" \
33 " --version/-V show version/license info\n" \
34 " -f <blks> set UL_SETFSIZE to <blks> (dec/oct/hex # of 512-byte units)\n" \
35 " -i ignore UL_SETFSIZE error if UL_GETFSIZE is <= <blks> value\n" \
36 " -- terminate options, next arg is command even if it starts with -\n" \
37 " <command> if omitted do nothing other than attempt to set ulimit fsize\n" \
38 " <arg>... zero or more optional args to pass to <command>\n" \
39 "First sets ulimit UL_SETFSIZE value if any -f option given then uses execvp to\n" \
40 "run the <command> with any given <arg> values. A failure of UL_SETFSIZE or\n" \
41 "execvp will always result in an error. Note that the value given for -f ALWAYS\n" \
42 "specifies the limit in number of 512-byte units as required by POSIX and that\n" \
43 "the maximum value is the largest positive value that fits in a `long` type.\n" \
44 "Any -f values starting with `0x` are taken to be hexadecimal, starting with `0`\n" \
45 "means octal otherwise the value is decimal. It may NOT be negative.\n" \
46 "Note that using a <blks> value of 0 means zero bytes and is in no way special.\n"
48 #include <stddef.h>
49 #include <stdio.h>
50 #include <stdlib.h>
51 #include <errno.h>
52 #include <string.h>
53 #include <ulimit.h>
54 #include <unistd.h>
56 int main(int argc, char *argv[])
59 int arg = 1;
60 long fsize = -1;
61 int ignore = 0;
63 while (arg < argc && *argv[arg] == '-') {
64 if (!strcmp(argv[arg], "--help") || !strcmp(argv[arg], "-h")) {
65 printf("%s", USAGE);
66 return 0;
68 if (!strcmp(argv[arg], "--version") || !strcmp(argv[arg], "-V")) {
69 printf("%s", VERSION);
70 return 0;
72 if (!strcmp(argv[arg], "-i")) {
73 ignore = 1;
74 ++arg;
75 continue;
77 if (!strcmp(argv[arg], "-f")) {
78 char *end;
80 if (++arg >= argc || !*argv[arg]) {
81 fprintf(stderr, "ulimit512: missing -f value\n");
82 return 1;
84 fsize = strtol(argv[arg], &end, 0);
85 if (*end) {
86 fprintf(stderr, "ulimit512: invalid number: %s\n",
87 argv[arg]);
88 return 2;
90 if (fsize < 0) {
91 fprintf(stderr, "ulimit512: invalid limit %ld "
92 "is < 0\n", fsize);
93 return 2;
95 ++arg;
96 continue;
98 if (!strcmp(argv[arg], "--")) {
99 ++arg;
100 break;
102 fprintf(stderr, "ulimit512: invalid option: %s (see ulimit512 -h)\n",
103 argv[arg]);
104 return 1;
106 if (fsize >= 0) {
107 long result;
109 errno = 0;
110 result = ulimit(UL_SETFSIZE, fsize);
111 if (result == -1 && errno != 0) {
112 int olderr = errno;
113 if (ignore) {
114 result = 0;
115 result = ulimit(UL_GETFSIZE);
116 if (result < 0 || result > fsize)
117 ignore = 0;
119 if (!ignore) {
120 fprintf(stderr, "ulimit512: error: "
121 "UL_SETFSIZE %ld failed: %s\n", fsize,
122 strerror(olderr));
123 return 1;
128 if (arg < argc) {
129 int i, cnt = argc - arg;
130 char **cmd = (char **)malloc((cnt + 1) * sizeof(char *));
132 if (!cmd) {
133 fprintf(stderr, "ulimit512: out of memory\n");
134 return 1;
136 for (i = 0; i < cnt; ++i) {
137 cmd[i] = argv[arg + i];
139 cmd[i] = NULL;
140 if (execvp(cmd[0], cmd) == -1) {
141 fprintf(stderr, "ulimit512: error: execvp failed: %s\n",
142 strerror(errno));
143 return 1;
145 /* It's an error if execvp returns even if it's not -1 */
146 return 1;
149 /* No error if nothing to do or just UL_SETFSIZE and that succeeded */
150 return 0;