Rich Felker suggested removing dprintf() from watch, and one thing led to
[oweals/busybox.git] / libbb / xfuncs.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Utility routines.
4  *
5  * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
6  *
7  * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
8  */
9
10 #include <sys/types.h>
11 #include <sys/stat.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include <unistd.h>
16 #include <fcntl.h>
17 #include "busybox.h"
18
19 #ifndef DMALLOC
20 #ifdef L_xmalloc
21 void *xmalloc(size_t size)
22 {
23         void *ptr = malloc(size);
24         if (ptr == NULL && size != 0)
25                 bb_error_msg_and_die(bb_msg_memory_exhausted);
26         return ptr;
27 }
28 #endif
29
30 #ifdef L_xrealloc
31 void *xrealloc(void *ptr, size_t size)
32 {
33         ptr = realloc(ptr, size);
34         if (ptr == NULL && size != 0)
35                 bb_error_msg_and_die(bb_msg_memory_exhausted);
36         return ptr;
37 }
38 #endif
39
40 #ifdef L_xzalloc
41 void *xzalloc(size_t size)
42 {
43         void *ptr = xmalloc(size);
44         memset(ptr, 0, size);
45         return ptr;
46 }
47 #endif
48
49 #ifdef L_xcalloc
50 void *xcalloc(size_t nmemb, size_t size)
51 {
52         void *ptr = calloc(nmemb, size);
53         if (ptr == NULL && nmemb != 0 && size != 0)
54                 bb_error_msg_and_die(bb_msg_memory_exhausted);
55         return ptr;
56 }
57 #endif
58 #endif /* DMALLOC */
59
60 #ifdef L_xstrdup
61 char * bb_xstrdup (const char *s)
62 {
63         char *t;
64
65         if (s == NULL)
66                 return NULL;
67
68         t = strdup (s);
69
70         if (t == NULL)
71                 bb_error_msg_and_die(bb_msg_memory_exhausted);
72
73         return t;
74 }
75 #endif
76
77 #ifdef L_xstrndup
78 char * bb_xstrndup (const char *s, int n)
79 {
80         char *t;
81
82         if (s == NULL)
83                 bb_error_msg_and_die("bb_xstrndup bug");
84
85         t = xmalloc(++n);
86
87         return safe_strncpy(t,s,n);
88 }
89 #endif
90
91 #ifdef L_xfopen
92 FILE *bb_xfopen(const char *path, const char *mode)
93 {
94         FILE *fp;
95         if ((fp = fopen(path, mode)) == NULL)
96                 bb_perror_msg_and_die("%s", path);
97         return fp;
98 }
99 #endif
100
101 #ifdef L_xopen
102 int bb_xopen(const char *pathname, int flags)
103 {
104         return bb_xopen3(pathname, flags, 0777);
105 }
106 #endif
107
108 #ifdef L_xopen3
109 int bb_xopen3(const char *pathname, int flags, int mode)
110 {
111         int ret;
112
113         ret = open(pathname, flags, mode);
114         if (ret < 0) {
115                 bb_perror_msg_and_die("%s", pathname);
116         }
117         return ret;
118 }
119 #endif
120
121 #ifdef L_xread
122 ssize_t bb_xread(int fd, void *buf, size_t count)
123 {
124         ssize_t size;
125
126         size = read(fd, buf, count);
127         if (size < 0) {
128                 bb_perror_msg_and_die(bb_msg_read_error);
129         }
130         return(size);
131 }
132 #endif
133
134 #ifdef L_xread_all
135 void bb_xread_all(int fd, void *buf, size_t count)
136 {
137         ssize_t size;
138
139         while (count) {
140                 if ((size = bb_xread(fd, buf, count)) == 0) {   /* EOF */
141                         bb_error_msg_and_die("Short read");
142                 }
143                 count -= size;
144                 buf = ((char *) buf) + size;
145         }
146         return;
147 }
148 #endif
149
150 #ifdef L_xread_char
151 unsigned char bb_xread_char(int fd)
152 {
153         char tmp;
154
155         bb_xread_all(fd, &tmp, 1);
156
157         return(tmp);
158 }
159 #endif
160
161 #ifdef L_xferror
162 void bb_xferror(FILE *fp, const char *fn)
163 {
164         if (ferror(fp)) {
165                 bb_error_msg_and_die("%s", fn);
166         }
167 }
168 #endif
169
170 #ifdef L_xferror_stdout
171 void bb_xferror_stdout(void)
172 {
173         bb_xferror(stdout, bb_msg_standard_output);
174 }
175 #endif
176
177 #ifdef L_xfflush_stdout
178 void bb_xfflush_stdout(void)
179 {
180         if (fflush(stdout)) {
181                 bb_perror_msg_and_die(bb_msg_standard_output);
182         }
183 }
184 #endif
185
186 #ifdef L_spawn
187 // This does a fork/exec in one call, using vfork().
188 pid_t bb_spawn(char **argv)
189 {
190         static int failed;
191         pid_t pid;
192
193         // Be nice to nommu machines.
194         failed = 0;
195         pid = vfork();
196         if (pid < 0) return pid;
197         if (!pid) {
198                 execvp(*argv, argv);
199
200                 // We're sharing a stack with blocked parent, let parent know we failed
201                 // and then exit to unblock parent (but don't run atexit() stuff, which
202                 // would screw up parent.)
203
204                 failed = -1;
205                 _exit(0);
206         }
207         return failed ? failed : pid;
208 }
209 #endif
210
211 #ifdef L_xspawn
212 pid_t bb_xspawn(char **argv)
213 {
214         pid_t pid = bb_spawn(argv);
215         if (pid < 0) bb_perror_msg_and_die("%s", *argv);
216         return pid;
217 }
218 #endif