10660de81SRick Macklem /*
20660de81SRick Macklem * Copyright (c) 2025 Rick Macklem
30660de81SRick Macklem *
40660de81SRick Macklem * SPDX-License-Identifier: BSD-2-Clause
50660de81SRick Macklem */
60660de81SRick Macklem
70660de81SRick Macklem #include <sys/param.h>
80660de81SRick Macklem #include <sys/wait.h>
90660de81SRick Macklem #include <err.h>
100660de81SRick Macklem #include <fcntl.h>
110660de81SRick Macklem #include <paths.h>
120660de81SRick Macklem #include <signal.h>
130660de81SRick Macklem #include <stdio.h>
140660de81SRick Macklem #include <stdlib.h>
150660de81SRick Macklem #include <string.h>
160660de81SRick Macklem #include <unistd.h>
170660de81SRick Macklem
180660de81SRick Macklem static void
usage(void)190660de81SRick Macklem usage(void)
200660de81SRick Macklem {
210660de81SRick Macklem (void)fprintf(stderr, "usage: runat <file> "
220660de81SRick Macklem "<shell command>\n");
230660de81SRick Macklem exit(1);
240660de81SRick Macklem }
250660de81SRick Macklem
260660de81SRick Macklem int
main(int argc,char * argv[])270660de81SRick Macklem main(int argc, char *argv[])
280660de81SRick Macklem {
290660de81SRick Macklem int i, file_fd, nameddir_fd, outsiz;
300660de81SRick Macklem char *buf;
310660de81SRick Macklem long named_enabled;
320660de81SRick Macklem size_t pos, siz;
330660de81SRick Macklem
340660de81SRick Macklem if (argc <= 2)
350660de81SRick Macklem usage();
360660de81SRick Macklem argv++;
370660de81SRick Macklem argc--;
380660de81SRick Macklem if (argc < 2)
390660de81SRick Macklem usage();
400660de81SRick Macklem
410660de81SRick Macklem named_enabled = pathconf(argv[0], _PC_NAMEDATTR_ENABLED);
420660de81SRick Macklem if (named_enabled <= 0)
430660de81SRick Macklem errx(1, "Named attributes not enabled for %s", argv[0]);
440660de81SRick Macklem
450660de81SRick Macklem /* Generate the command string for "sh". */
460660de81SRick Macklem siz = 0;
470660de81SRick Macklem for (i = 1; i < argc; i++)
480660de81SRick Macklem siz += strlen(argv[i]) + 1;
490660de81SRick Macklem buf = malloc(siz);
500660de81SRick Macklem if (buf == NULL)
510660de81SRick Macklem errx(1, "Cannot malloc");
520660de81SRick Macklem pos = 0;
530660de81SRick Macklem for (i = 1; i < argc; i++) {
540660de81SRick Macklem outsiz = snprintf(&buf[pos], siz, "%s ", argv[i]);
55*511de5b1SRick Macklem if (outsiz <= 0)
56*511de5b1SRick Macklem errx(1, "snprintf failed: returned %d", outsiz);
570660de81SRick Macklem if ((size_t)outsiz > siz)
580660de81SRick Macklem errx(1, "Arguments too large");
590660de81SRick Macklem pos += outsiz;
600660de81SRick Macklem siz -= outsiz;
610660de81SRick Macklem }
620660de81SRick Macklem buf[pos - 1] = '\0';
630660de81SRick Macklem
640660de81SRick Macklem file_fd = open(argv[0], O_RDONLY | O_CLOEXEC, 0);
650660de81SRick Macklem if (file_fd < 0)
660660de81SRick Macklem err(1, "Cannot open %s", argv[0]);
670660de81SRick Macklem nameddir_fd = openat(file_fd, ".", O_RDONLY | O_CLOEXEC | O_NAMEDATTR,
680660de81SRick Macklem 0);
690660de81SRick Macklem if (nameddir_fd < 0)
700660de81SRick Macklem err(1, "Cannot open named attribute directory "
710660de81SRick Macklem "for %s", argv[0]);
720660de81SRick Macklem
730660de81SRick Macklem if (fchdir(nameddir_fd) < 0)
740660de81SRick Macklem err(1, "Cannot fchdir to named attribute dir");
750660de81SRick Macklem
760660de81SRick Macklem execl(_PATH_BSHELL, "sh", "-c", buf, NULL);
770660de81SRick Macklem err(1, "Could not exec %s", _PATH_BSHELL);
780660de81SRick Macklem }
79