1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 2001 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 /*
28 * runat: run a command in attribute directory.
29 *
30 * runat file [command]
31 *
32 * when command is not specified an interactive shell is started
33 * in the attribute directory.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <unistd.h>
39 #include <fcntl.h>
40 #include <libintl.h>
41 #include <errno.h>
42 #include <strings.h>
43
44 static void
usage()45 usage()
46 {
47 (void) fprintf(stderr, gettext("usage: runat filename [command]\n"));
48 }
49
50 int
main(int argc,char * argv[])51 main(int argc, char *argv[])
52 {
53 int fd;
54 int dirfd;
55 int i;
56 int argslen;
57 char *shell;
58 char *args[4];
59 char *cmdargs;
60
61 if (argc < 2) {
62 usage();
63 exit(127);
64 }
65
66 if ((fd = open64(argv[1], O_RDONLY)) == -1) {
67 (void) fprintf(stderr,
68 gettext("runat: cannot open %s: %s\n"), argv[1],
69 strerror(errno));
70 exit(125);
71 }
72
73 if ((dirfd = openat64(fd, ".", O_RDONLY|O_XATTR)) == -1) {
74 (void) fprintf(stderr,
75 gettext("runat: cannot open attribute"
76 " directory for %s: %s\n"), argv[1], strerror(errno));
77 exit(125);
78 }
79
80 (void) close(fd);
81
82 if (fchdir(dirfd) == -1) {
83 (void) fprintf(stderr,
84 gettext("runat: cannot fchdir to attribute"
85 " directory: %s\n"), strerror(errno));
86 exit(125);
87 }
88
89 if (argc < 3) {
90 shell = getenv("SHELL");
91 if (shell == NULL) {
92 (void) fprintf(stderr,
93 gettext(
94 "runat: shell not found, using /bin/sh\n"));
95 shell = "/bin/sh";
96 }
97
98 (void) execl(shell, shell, NULL);
99 (void) fprintf(stderr,
100 gettext("runat: Failed to exec %s: %s\n"), shell,
101 strerror(errno));
102 return (126);
103 }
104
105 /*
106 * Count up the size of all of the args
107 */
108
109 for (i = 2, argslen = 0; i < argc; i++) {
110 argslen += strlen(argv[i]) + 1;
111 }
112
113 cmdargs = calloc(1, argslen);
114 if (cmdargs == NULL) {
115 (void) fprintf(stderr, gettext(
116 "runat: failed to allocate memory for"
117 " command arguments: %s\n"), strerror(errno));
118 exit(126);
119 }
120
121
122 /*
123 * create string with all of the args concatenated together
124 * This is done so that the shell will interpret the args
125 * and do globbing if necessary.
126 */
127 for (i = 2; i < argc; i++) {
128 if (strlcat(cmdargs, argv[i], argslen) >= argslen) {
129 (void) fprintf(stderr, gettext(
130 "runat: arguments won't fit in"
131 " allocated buffer\n"));
132 exit(126);
133 }
134
135 /*
136 * tack on a space if there are more args
137 */
138 if ((i + 1) < argc) {
139 if (strlcat(cmdargs, " ", argslen) >= argslen) {
140 (void) fprintf(stderr, gettext(
141 "runat: arguments won't fit in"
142 " allocated buffer\n"));
143 exit(126);
144 }
145 }
146
147 }
148
149 args[0] = "/bin/sh";
150 args[1] = "-c";
151 args[2] = cmdargs;
152 args[3] = NULL;
153 (void) execvp(args[0], args);
154 (void) fprintf(stderr, gettext("runat: Failed to exec %s: %s\n"),
155 argv[0], strerror(errno));
156 return (126);
157 }
158