2 * Copyright (c) 2003-2006 Apple Computer, Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
33 #include "testleaks.h"
37 static char *cf_user_text_encoding_var
;
51 /* Work around the fact that CF calls setenv, which leaks. */
52 cf_user_text_encoding_var
= getenv("__CF_USER_TEXT_ENCODING");
54 ok_unix(parent
= getpid(), "getpid");
55 int cld_stdout
[2] = {};
56 ok_unix(child
= pipe(cld_stdout
), "pipe");
57 ok_unix(child
= fork(), "fork");
66 /* Set childs stdout and stderr to pipe. */
67 ok_unix(close(cld_stdout
[0]), "close parent end of pipe");
68 ok_unix(dup2(cld_stdout
[1], 1), "reopen stdout on pipe");
70 ok_unix(dup2(cld_stdout
[1], 2), "reopen stderr on pipe");
74 char *const *argv
= NULL
;
75 char **argvec
= (char **)malloc((argc
+ 2) * sizeof(char *));
79 sprintf(pidstr
, "%d", parent
);
80 argvec
[0] = "/usr/bin/leaks";
81 for (ix
= 1; ix
< argc
; ++ix
)
82 argvec
[ix
] = argv
[ix
];
84 argvec
[ix
+ 1] = NULL
;
86 ok_unix(execv(argvec
[0], argvec
), "execv");
93 ok_unix(close(cld_stdout
[1]), "close child end of pipe");
95 /* Set statemachine initial state to 0. */
97 /* True iff the last char read was a newline. */
104 bytes_read
= read(cld_stdout
[0], p
, 4096);
108 int start
= newline
? -2 : 0;
110 for (ix
= 0; ix
< bytes_read
; ++ix
)
112 /* Simple state machine for parsing leaks output.
114 * '[^\n]*\n[^:]*: ([0-9]*)'
115 * and sets leaks to atoi of the ([0-9]*) bit. */
118 case 0: if (p
[ix
] == '\n') state
= 1; break;
119 case 1: if (p
[ix
] == ':') state
= 2; break;
120 case 2: if (p
[ix
] == ' ') state
= 3; break;
122 if (p
[ix
] <= '0' || p
[ix
] >='9')
125 leaks
= leaks
* 10 + p
[ix
] - '0';
130 /* If there is a newline in the input or we are looking
131 at the last char of the buffer it's time to write the
133 if (p
[ix
] == '\n' || ix
+ 1 >= bytes_read
)
135 /* If the previous char was a newline we prefix the
142 fwrite(p
+ start
, ix
+ 1 - start
, 1, stdout
);
157 /* Wait for the child to exit. */
158 pid_t waited_pid
= waitpid(child
, &status
, 0);
159 if (waited_pid
== -1)
162 /* Keep going if we get interupted but bail out on any
167 ok_unix(waited_pid
, "waitpid");
171 if (WIFEXITED(status
))
173 is(WEXITSTATUS(status
), 0, "leaks exit status");
176 else if (WIFSIGNALED(status
))
178 is(WTERMSIG(status
), 0, "leaks terminated by");