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