]> git.pld-linux.org Git - packages/setup.git/blame - postshell.c
- avoid using fprintf(). saved 5k with diet
[packages/setup.git] / postshell.c
CommitLineData
db72565d
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>
76
77#define MAX_LINE 1024
78#define MAX_ARGS 32
79#define SEARCH_PATH { "/sbin/", "/bin/", "/usr/sbin/", "/usr/bin/", NULL }
80
81int exit_status;
82int ignore_status;
83
84void do_execve(char **argv)
85{
86 char *path[] = SEARCH_PATH;
87 char file[MAX_LINE + 100];
88 int i;
89
90 if (**argv == '.' || **argv == '/')
91 execve(argv[0], argv, environ);
92 else
93 for (i = 0; path[i]; i++) {
94 strcpy(file, path[i]);
95 strcat(file, argv[0]);
96 execve(file, argv, environ);
97 }
98}
99
100int exec_and_wait(char **argv)
101{
102 pid_t pid;
103
104 pid = fork();
105
106 if (pid == -1) {
107 perror("fork");
108 return -1;
109 } else if (pid == 0) {
110 /* child. */
111 do_execve(argv);
112 if (!ignore_status)
113 perror(argv[0]);
114 exit(127);
115 } else {
116 int status, err;
117
118 err = waitpid(pid, &status, 0);
119 if (err < 0) {
120 perror("waitpid");
121 return -1;
122 } else
123 return WEXITSTATUS(status);
124 }
125}
126
127void split_argv(char **argv, char *s)
128{
129 char *dst;
130 int argc, delim;
131
132 for (argc = 0; argc < MAX_ARGS; argc++) {
133 while (*s == ' ' || *s == '\t')
134 s++;
135
136 if (*s == 0)
137 break;
138
139 argv[argc] = s;
140 dst = s;
141
142 while (*s && *s != ' ' && *s != '\t') {
143 if (*s == '\'' || *s == '"') {
144 delim = *s++;
145 while (*s && *s != delim)
146 *dst++ = *s++;
147 if (*s)
148 s++;
149 } else {
150 *dst++ = *s++;
151 }
152 }
153
154 if (*dst) {
155 if (s == dst)
156 s++;
157 *dst++ = 0;
158 }
159 }
160
161 argv[argc] = NULL;
162}
163
164void exec_line(char *s)
165{
166 char *argv[MAX_ARGS + 1];
167 int ret;
168
169 split_argv(argv, s);
170
171 ignore_status = 0;
172
173 if (**argv == '-') {
174 ignore_status++;
175 (*argv)++;
176 }
177
178 ret = exec_and_wait(argv);
179
180 if (ret && !ignore_status)
181 exit_status = ret;
182}
183
184void exec_file(FILE *f)
185{
186 char line[MAX_LINE];
187
188 while (fgets(line, sizeof(line), f)) {
189 /* chomp it */
190 if (line[strlen(line) - 1] == '\n')
191 line[strlen(line) - 1] = 0;
192 /* and exec. */
193 exec_line(line);
194 }
195}
196
5ba3274c 197#define error(msg) write(2, msg, strlen(msg))
db72565d
ER
198int main(int argc, char **argv)
199{
200 FILE *f;
201
202 if (argc < 2) {
5ba3274c
ER
203 error("USAGE: ");
204 error(argv[0]);
205 error(" filename\n");
db72565d
ER
206 exit(1);
207 }
208
209 f = fopen(argv[1], "r");
210
211 if (f == NULL) {
212 perror(argv[1]);
213 exit(1);
214 }
215
216 exec_file(f);
217 fclose(f);
218 exit(exit_status);
219}
This page took 0.109929 seconds and 4 git commands to generate.