blob: 432fd60798cc72bdf24f4eed8140c11e73456bac [file] [log] [blame]
Eric Andersenaad1a882001-03-16 22:47:14 +00001/* vi: set sw=4 ts=4: */
2/*
3 * Utility routines.
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersenaad1a882001-03-16 22:47:14 +00006 *
Rob Landley4e9deec2006-02-20 02:44:30 +00007 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
Eric Andersenaad1a882001-03-16 22:47:14 +00008 */
9
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000010#include <sys/types.h>
11#include <sys/stat.h>
Rob Landleyc7ddefc2006-06-14 01:24:33 +000012#include <sys/wait.h>
Eric Andersenaad1a882001-03-16 22:47:14 +000013#include <stdio.h>
14#include <string.h>
15#include <stdlib.h>
16#include <unistd.h>
Glenn L McGrath7ca04f32002-09-25 02:47:48 +000017#include <fcntl.h>
Rob Landley552b56d2006-05-04 21:22:27 +000018#include "busybox.h"
Eric Andersenaad1a882001-03-16 22:47:14 +000019
20#ifndef DMALLOC
Manuel Novoa III cad53642003-03-19 09:13:01 +000021#ifdef L_xmalloc
Rob Landleydfba7412006-03-06 20:47:33 +000022void *xmalloc(size_t size)
Eric Andersenaad1a882001-03-16 22:47:14 +000023{
24 void *ptr = malloc(size);
Matt Kraaia99b1942002-02-26 15:28:22 +000025 if (ptr == NULL && size != 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +000026 bb_error_msg_and_die(bb_msg_memory_exhausted);
Eric Andersenaad1a882001-03-16 22:47:14 +000027 return ptr;
28}
Manuel Novoa III cad53642003-03-19 09:13:01 +000029#endif
Eric Andersenaad1a882001-03-16 22:47:14 +000030
Manuel Novoa III cad53642003-03-19 09:13:01 +000031#ifdef L_xrealloc
Rob Landleydfba7412006-03-06 20:47:33 +000032void *xrealloc(void *ptr, size_t size)
Eric Andersenaad1a882001-03-16 22:47:14 +000033{
Matt Kraaia99b1942002-02-26 15:28:22 +000034 ptr = realloc(ptr, size);
35 if (ptr == NULL && size != 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +000036 bb_error_msg_and_die(bb_msg_memory_exhausted);
Eric Andersenaad1a882001-03-16 22:47:14 +000037 return ptr;
38}
Manuel Novoa III cad53642003-03-19 09:13:01 +000039#endif
Eric Andersenaad1a882001-03-16 22:47:14 +000040
Rob Landley80b8ff02006-05-19 20:36:49 +000041#ifdef L_xzalloc
42void *xzalloc(size_t size)
43{
44 void *ptr = xmalloc(size);
45 memset(ptr, 0, size);
46 return ptr;
47}
48#endif
49
Manuel Novoa III cad53642003-03-19 09:13:01 +000050#ifdef L_xcalloc
Rob Landleydfba7412006-03-06 20:47:33 +000051void *xcalloc(size_t nmemb, size_t size)
Eric Andersenaad1a882001-03-16 22:47:14 +000052{
53 void *ptr = calloc(nmemb, size);
Matt Kraaia99b1942002-02-26 15:28:22 +000054 if (ptr == NULL && nmemb != 0 && size != 0)
Manuel Novoa III cad53642003-03-19 09:13:01 +000055 bb_error_msg_and_die(bb_msg_memory_exhausted);
Eric Andersenaad1a882001-03-16 22:47:14 +000056 return ptr;
57}
Manuel Novoa III cad53642003-03-19 09:13:01 +000058#endif
Eric Andersen9f894f42003-07-05 22:15:43 +000059#endif /* DMALLOC */
Eric Andersenaad1a882001-03-16 22:47:14 +000060
Manuel Novoa III cad53642003-03-19 09:13:01 +000061#ifdef L_xstrdup
Rob Landley31642d72006-03-14 21:45:38 +000062char * bb_xstrdup (const char *s)
63{
Eric Andersenaad1a882001-03-16 22:47:14 +000064 char *t;
65
66 if (s == NULL)
67 return NULL;
68
69 t = strdup (s);
70
71 if (t == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +000072 bb_error_msg_and_die(bb_msg_memory_exhausted);
Eric Andersenaad1a882001-03-16 22:47:14 +000073
74 return t;
75}
76#endif
77
Manuel Novoa III cad53642003-03-19 09:13:01 +000078#ifdef L_xstrndup
Rob Landley31642d72006-03-14 21:45:38 +000079char * bb_xstrndup (const char *s, int n)
80{
Eric Andersenaad1a882001-03-16 22:47:14 +000081 char *t;
82
83 if (s == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +000084 bb_error_msg_and_die("bb_xstrndup bug");
Eric Andersenaad1a882001-03-16 22:47:14 +000085
86 t = xmalloc(++n);
Eric Andersenc7bda1c2004-03-15 08:29:22 +000087
Eric Andersenaad1a882001-03-16 22:47:14 +000088 return safe_strncpy(t,s,n);
89}
Manuel Novoa III cad53642003-03-19 09:13:01 +000090#endif
Eric Andersenaad1a882001-03-16 22:47:14 +000091
Manuel Novoa III cad53642003-03-19 09:13:01 +000092#ifdef L_xfopen
93FILE *bb_xfopen(const char *path, const char *mode)
Eric Andersenaad1a882001-03-16 22:47:14 +000094{
95 FILE *fp;
96 if ((fp = fopen(path, mode)) == NULL)
Manuel Novoa III cad53642003-03-19 09:13:01 +000097 bb_perror_msg_and_die("%s", path);
Eric Andersenaad1a882001-03-16 22:47:14 +000098 return fp;
99}
Manuel Novoa III cad53642003-03-19 09:13:01 +0000100#endif
Eric Andersenaad1a882001-03-16 22:47:14 +0000101
Manuel Novoa III cad53642003-03-19 09:13:01 +0000102#ifdef L_xopen
Rob Landleydfba7412006-03-06 20:47:33 +0000103int bb_xopen(const char *pathname, int flags)
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000104{
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +0000105 return bb_xopen3(pathname, flags, 0777);
106}
107#endif
108
109#ifdef L_xopen3
110int bb_xopen3(const char *pathname, int flags, int mode)
111{
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000112 int ret;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000113
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +0000114 ret = open(pathname, flags, mode);
115 if (ret < 0) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000116 bb_perror_msg_and_die("%s", pathname);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000117 }
118 return ret;
119}
Manuel Novoa III cad53642003-03-19 09:13:01 +0000120#endif
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000121
Manuel Novoa III cad53642003-03-19 09:13:01 +0000122#ifdef L_xread
Rob Landleydfba7412006-03-06 20:47:33 +0000123ssize_t bb_xread(int fd, void *buf, size_t count)
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000124{
125 ssize_t size;
126
127 size = read(fd, buf, count);
Bernhard Reutner-Fischerc2cb0f32006-04-13 12:45:04 +0000128 if (size < 0) {
"Vladimir N. Oleynik"4eb2fd62005-11-25 11:36:36 +0000129 bb_perror_msg_and_die(bb_msg_read_error);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000130 }
131 return(size);
132}
Manuel Novoa III cad53642003-03-19 09:13:01 +0000133#endif
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000134
Manuel Novoa III cad53642003-03-19 09:13:01 +0000135#ifdef L_xread_all
Rob Landleydfba7412006-03-06 20:47:33 +0000136void bb_xread_all(int fd, void *buf, size_t count)
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000137{
138 ssize_t size;
139
Manuel Novoa III cad53642003-03-19 09:13:01 +0000140 while (count) {
141 if ((size = bb_xread(fd, buf, count)) == 0) { /* EOF */
142 bb_error_msg_and_die("Short read");
143 }
144 count -= size;
Manuel Novoa III 948d4902004-03-08 05:44:30 +0000145 buf = ((char *) buf) + size;
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000146 }
147 return;
148}
Manuel Novoa III cad53642003-03-19 09:13:01 +0000149#endif
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000150
Manuel Novoa III cad53642003-03-19 09:13:01 +0000151#ifdef L_xread_char
Rob Landleydfba7412006-03-06 20:47:33 +0000152unsigned char bb_xread_char(int fd)
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000153{
154 char tmp;
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000155
Manuel Novoa III cad53642003-03-19 09:13:01 +0000156 bb_xread_all(fd, &tmp, 1);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000157
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000158 return(tmp);
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000159}
Manuel Novoa III cad53642003-03-19 09:13:01 +0000160#endif
Glenn L McGrath7ca04f32002-09-25 02:47:48 +0000161
Manuel Novoa III cad53642003-03-19 09:13:01 +0000162#ifdef L_xferror
Rob Landleydfba7412006-03-06 20:47:33 +0000163void bb_xferror(FILE *fp, const char *fn)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000164{
165 if (ferror(fp)) {
166 bb_error_msg_and_die("%s", fn);
167 }
168}
169#endif
170
171#ifdef L_xferror_stdout
Rob Landleydfba7412006-03-06 20:47:33 +0000172void bb_xferror_stdout(void)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000173{
174 bb_xferror(stdout, bb_msg_standard_output);
175}
176#endif
177
178#ifdef L_xfflush_stdout
Rob Landleydfba7412006-03-06 20:47:33 +0000179void bb_xfflush_stdout(void)
Manuel Novoa III cad53642003-03-19 09:13:01 +0000180{
181 if (fflush(stdout)) {
182 bb_perror_msg_and_die(bb_msg_standard_output);
183 }
184}
185#endif
Rob Landley399d2b52006-05-25 23:02:40 +0000186
187#ifdef L_spawn
188// This does a fork/exec in one call, using vfork().
189pid_t bb_spawn(char **argv)
190{
191 static int failed;
192 pid_t pid;
Rob Landleyc7ddefc2006-06-14 01:24:33 +0000193 void *app = find_applet_by_name(argv[0]);
Rob Landley399d2b52006-05-25 23:02:40 +0000194
195 // Be nice to nommu machines.
196 failed = 0;
197 pid = vfork();
198 if (pid < 0) return pid;
199 if (!pid) {
Rob Landleyc7ddefc2006-06-14 01:24:33 +0000200 execvp(app ? CONFIG_BUSYBOX_EXEC_PATH : *argv, argv);
Rob Landley399d2b52006-05-25 23:02:40 +0000201
202 // We're sharing a stack with blocked parent, let parent know we failed
203 // and then exit to unblock parent (but don't run atexit() stuff, which
204 // would screw up parent.)
205
206 failed = -1;
207 _exit(0);
208 }
209 return failed ? failed : pid;
210}
211#endif
212
213#ifdef L_xspawn
214pid_t bb_xspawn(char **argv)
215{
216 pid_t pid = bb_spawn(argv);
217 if (pid < 0) bb_perror_msg_and_die("%s", *argv);
218 return pid;
219}
220#endif
Rob Landleyc7ddefc2006-06-14 01:24:33 +0000221
222#ifdef L_wait4
223int wait4pid(int pid)
224{
225 int status;
226
227 if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;
228 if (WIFEXITED(status)) return WEXITSTATUS(status);
229 if (WIFSIGNALED(status)) return WTERMSIG(status);
230 return 0;
231}
232#endif