+static vc_limit_t
+readValue(int fd, char const *filename)
+{
+ char buf[128];
+ size_t len = Eread(fd, buf, sizeof(buf)-1);
+ vc_limit_t res;
+
+ buf[len] = '\0';
+
+ if (!vc_parseLimit(buf, &res)) {
+ WRITE_MSG(2, "Invalid limit in '");
+ WRITE_STR(2, filename);
+ WRITE_STR(2, "'\n");
+ exit(wrapper_exit_code);
+ }
+
+ return res;
+}
+
+static bool
+readFile(char const *file, char *base, char const *suffix,
+ vc_limit_t *limit)
+{
+ int fd;
+
+ strcpy(base, suffix);
+ fd = open(file, O_RDONLY);
+ if (fd!=-1) {
+ *limit = readValue(fd, file);
+ Eclose(fd);
+ }
+
+ return fd!=-1;
+}
+
+static void
+readFromDir(struct vc_rlimit limits[32], uint_least32_t *mask,
+ char const *pathname, bool missing_ok)
+{
+ struct stat st;
+ size_t i;
+ size_t l_pathname = strlen(pathname);
+ char buf[l_pathname + sizeof("/memlock.hard") + 32];
+
+ if (stat(pathname, &st)==-1) {
+ if (errno==ENOENT && missing_ok) return;
+ PERROR_Q("vlimit: fstat", pathname);
+ exit(wrapper_exit_code);
+ }
+
+ memcpy(buf, pathname, l_pathname);
+ if (l_pathname>0 && pathname[l_pathname-1]!='/')
+ buf[l_pathname++] = '/';
+
+ for (i=0; i<DIM_OF(LIMIT_STR); ++i) {
+ size_t l_res;
+ char * ptr = buf+l_pathname;
+
+ // ignore unimplemented limits
+ if (LIMIT_STR[i]==0) continue;
+
+ // ignore limits set on cli already
+ if (*mask & (1<<i)) continue;
+
+ l_res = strlen(LIMIT_STR[i]);
+ memcpy(ptr, LIMIT_STR[i], l_res+1);
+ while (*ptr) {
+ *ptr = tolower(*ptr);
+ ++ptr;
+ }
+
+ if (readFile(buf, ptr, "", &limits[i].min)) {
+ limits[i].soft = limits[i].hard = limits[i].min;
+ *mask |= (1<<i);
+ }
+
+ if (readFile(buf, ptr, ".min", &limits[i].min))
+ *mask |= (1<<i);
+
+ if (readFile(buf, ptr, ".soft", &limits[i].soft))
+ *mask |= (1<<i);
+
+ if (readFile(buf, ptr, ".hard", &limits[i].hard))
+ *mask |= (1<<i);
+ }
+}
+