if (fd) fclose(fp);
}
+
+// Returns the number of bytes taken by the environment variables. For use
+// when calculating the maximum bytes of environment+argument data that can
+// be passed to exec for find(1) and xargs(1).
+long environ_bytes()
+{
+ long bytes = sizeof(char *);
+ char **ev;
+
+ for (ev = environ; *ev; ev++)
+ bytes += sizeof(char *) + strlen(*ev) + 1;
+ return bytes;
+}
char *getusername(uid_t uid);
char *getgroupname(gid_t gid);
void do_lines(int fd, void (*call)(char **pline, long len));
+long environ_bytes();
#define HR_SPACE 1 // Space between number and units
#define HR_B 2 // Use "B" for single byte units
if (!*s) break;
save = s;
+ TT.bytes += sizeof(char *);
+
for (;;) {
if (++TT.bytes >= TT.max_bytes && TT.max_bytes) return save;
if (!*s || isspace(*s)) break;
// -0 support
} else {
- TT.bytes += strlen(data)+1;
+ TT.bytes += sizeof(char *)+strlen(data)+1;
if (TT.max_bytes && TT.bytes >= TT.max_bytes) return data;
if (TT.max_entries && TT.entries >= TT.max_entries)
return (char *)1;
int entries, bytes, done = 0, status;
char *data = NULL, **out;
pid_t pid;
+ long posix_max_bytes;
+
+ // POSIX requires that we never hit the ARG_MAX limit, even if we try to
+ // with -s. POSIX also says we have to reserve 2048 bytes "to guarantee
+ // that the invoked utility has room to modify its environment variables
+ // and command line arguments and still be able to invoke another utility",
+ // though obviously that's not really something you can guarantee.
+ posix_max_bytes = sysconf(_SC_ARG_MAX) - environ_bytes() - 2048;
+ if (TT.max_bytes == 0 || TT.max_bytes > posix_max_bytes)
+ TT.max_bytes = posix_max_bytes;
if (!(toys.optflags & FLAG_0)) TT.delim = '\n';