00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <fcntl.h>
00022
00023 #include "wvfork.h"
00024 #include "wvlinklist.h"
00025
00026 #define MAX_FD sysconf(_SC_OPEN_MAX) + 1
00027
00028 DeclareWvList(WvForkCallback);
00029 WvForkCallbackList callbacks;
00030
00031
00032 void add_wvfork_callback(WvForkCallback cb)
00033 {
00034 #if 0
00035
00036 WvForkCallbackList::Iter i(callbacks);
00037 for (i.rewind(); i.next(); )
00038 if (*i == cb) return;
00039 #endif
00040 callbacks.append(new WvForkCallback(cb), true);
00041 }
00042
00043 #if 0
00044 void remove_wvfork_callback(WvForkCallback cb)
00045 {
00046 WvForkCallbackList::Iter i(callbacks);
00047 for (i.rewind(); i.next(); )
00048 if (*i == cb) i.xunlink();
00049 }
00050 #endif
00051
00052 pid_t wvfork(int dontclose1, int dontclose2)
00053 {
00054 intTable t(1);
00055 if (dontclose1 >= 0)
00056 t.add(&dontclose1, false);
00057 if (dontclose2 >= 0)
00058 t.add(&dontclose2, false);
00059 return (wvfork(t));
00060 }
00061
00062 pid_t wvfork_start(int *waitfd)
00063 {
00064 int waitpipe[2];
00065
00066 if (pipe(waitpipe) < 0)
00067 return -1;
00068
00069 pid_t pid = fork();
00070
00071 WvForkCallbackList::Iter i(callbacks);
00072 for (i.rewind(); i.next(); )
00073 {
00074 WvForkCallback *cb = i.ptr();
00075 (*cb)(pid);
00076 }
00077
00078 if (pid < 0)
00079 return pid;
00080 else if (pid > 0)
00081 {
00082
00083
00084 char buf;
00085 close(waitpipe[1]);
00086 read(waitpipe[0], &buf, 1);
00087 close(waitpipe[0]);
00088 }
00089 else
00090 {
00091
00092 close(waitpipe[0]);
00093 *waitfd = waitpipe[1];
00094 }
00095
00096 return pid;
00097 }
00098
00099 pid_t wvfork(intTable &dontclose)
00100 {
00101 int waitfd = -1;
00102 pid_t pid = wvfork_start(&waitfd);
00103
00104 if (pid != 0)
00105 {
00106
00107 return pid;
00108 }
00109
00110
00111
00112 for (int fd = 0; fd < MAX_FD; fd++)
00113 {
00114 if (!dontclose[fd] && fd != waitfd &&
00115 (fcntl(fd, F_GETFD) & FD_CLOEXEC) > 0)
00116 close(fd);
00117 }
00118
00119 close(waitfd);
00120
00121 return pid;
00122 }