"Fossies" - the Fresh Open Source Software Archive 
Member "mpr-2.8/mprhook.c" (18 Dec 2003, 6157 Bytes) of package /linux/misc/old/mpr-2.8.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
1 #include <stdlib.h>
2 #include <string.h>
3 #include <unistd.h>
4 #include <signal.h>
5 #include <stdarg.h>
6 #include <fcntl.h>
7 #include <unistd.h>
8 #include <errno.h>
9 #include <sys/types.h>
10 #include <sys/wait.h>
11
12 #undef malloc
13 #undef free
14 #undef calloc
15 #undef realloc
16 #include <malloc.h>
17
18 #undef ulong
19 #define ulong unsigned long
20
21 extern void mprbt(int);
22 extern void *(*__mpr_malloc_hook)(size_t);
23 static void *(*old_malloc_hook)(size_t);
24 extern void (*__mpr_free_hook)(void *);
25 static void (*old_free_hook)(void *);
26 extern void *(*__mpr_realloc_hook)(void *, size_t);
27 static void *(*old_realloc_hook)(void *, size_t);
28 static void hook(void), unhook(void);
29 int mprprint(int fd, char *fmt, ...);
30
31 static pid_t mprmypid; /* current process id */
32 static pid_t mprpid; /* MPRFI child process id */
33 static int mprfd=-1; /* MPRFI pipe descriptor */
34 static int mprsync; /* == 0 -> buffer writes to mprfd */
35 static char mprbuf[8192]; /* buffer for mprfd */
36 static char *mprbp=mprbuf; /* current buffer pointer */
37
38 static int
39 xwrite(int fd, char *buf, int len)
40 {
41 int nleft, n;
42
43 for (nleft=len; nleft>0; nleft-=n, buf+=n) {
44 n = write(fd, buf, nleft);
45 if (n < 0) {
46 if (errno == EINTR) {
47 n=0;
48 continue;
49 }
50 if (fd != 2)
51 mprprint(2, "xwrite: warning: write failed errno=%d\n", errno);
52 return len-nleft;
53 }
54 }
55 return len;
56 }
57
58 static void
59 mprflush(void)
60 {
61 xwrite(mprfd, mprbuf, mprbp-mprbuf);
62 mprbp = mprbuf;
63 }
64
65 static int
66 mprwrite(int fd, char *str, char *buf, int len)
67 {
68 if (str) {
69 memmove(str, buf, len);
70 return len;
71 }
72 if (fd != mprfd) {
73 xwrite(fd, buf, len);
74 return len;
75 }
76 if (mprbp+len > mprbuf+sizeof(mprbuf)) /* flush */
77 mprflush();
78 if (mprbp+len > mprbuf+sizeof(mprbuf)) /* can't buffer */
79 xwrite(fd, buf, len);
80 else { /* buffer */
81 memmove(mprbp, buf, len);
82 mprbp += len;
83 }
84 return len;
85 }
86
87 static int
88 mprvprint(int fd, char *str, char *fmt, va_list ap)
89 {
90 ulong ul;
91 int i, len;
92 char *ep, *cp, buf[64];
93
94 for (ep=fmt, len=0; *ep; ep++) {
95 if (*ep == '%') {
96 switch (*++ep) {
97 case 'U':
98 ul = va_arg(ap, ulong);
99 cp = buf + sizeof(buf);
100 do
101 *--cp = '0' + ul%10;
102 while ((ul/=10) != 0);
103 len += mprwrite(fd, str, cp, buf+sizeof(buf)-cp);
104 break;
105 case 'd':
106 i = va_arg(ap, int);
107 ul = i<0 ? -i : i;
108 cp = buf + sizeof(buf);
109 do
110 *--cp = '0' + ul%10;
111 while ((ul/=10) != 0);
112 if (i < 0)
113 *--cp = '-';
114 len += mprwrite(fd, str, cp, buf+sizeof(buf)-cp);
115 break;
116 case 's':
117 cp = va_arg(ap, char *);
118 len += mprwrite(fd, str, cp, strlen(cp));
119 break;
120 default:
121 abort();
122 }
123 }
124 else {
125 len += mprwrite(fd, str, ep, 1);
126 if (mprsync && fd == mprfd && *ep == '\n')
127 mprflush();
128 }
129 }
130 return len;
131 }
132
133 int
134 mprprint(int fd, char *fmt, ...)
135 {
136 int len;
137 va_list ap;
138
139 if (fd < 0)
140 return -1;
141 va_start(ap, fmt);
142 len = mprvprint(fd, 0, fmt, ap);
143 va_end(ap);
144 return len;
145 }
146
147 static int
148 mprsprint(char *str, char *fmt, ...)
149 {
150 int len;
151 va_list ap;
152
153 va_start(ap, fmt);
154 len = mprvprint(-1, str, fmt, ap);
155 va_end(ap);
156 return len;
157 }
158
159 static void
160 mprexit(void)
161 {
162 pid_t pid;
163 int status;
164
165 if (mprfd < 0)
166 return;
167 mprflush();
168 if (close(mprfd) < 0)
169 mprprint(2, "mprexit: warning: close failed errno=%d\n", errno);
170 mprfd = -1;
171 unhook();
172 if (mprmypid != getpid()) /* child */
173 return;
174 do
175 pid = waitpid(mprpid, &status, 0);
176 while (pid < 0 && errno == EINTR);
177 if (pid < 0) {
178 mprprint(2, "mprexit: warning: waitpid failed errno=%d\n", errno);
179 return;
180 }
181 if (WIFEXITED(status) && WEXITSTATUS(status) != 0)
182 mprprint(2, "mprexit: warning: MPRFI exited %d\n", WEXITSTATUS(status));
183 if (WIFSIGNALED(status))
184 mprprint(2, "mprexit: warning: MPRFI caught signal %d\n", WTERMSIG(status));
185 }
186
187 static void *
188 malloc_hook(size_t sz)
189 {
190 void *ptr;
191
192 unhook();
193 ptr = malloc(sz);
194 mprprint(mprfd, "m:");
195 mprbt(mprfd);
196 mprprint(mprfd, "%U:%U\n", (ulong)sz, (ulong)ptr);
197 hook();
198 return ptr;
199 }
200
201 static void
202 free_hook(void *ptr)
203 {
204 unhook();
205 mprprint(mprfd, "f:");
206 mprbt(mprfd);
207 mprprint(mprfd, "%U\n", (ulong)ptr);
208 free(ptr);
209 hook();
210 }
211
212 static void *
213 realloc_hook(void *ptr, size_t sz)
214 {
215 void *ptr2;
216
217 unhook();
218 ptr2 = realloc(ptr, sz);
219 mprprint(mprfd, "r:");
220 mprbt(mprfd);
221 mprprint(mprfd, "%U:%U:%U\n", (ulong)sz, (ulong)ptr, (ulong)ptr2);
222 hook();
223 return ptr2;
224 }
225
226 static void
227 hook(void)
228 {
229 old_malloc_hook = __mpr_malloc_hook;
230 old_free_hook = __mpr_free_hook;
231 old_realloc_hook = __mpr_realloc_hook;
232 __mpr_malloc_hook = malloc_hook;
233 __mpr_free_hook = free_hook;
234 __mpr_realloc_hook = realloc_hook;
235 }
236
237 static void
238 unhook(void)
239 {
240 __mpr_malloc_hook = old_malloc_hook;
241 __mpr_free_hook = old_free_hook;
242 __mpr_realloc_hook = old_realloc_hook;
243 }
244
245 static int
246 mprpopen(char *mprfi)
247 {
248 char cmd[256], *cp, *mprsh;
249 struct sigaction sa;
250 int pfd[2];
251
252 for (cp=cmd; *mprfi && cp<cmd+sizeof(cmd); ) { /* s/%p/pid/ */
253 if (mprfi[0] == '%' && mprfi[1] == 'p') {
254 cp += mprsprint(cp, "%d", getpid());
255 mprfi += 2;
256 }
257 else
258 *cp++ = *mprfi++;
259 }
260 *cp = '\0';
261
262 if (pipe(pfd) < 0)
263 return -1;
264 if ((mprpid = fork()) < 0) {
265 close(pfd[0]);
266 close(pfd[1]);
267 return -1;
268 }
269 else if (mprpid == 0) {
270 close(pfd[1]);
271 if (pfd[0] != 0) {
272 if (dup2(pfd[0], 0) < 0) {
273 mprprint(2, "mprpopen: dup2 failed: errno=%d\n", errno);
274 exit(1);
275 }
276 close(pfd[0]);
277 }
278 putenv("MPRFI=");
279 if (!(mprsh = getenv("MPRSH")))
280 mprsh = "/bin/sh";
281 sa.sa_handler = SIG_IGN;
282 sa.sa_flags = 0;
283 sigemptyset(&sa.sa_mask);
284 sigaction(SIGINT, &sa, 0);
285 sigaction(SIGTERM, &sa, 0);
286 execl(mprsh, "sh", "-c", cmd, 0);
287 mprprint(2, "mprpopen: error: could not exec %s\n", mprsh);
288 _exit(127);
289 }
290 close(pfd[0]);
291 return pfd[1];
292 }
293
294 int
295 mprhook(void)
296 {
297 char *mprfi;
298 static int mprinit;
299
300 if (mprinit)
301 return 0;
302 mprmypid = getpid();
303 mprinit = 1;
304 if (!(mprfi = getenv("MPRFI")) || !*mprfi)
305 return 0;
306 if ((mprfd = mprpopen(mprfi)) < 0) {
307 mprprint(2, "mpr: error: mprpopen() failed\n");
308 return -1;
309 }
310 if (atexit(mprexit) < 0) {
311 mprprint(2, "mpr: error: atexit failed\n");
312 close(mprfd);
313 return -1;
314 }
315 if (getenv("MPRSYNC"))
316 mprsync = 1;
317 if (getenv("MPRNOCHILD"))
318 putenv("MPRFI=");
319 hook();
320 return 0;
321 }