]> git.saurik.com Git - apple/security.git/blobdiff - libsecurity_utilities/lib/unixchild.h
Security-55163.44.tar.gz
[apple/security.git] / libsecurity_utilities / lib / unixchild.h
diff --git a/libsecurity_utilities/lib/unixchild.h b/libsecurity_utilities/lib/unixchild.h
new file mode 100644 (file)
index 0000000..b9ff5a5
--- /dev/null
@@ -0,0 +1,136 @@
+/*
+ * 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