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