]> git.pld-linux.org Git - projects/setup.git/blame - postshell.c
add etc/sub[ug]id
[projects/setup.git] / postshell.c
CommitLineData
6363f2ed
ER
1/*
2 * Copyright (c) 2002 Michal Moskal <malekith@pld-linux.org>.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Michal Moskal.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY MICHAL MOSKAL AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33/*
34 * Usage
35 * ~~~~~
36 *
37 * This simple program is aimed to be used as script interpreter in rpm
38 * %post scriptlets and the like. It opens file passed as first argument
39 * and executes commands found there. Only linear execution is supported.
40 * For example, in glibc.spec:
41 *
42 * %post -p /sbin/postshell
43 * ldconfig
44 * -telinit q
45 *
46 * (full patch like /sbin/ldconfig or -/sbin/tellinit will also work).
47 *
48 * If command starts with - its exit status is ignored. Otherwise last
49 * non-zero exit status is returned.
50 *
51 * There are no builtin commands (yet :).
52 *
53 * Following commands *will* work as expected (as in Bourne shell):
54 *
55 * /bin/echo "Foo bar baz"
56 * insmod foobar options="foo bar 'qux'"
57 * false
58 *
59 * Following *won't*:
60 *
61 * exit 1
62 * echo foo || echo baz
63 * set -x
64 *
65 * Patches and bugreports are welcome, direct them to Michal Moskal
66 * <malekith@pld-linux.org>.
67 */
68
69#define _GNU_SOURCE
70#include <sys/types.h>
71#include <sys/wait.h>
72#include <unistd.h>
73#include <stdio.h>
74#include <stdlib.h>
75#include <string.h>
0d0b60a4 76#include <ctype.h>
3a827ec1
ER
77#include <fcntl.h>
78#include <sys/mman.h>
145e6ea9 79#include <sys/stat.h>
6363f2ed
ER
80
81#define MAX_LINE 1024
82#define MAX_ARGS 32
83#define SEARCH_PATH { "/sbin/", "/bin/", "/usr/sbin/", "/usr/bin/", NULL }
84
85int exit_status;
86int ignore_status;
87
88void do_execve(char **argv)
89{
90 char *path[] = SEARCH_PATH;
91 char file[MAX_LINE + 100];
92 int i;
93
94 if (**argv == '.' || **argv == '/')
95 execve(argv[0], argv, environ);
96 else
97 for (i = 0; path[i]; i++) {
98 strcpy(file, path[i]);
99 strcat(file, argv[0]);
100 execve(file, argv, environ);
101 }
102}
103
104int exec_and_wait(char **argv)
105{
106 pid_t pid;
107
108 pid = fork();
109
110 if (pid == -1) {
111 perror("fork");
112 return -1;
113 } else if (pid == 0) {
114 /* child. */
115 do_execve(argv);
116 if (!ignore_status)
117 perror(argv[0]);
118 exit(127);
119 } else {
120 int status, err;
121
122 err = waitpid(pid, &status, 0);
123 if (err < 0) {
124 perror("waitpid");
125 return -1;
126 } else
127 return WEXITSTATUS(status);
128 }
129}
130
131void split_argv(char **argv, char *s)
132{
133 char *dst;
134 int argc, delim;
135
136 for (argc = 0; argc < MAX_ARGS; argc++) {
137 while (*s == ' ' || *s == '\t')
138 s++;
139
140 if (*s == 0)
141 break;
142
143 argv[argc] = s;
144 dst = s;
145
146 while (*s && *s != ' ' && *s != '\t') {
147 if (*s == '\'' || *s == '"') {
148 delim = *s++;
149 while (*s && *s != delim)
150 *dst++ = *s++;
151 if (*s)
152 s++;
153 } else {
154 *dst++ = *s++;
155 }
156 }
157
158 if (*dst) {
159 if (s == dst)
160 s++;
161 *dst++ = 0;
162 }
163 }
164
165 argv[argc] = NULL;
166}
167
168void exec_line(char *s)
169{
0d0b60a4 170 char *argv[MAX_ARGS + 1], *c;
6363f2ed
ER
171 int ret;
172
0d0b60a4
AM
173
174 /* skip blank characters */
175 for (c = s; c && isblank(*c); c++)
176 ;
177 /* skip commented lines */
178 if (*c == '#')
179 return;
180
6363f2ed
ER
181 split_argv(argv, s);
182
183 ignore_status = 0;
184
185 if (**argv == '-') {
186 ignore_status++;
187 (*argv)++;
188 }
189
190 ret = exec_and_wait(argv);
191
192 if (ret && !ignore_status)
193 exit_status = ret;
194}
195
3a827ec1 196void exec_file(int fd)
6363f2ed
ER
197{
198 char line[MAX_LINE];
3a827ec1
ER
199 struct stat sbuf;
200 char *p, *s, *a;
6363f2ed 201
3a827ec1
ER
202 if (fstat(fd, &sbuf) < 0) {
203 perror("fstat()");
204 exit(1);
205 }
206
207 if ((p = mmap(0, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) < 0) {
208 perror("mmap()");
209 exit(1);
210 }
211
212 for (a = s = p; s < p + sbuf.st_size; s++) {
213 if (*s == '\n') {
214 memcpy(line, a, s - a);
215 line[s - a] = '\0';
216 exec_line(line);
217 a = ++s;
218 }
219 }
220
221 // last line was not terminated.
222 if (s == p + sbuf.st_size) {
223 memcpy(line, a, s - a);
224 line[s - a] = '\0';
6363f2ed
ER
225 exec_line(line);
226 }
3a827ec1
ER
227
228 if (munmap(p, sbuf.st_size) < 0) {
229 perror("munmap()");
230 exit(1);
231 }
6363f2ed
ER
232}
233
db127c35
AM
234ssize_t error(char *msg) {
235 return write(2, msg, strlen(msg));
236}
237
6363f2ed
ER
238int main(int argc, char **argv)
239{
3a827ec1 240 int fd;
6363f2ed
ER
241
242 if (argc < 2) {
f067f00c
ER
243 error("USAGE: ");
244 error(argv[0]);
245 error(" filename\n");
6363f2ed
ER
246 exit(1);
247 }
248
3a827ec1 249 fd = open(argv[1], O_RDONLY);
6363f2ed 250
3a827ec1 251 if (fd == -1) {
6363f2ed
ER
252 perror(argv[1]);
253 exit(1);
254 }
255
3a827ec1
ER
256 exec_file(fd);
257 close(fd);
6363f2ed
ER
258 exit(exit_status);
259}
This page took 0.232677 seconds and 4 git commands to generate.