source: freewrt/package/nvram/src/shutils.c@ 0ea1f3f

freewrt_1_0 freewrt_2_0
Last change on this file since 0ea1f3f was 475ad56, checked in by Waldemar Brodkorb <wbx@…>, 20 years ago

add OpenWrt trunk revision 3830.

git-svn-id: svn://www.freewrt.org/trunk/freewrt@1 afb5a338-a214-0410-bd46-81f09a774fd1

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/*
2 * Shell-like utility functions
3 *
4 * Copyright 2004, Broadcom Corporation
5 * All Rights Reserved.
6 *
7 * THIS SOFTWARE IS OFFERED "AS IS", AND BROADCOM GRANTS NO WARRANTIES OF ANY
8 * KIND, EXPRESS OR IMPLIED, BY STATUTE, COMMUNICATION OR OTHERWISE. BROADCOM
9 * SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS
10 * FOR A SPECIFIC PURPOSE OR NONINFRINGEMENT CONCERNING THIS SOFTWARE.
11 *
12 * $Id: shutils.c 1540 2005-07-24 19:58:14Z nbd $
13 */
14
15#include <stdio.h>
16#include <stdlib.h>
17#include <stdarg.h>
18#include <errno.h>
19#include <error.h>
20#include <fcntl.h>
21#include <limits.h>
22#include <unistd.h>
23#include <signal.h>
24#include <string.h>
25#include <sys/types.h>
26#include <sys/stat.h>
27#include <sys/wait.h>
28#include <termios.h>
29#include <sys/ioctl.h>
30#include <sys/time.h>
31#include <net/ethernet.h>
32
33#include <shutils.h>
34
35/*
36 * Reads file and returns contents
37 * @param fd file descriptor
38 * @return contents of file or NULL if an error occurred
39 */
40char *
41fd2str(int fd)
42{
43 char *buf = NULL;
44 size_t count = 0, n;
45
46 do {
47 buf = realloc(buf, count + 512);
48 n = read(fd, buf + count, 512);
49 if (n < 0) {
50 free(buf);
51 buf = NULL;
52 }
53 count += n;
54 } while (n == 512);
55
56 close(fd);
57 if (buf)
58 buf[count] = '\0';
59 return buf;
60}
61
62/*
63 * Reads file and returns contents
64 * @param path path to file
65 * @return contents of file or NULL if an error occurred
66 */
67char *
68file2str(const char *path)
69{
70 int fd;
71
72 if ((fd = open(path, O_RDONLY)) == -1) {
73 perror(path);
74 return NULL;
75 }
76
77 return fd2str(fd);
78}
79
80/*
81 * Waits for a file descriptor to change status or unblocked signal
82 * @param fd file descriptor
83 * @param timeout seconds to wait before timing out or 0 for no timeout
84 * @return 1 if descriptor changed status or 0 if timed out or -1 on error
85 */
86int
87waitfor(int fd, int timeout)
88{
89 fd_set rfds;
90 struct timeval tv = { timeout, 0 };
91
92 FD_ZERO(&rfds);
93 FD_SET(fd, &rfds);
94 return select(fd + 1, &rfds, NULL, NULL, (timeout > 0) ? &tv : NULL);
95}
96
97/*
98 * Concatenates NULL-terminated list of arguments into a single
99 * commmand and executes it
100 * @param argv argument list
101 * @param path NULL, ">output", or ">>output"
102 * @param timeout seconds to wait before timing out or 0 for no timeout
103 * @param ppid NULL to wait for child termination or pointer to pid
104 * @return return value of executed command or errno
105 */
106int
107_eval(char *const argv[], char *path, int timeout, int *ppid)
108{
109 pid_t pid;
110 int status;
111 int fd;
112 int flags;
113 int sig;
114 char buf[254]="";
115 int i;
116
117 switch (pid = fork()) {
118 case -1: /* error */
119 perror("fork");
120 return errno;
121 case 0: /* child */
122 /* Reset signal handlers set for parent process */
123 for (sig = 0; sig < (_NSIG-1); sig++)
124 signal(sig, SIG_DFL);
125
126 /* Clean up */
127 ioctl(0, TIOCNOTTY, 0);
128 close(STDIN_FILENO);
129 close(STDOUT_FILENO);
130 close(STDERR_FILENO);
131 setsid();
132
133 /* We want to check the board if exist UART? , add by honor 2003-12-04 */
134 if ((fd = open("/dev/console", O_RDWR)) < 0) {
135 (void) open("/dev/null", O_RDONLY);
136 (void) open("/dev/null", O_WRONLY);
137 (void) open("/dev/null", O_WRONLY);
138 }
139 else{
140 close(fd);
141 (void) open("/dev/console", O_RDONLY);
142 (void) open("/dev/console", O_WRONLY);
143 (void) open("/dev/console", O_WRONLY);
144 }
145
146 /* Redirect stdout to <path> */
147 if (path) {
148 flags = O_WRONLY | O_CREAT;
149 if (!strncmp(path, ">>", 2)) {
150 /* append to <path> */
151 flags |= O_APPEND;
152 path += 2;
153 } else if (!strncmp(path, ">", 1)) {
154 /* overwrite <path> */
155 flags |= O_TRUNC;
156 path += 1;
157 }
158 if ((fd = open(path, flags, 0644)) < 0)
159 perror(path);
160 else {
161 dup2(fd, STDOUT_FILENO);
162 close(fd);
163 }
164 }
165
166 /* execute command */
167 for(i=0 ; argv[i] ; i++)
168 snprintf(buf+strlen(buf), sizeof(buf), "%s ", argv[i]);
169 dprintf("cmd=[%s]\n", buf);
170 setenv("PATH", "/sbin:/bin:/usr/sbin:/usr/bin", 1);
171 alarm(timeout);
172 execvp(argv[0], argv);
173 perror(argv[0]);
174 exit(errno);
175 default: /* parent */
176 if (ppid) {
177 *ppid = pid;
178 return 0;
179 } else {
180 waitpid(pid, &status, 0);
181 if (WIFEXITED(status))
182 return WEXITSTATUS(status);
183 else
184 return status;
185 }
186 }
187}
188
189/*
190 * Concatenates NULL-terminated list of arguments into a single
191 * commmand and executes it
192 * @param argv argument list
193 * @return stdout of executed command or NULL if an error occurred
194 */
195char *
196_backtick(char *const argv[])
197{
198 int filedes[2];
199 pid_t pid;
200 int status;
201 char *buf = NULL;
202
203 /* create pipe */
204 if (pipe(filedes) == -1) {
205 perror(argv[0]);
206 return NULL;
207 }
208
209 switch (pid = fork()) {
210 case -1: /* error */
211 return NULL;
212 case 0: /* child */
213 close(filedes[0]); /* close read end of pipe */
214 dup2(filedes[1], 1); /* redirect stdout to write end of pipe */
215 close(filedes[1]); /* close write end of pipe */
216 execvp(argv[0], argv);
217 exit(errno);
218 break;
219 default: /* parent */
220 close(filedes[1]); /* close write end of pipe */
221 buf = fd2str(filedes[0]);
222 waitpid(pid, &status, 0);
223 break;
224 }
225
226 return buf;
227}
228
229/*
230 * Kills process whose PID is stored in plaintext in pidfile
231 * @param pidfile PID file
232 * @return 0 on success and errno on failure
233 */
234int
235kill_pidfile(char *pidfile)
236{
237 FILE *fp = fopen(pidfile, "r");
238 char buf[256];
239
240 if (fp && fgets(buf, sizeof(buf), fp)) {
241 pid_t pid = strtoul(buf, NULL, 0);
242 fclose(fp);
243 return kill(pid, SIGTERM);
244 } else
245 return errno;
246}
247
248/*
249 * fread() with automatic retry on syscall interrupt
250 * @param ptr location to store to
251 * @param size size of each element of data
252 * @param nmemb number of elements
253 * @param stream file stream
254 * @return number of items successfully read
255 */
256int
257safe_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
258{
259 size_t ret = 0;
260
261 do {
262 clearerr(stream);
263 ret += fread((char *)ptr + (ret * size), size, nmemb - ret, stream);
264 } while (ret < nmemb && ferror(stream) && errno == EINTR);
265
266 return ret;
267}
268
269/*
270 * fwrite() with automatic retry on syscall interrupt
271 * @param ptr location to read from
272 * @param size size of each element of data
273 * @param nmemb number of elements
274 * @param stream file stream
275 * @return number of items successfully written
276 */
277int
278safe_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
279{
280 size_t ret = 0;
281
282 do {
283 clearerr(stream);
284 ret += fwrite((char *)ptr + (ret * size), size, nmemb - ret, stream);
285 } while (ret < nmemb && ferror(stream) && errno == EINTR);
286
287 return ret;
288}
289
290/*
291 * Convert Ethernet address string representation to binary data
292 * @param a string in xx:xx:xx:xx:xx:xx notation
293 * @param e binary data
294 * @return TRUE if conversion was successful and FALSE otherwise
295 */
296int
297ether_atoe(const char *a, unsigned char *e)
298{
299 char *c = (char *) a;
300 int i = 0;
301
302 memset(e, 0, ETHER_ADDR_LEN);
303 for (;;) {
304 e[i++] = (unsigned char) strtoul(c, &c, 16);
305 if (!*c++ || i == ETHER_ADDR_LEN)
306 break;
307 }
308 return (i == ETHER_ADDR_LEN);
309}
310
311/*
312 * Convert Ethernet address binary data to string representation
313 * @param e binary data
314 * @param a string in xx:xx:xx:xx:xx:xx notation
315 * @return a
316 */
317char *
318ether_etoa(const unsigned char *e, char *a)
319{
320 char *c = a;
321 int i;
322
323 for (i = 0; i < ETHER_ADDR_LEN; i++) {
324 if (i)
325 *c++ = ':';
326 c += sprintf(c, "%02X", e[i] & 0xff);
327 }
328 return a;
329}
Note: See TracBrowser for help on using the repository browser.