1/* 2 * Copyright (c) 2003-2004,2006-2007,2013 Apple 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 * leaks.c 24 */ 25 26#include "leaks.h" 27 28#include <errno.h> 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <sys/wait.h> 33#include <unistd.h> 34 35int 36leaks(int argc, char *const *argv) 37{ 38 int result = 1; 39 pid_t child; 40 pid_t parent = getpid(); 41 42 child = fork(); 43 switch (child) 44 { 45 case -1: 46 /* Fork failed we're hosed. */ 47 fprintf(stderr, "fork: %s", strerror(errno)); 48 break; 49 case 0: 50 { 51 /* child. */ 52 char **argvec = (char **)malloc((argc + 2) * sizeof(char *)); 53 char pidstr[8]; 54 int ix; 55 56 sprintf(pidstr, "%d", parent); 57 argvec[0] = "/usr/bin/leaks"; 58 for (ix = 1; ix < argc; ++ix) 59 argvec[ix] = argv[ix]; 60 argvec[ix] = pidstr; 61 argvec[ix + 1] = NULL; 62 63 execv(argvec[0], argvec); 64 fprintf(stderr, "exec: %s", strerror(errno)); 65 _exit(1); 66 break; 67 } 68 default: 69 { 70 /* Parent. */ 71 int status = 0; 72 for (;;) 73 { 74 /* Wait for the child to exit. */ 75 pid_t waited_pid = waitpid(child, &status, 0); 76 if (waited_pid == -1) 77 { 78 int error = errno; 79 /* Keep going if we get interupted but bail out on any 80 other error. */ 81 if (error == EINTR) 82 continue; 83 84 fprintf(stderr, "waitpid %d: %s", status, strerror(errno)); 85 break; 86 } 87 88 if (WIFEXITED(status)) 89 { 90 if (WEXITSTATUS(status)) 91 { 92 /* Force usage message. */ 93 result = 2; 94 fprintf(stderr, "leaks exited: %d", result); 95 } 96 break; 97 } 98 else if (WIFSIGNALED(status)) 99 { 100 fprintf(stderr, "leaks terminated by signal: %d", WTERMSIG(status)); 101 break; 102 } 103 } 104 break; 105 } 106 } 107 108 return result; 109} 110