xref: /freebsd/usr.bin/runat/runat.c (revision 511de5b1430ea974b3dc6fcb2af28d2e10b2b25e)
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