1/* 2 * Copyright (c) 2003-2006 Apple Computer, Inc. All Rights Reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 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 11 * file. 12 * 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. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 * 23 * testleaks.c 24 */ 25 26#include <errno.h> 27#include <stdio.h> 28#include <stdlib.h> 29#include <string.h> 30#include <sys/wait.h> 31#include <unistd.h> 32 33#include "testleaks.h" 34#include "testmore.h" 35 36#if 0 37static char *cf_user_text_encoding_var; 38#endif 39 40int 41test_leaks(void) 42{ 43 return 0; 44#if 0 45 int leaks = 0; 46 pid_t child; 47 pid_t parent; 48 49 setup("leaks"); 50 51 /* Work around the fact that CF calls setenv, which leaks. */ 52 cf_user_text_encoding_var = getenv("__CF_USER_TEXT_ENCODING"); 53 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"); 58 switch (child) 59 { 60 case -1: 61 break; 62 case 0: 63 { 64 /* child. */ 65 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"); 69#if 0 70 ok_unix(dup2(cld_stdout[1], 2), "reopen stderr on pipe"); 71#endif 72 73 int argc = 0; 74 char *const *argv = NULL; 75 char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); 76 char pidstr[8]; 77 int ix; 78 79 sprintf(pidstr, "%d", parent); 80 argvec[0] = "/usr/bin/leaks"; 81 for (ix = 1; ix < argc; ++ix) 82 argvec[ix] = argv[ix]; 83 argvec[ix] = pidstr; 84 argvec[ix + 1] = NULL; 85 86 ok_unix(execv(argvec[0], argvec), "execv"); 87 _exit(1); 88 break; 89 } 90 default: 91 { 92 /* Parent. */ 93 ok_unix(close(cld_stdout[1]), "close child end of pipe"); 94 95 /* Set statemachine initial state to 0. */ 96 int state = 0; 97 /* True iff the last char read was a newline. */ 98 int newline = 1; 99 char buf[4098]; 100 for (;;) 101 { 102 char *p = buf + 2; 103 ssize_t bytes_read; 104 bytes_read = read(cld_stdout[0], p, 4096); 105 if (bytes_read <= 0) 106 break; 107 108 int start = newline ? -2 : 0; 109 int ix = 0; 110 for (ix = 0; ix < bytes_read; ++ix) 111 { 112 /* Simple state machine for parsing leaks output. 113 * Looks for 114 * '[^\n]*\n[^:]*: ([0-9]*)' 115 * and sets leaks to atoi of the ([0-9]*) bit. */ 116 switch (state) 117 { 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; 121 case 3: 122 if (p[ix] <= '0' || p[ix] >='9') 123 state = 4; 124 else 125 leaks = leaks * 10 + p[ix] - '0'; 126 break; 127 case 4: break; 128 } 129 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 132 output. */ 133 if (p[ix] == '\n' || ix + 1 >= bytes_read) 134 { 135 /* If the previous char was a newline we prefix the 136 output with "# ". */ 137 if (newline) 138 { 139 p[start] = '#'; 140 p[start + 1] = ' '; 141 } 142 fwrite(p + start, ix + 1 - start, 1, stdout); 143 if (p[ix] == '\n') 144 { 145 start = ix - 1; 146 newline = 1; 147 } 148 else 149 newline = 0; 150 } 151 } 152 } 153 154 int status = 0; 155 for (;;) 156 { 157 /* Wait for the child to exit. */ 158 pid_t waited_pid = waitpid(child, &status, 0); 159 if (waited_pid == -1) 160 { 161 int error = errno; 162 /* Keep going if we get interupted but bail out on any 163 other error. */ 164 if (error == EINTR) 165 continue; 166 167 ok_unix(waited_pid, "waitpid"); 168 break; 169 } 170 171 if (WIFEXITED(status)) 172 { 173 is(WEXITSTATUS(status), 0, "leaks exit status"); 174 break; 175 } 176 else if (WIFSIGNALED(status)) 177 { 178 is(WTERMSIG(status), 0, "leaks terminated by"); 179 break; 180 } 181 } 182 break; 183 } 184 } 185 186 return leaks; 187#endif 188} 189