1/* 2 * Copyright (c) 2004 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 24 25// 26// unixchild - low-level UNIX process child management 27// 28#ifndef _H_UNIXCHILD 29#define _H_UNIXCHILD 30 31#include <security_utilities/utilities.h> 32#include <security_utilities/errors.h> 33#include <security_utilities/globalizer.h> 34#include <sys/types.h> 35#include <sys/wait.h> 36#include <map> 37#include <list> 38 39 40namespace Security { 41namespace UnixPlusPlus { 42 43 44// 45// A Child object represents a (potential) fork-child of your process. 46// It could be a clean fork or a fork/exec; this layer doesn't care. 47// It is meant to track the UNIX-life of that process. 48// Subclass Child or use it as a mix-in. 49// 50// Child keeps track of all alive children; Child::find<>() can locate them 51// by pid if you like. Other children are not collected; you've got to do this 52// yourself. 53// 54class Child { 55public: 56 Child(); 57 virtual ~Child(); 58 59 enum State { 60 unborn, // never forked 61 alive, // last seen alive 62 dead, // coroner confirms death 63 stopped, // stopped due to trace or job control (not implemented) 64 abandoned, // cut loose (via forget()) 65 invalid // system says we're all confused about this child 66 }; 67 68 void fork(); // do the forky-forky 69 70 State state() const { return mState; } 71 operator bool () const { return mState == alive; } 72 pid_t pid() const { assert(mState != unborn); return mPid; } 73 74 State check(); // update status on (just) this child and return new state 75 void wait(); // wait for (just) this Child to die 76 77 void kill(int signal); // send signal to child (if alive) 78 void kill(); // bring me its head, NOW 79 80 // status is only available for dead children 81 int waitStatus() const; // raw wait(2) status byte 82 bool succeeded() const { return waitStatus() == 0; } 83 bool bySignal() const; // was killed by a signal 84 int exitCode() const; // exit() code; valid only if !bySignal() 85 int exitSignal() const; // signal that killed child; valid only if bySignal() 86 bool coreDumped() const; // child dumped core when it died 87 88protected: 89 virtual void childAction() = 0; // called in child after fork() 90 virtual void parentAction(); // called in parent after fork() 91 virtual void dying(); // called when child is confirmed dead 92 93 void abandon(); // cut a living child loose (forget about it) 94 95private: 96 State mState; // child state 97 pid_t mPid; // pid of child (if born) 98 int mStatus; // exit status (if dead) 99 100 bool checkStatus(int options); // check status of this Child (wait4) 101 void bury(int status); // canonical last rites 102 static Child *findGeneric(pid_t pid); // find living child by pid 103 void tryKill(int signal); 104 105 class Bier: public std::list<Child *> { 106 public: 107 void add(Child *child) { this->push_back(child); } 108 void notify(); 109 }; 110 111public: 112 // set sharedChildren(true) in library code to leave other children alone 113 static void sharedChildren(bool s); 114 static bool sharedChildren(); 115 116 void reset(); // make Child ready to be born again (forgets all state) 117 118 static void checkChildren(); // update status on living offspring 119 120 template <class Subclass> 121 static Subclass *find(pid_t pid) 122 { return dynamic_cast<Subclass *>(findGeneric(pid)); } 123 124private: 125 struct Children : public Mutex, public std::map<pid_t, Child *> { 126 Children() : shared(false) { } 127 bool shared; 128 }; 129 static ModuleNexus<Children> mChildren; 130}; 131 132 133} // end namespace UnixPlusPlus 134} // end namespace Security 135 136#endif //_H_UNIXCHILD 137