--- /dev/null
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+
+//
+// unixchild - low-level UNIX process child management
+//
+#ifndef _H_UNIXCHILD
+#define _H_UNIXCHILD
+
+#include <security_utilities/utilities.h>
+#include <security_utilities/errors.h>
+#include <security_utilities/globalizer.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <map>
+#include <list>
+
+
+namespace Security {
+namespace UnixPlusPlus {
+
+
+//
+// A Child object represents a (potential) fork-child of your process.
+// It could be a clean fork or a fork/exec; this layer doesn't care.
+// It is meant to track the UNIX-life of that process.
+// Subclass Child or use it as a mix-in.
+//
+// Child keeps track of all alive children; Child::find<>() can locate them
+// by pid if you like. Other children are not collected; you've got to do this
+// yourself.
+//
+class Child {
+public:
+ Child();
+ virtual ~Child();
+
+ enum State {
+ unborn, // never forked
+ alive, // last seen alive
+ dead, // coroner confirms death
+ stopped, // stopped due to trace or job control (not implemented)
+ abandoned, // cut loose (via forget())
+ invalid // system says we're all confused about this child
+ };
+
+ void fork(); // do the forky-forky
+
+ State state() const { return mState; }
+ operator bool () const { return mState == alive; }
+ pid_t pid() const { assert(mState != unborn); return mPid; }
+
+ State check(); // update status on (just) this child and return new state
+ void wait(); // wait for (just) this Child to die
+
+ void kill(int signal); // send signal to child (if alive)
+ void kill(); // bring me its head, NOW
+
+ // status is only available for dead children
+ int waitStatus() const; // raw wait(2) status byte
+ bool succeeded() const { return waitStatus() == 0; }
+ bool bySignal() const; // was killed by a signal
+ int exitCode() const; // exit() code; valid only if !bySignal()
+ int exitSignal() const; // signal that killed child; valid only if bySignal()
+ bool coreDumped() const; // child dumped core when it died
+
+protected:
+ virtual void childAction() = 0; // called in child after fork()
+ virtual void parentAction(); // called in parent after fork()
+ virtual void dying(); // called when child is confirmed dead
+
+ void abandon(); // cut a living child loose (forget about it)
+
+private:
+ State mState; // child state
+ pid_t mPid; // pid of child (if born)
+ int mStatus; // exit status (if dead)
+
+ bool checkStatus(int options); // check status of this Child (wait4)
+ void bury(int status); // canonical last rites
+ static Child *findGeneric(pid_t pid); // find living child by pid
+ void tryKill(int signal);
+
+ class Bier: public std::list<Child *> {
+ public:
+ void add(Child *child) { this->push_back(child); }
+ void notify();
+ };
+
+public:
+ // set sharedChildren(true) in library code to leave other children alone
+ static void sharedChildren(bool s);
+ static bool sharedChildren();
+
+ void reset(); // make Child ready to be born again (forgets all state)
+
+ static void checkChildren(); // update status on living offspring
+
+ template <class Subclass>
+ static Subclass *find(pid_t pid)
+ { return dynamic_cast<Subclass *>(findGeneric(pid)); }
+
+private:
+ struct Children : public Mutex, public std::map<pid_t, Child *> {
+ Children() : shared(false) { }
+ bool shared;
+ };
+ static ModuleNexus<Children> mChildren;
+};
+
+
+} // end namespace UnixPlusPlus
+} // end namespace Security
+
+#endif //_H_UNIXCHILD