6f786d5de064690c21c0fd226e548c448a77e852
[util-vserver.git] / src / context-sync.hc
1 // $Id: context-sync.hc,v 1.5 2005/04/10 01:01:33 ensc Exp $    --*- c -*--
2
3 // Copyright (C) 2004 Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
4 //  
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; version 2 of the License.
8 //  
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 // GNU General Public License for more details.
13 //  
14 // You should have received a copy of the GNU General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17
18
19 /// \args p[0]  used for parent -> child sync (child waits till parent is in deathrow)
20 /// \args p[1]  used for child -> parent sync (recognize execv() errors)
21 static inline ALWAYSINLINE int
22 initSync(int p[2][2], bool do_disconnect)
23 {
24   if (!do_disconnect) return 0;
25
26   Epipe(p[0]);
27   Epipe(p[1]);
28   fcntl(p[1][1], F_SETFD, FD_CLOEXEC);
29   return Efork();
30 }
31
32 static inline ALWAYSINLINE void
33 doSyncStage0(int p[2][2], bool do_disconnect)
34 {
35   char          c;
36   if (!do_disconnect) return;
37
38   Eclose(p[0][1]);
39   Eread (p[0][0], &c, 1);
40   Eclose(p[0][0]);
41 }
42
43 static inline ALWAYSINLINE void
44 doSyncStage1(int p[2][2], bool do_disconnect)
45 {
46   int   fd;
47
48   if (!do_disconnect) return;
49   
50   fd = EopenD("/dev/null", O_RDONLY|O_NONBLOCK, 0);
51   (void)setsid();       // ignore error when we are already a session-leader
52   Edup2(fd, 0);
53   Eclose(p[1][0]);
54   if (fd!=0) Eclose(fd);
55   Ewrite(p[1][1], ".", 1);
56 }
57
58 static inline ALWAYSINLINE void
59 doSyncStage2(int p[2][2], bool do_disconnect)
60 {
61   if (!do_disconnect) return;
62
63   Ewrite(p[1][1], "X", 1);
64 }
65
66 /// \args p[0]  used for parent -> child sync (child waits till parent is in deathrow)
67 /// \args p[1]  used for child -> parent sync (recognize execv() errors)
68 static void
69 waitOnSync(pid_t pid, int p[2][2], bool is_prevent_race)
70 {
71   char          c;
72   size_t        l;
73
74   if (is_prevent_race &&
75       !jailIntoTempDir(0)) {
76     perror(ENSC_WRAPPERS_PREFIX "jailIntoTempDir()");
77     exit(255);
78   }
79
80   Eclose(p[0][0]);
81   Ewrite(p[0][1], "X", 1);
82   Eclose(p[0][1]);
83   
84   Eclose(p[1][1]);
85   l = Eread(p[1][0], &c, 1);
86   if (l!=1) exitLikeProcess(pid,0, wrapper_exit_code);
87   l = Eread(p[1][0], &c, 1);
88   if (l!=0) exitLikeProcess(pid,0, wrapper_exit_code);
89 }