Annotation of ircnowd/src/ngircd/proc.c, Revision 1.1.1.1
1.1 tomglok 1: /*
2: * ngIRCd -- The Next Generation IRC Daemon
3: * Copyright (c)2001-2014 Alexander Barton (alex@barton.de) and Contributors.
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; either version 2 of the License, or
8: * (at your option) any later version.
9: * Please read the file COPYING, README and AUTHORS for more information.
10: */
11:
12: #include "portab.h"
13:
14: /**
15: * @file
16: * Process management
17: */
18:
19: #include <assert.h>
20: #include <errno.h>
21: #include <signal.h>
22: #include <string.h>
23: #include <stdlib.h>
24: #include <sys/types.h>
25: #include <unistd.h>
26: #include <time.h>
27:
28: #include "log.h"
29: #include "io.h"
30: #include "sighandlers.h"
31:
32: #include "proc.h"
33:
34: /**
35: * Initialize process structure.
36: */
37: GLOBAL void
38: Proc_InitStruct (PROC_STAT *proc)
39: {
40: assert(proc != NULL);
41: proc->pid = 0;
42: proc->pipe_fd = -1;
43: }
44:
45: /**
46: * Fork a child process.
47: */
48: GLOBAL pid_t
49: Proc_Fork(PROC_STAT *proc, int *pipefds, void (*cbfunc)(int, short), int timeout)
50: {
51: pid_t pid;
52: #ifndef HAVE_ARC4RANDOM
53: unsigned int seed;
54: #endif
55:
56: assert(proc != NULL);
57: assert(pipefds != NULL);
58: assert(cbfunc != NULL);
59:
60: if (pipe(pipefds) != 0) {
61: Log(LOG_ALERT, "Can't create output pipe for child process: %s!",
62: strerror(errno));
63: return -1;
64: }
65:
66: #ifndef HAVE_ARC4RANDOM
67: seed = (unsigned int)rand();
68: #endif
69: pid = fork();
70: switch (pid) {
71: case -1:
72: /* Error on fork: */
73: Log(LOG_CRIT, "Can't fork child process: %s!", strerror(errno));
74: close(pipefds[0]);
75: close(pipefds[1]);
76: return -1;
77: case 0:
78: /* New child process: */
79: #ifdef HAVE_ARC4RANDOM_STIR
80: arc4random_stir();
81: #endif
82: #ifndef HAVE_ARC4RANDOM
83: srand(seed ^ (unsigned int)time(NULL) ^ getpid());
84: #endif
85: Signals_Exit();
86: signal(SIGTERM, Proc_GenericSignalHandler);
87: signal(SIGALRM, Proc_GenericSignalHandler);
88: close(pipefds[0]);
89: alarm(timeout);
90: return 0;
91: }
92:
93: /* Old parent process: */
94: close(pipefds[1]);
95:
96: if (!io_setnonblock(pipefds[0])
97: || !io_event_create(pipefds[0], IO_WANTREAD, cbfunc)) {
98: Log(LOG_CRIT, "Can't register callback for child process: %s!",
99: strerror(errno));
100: close(pipefds[0]);
101: return -1;
102: }
103:
104: proc->pid = pid;
105: proc->pipe_fd = pipefds[0];
106: return pid;
107: }
108:
109: /**
110: * Generic signal handler for forked child processes.
111: */
112: GLOBAL void
113: Proc_GenericSignalHandler(int Signal)
114: {
115: switch(Signal) {
116: case SIGTERM:
117: #ifdef DEBUG
118: Log_Subprocess(LOG_DEBUG, "Child got TERM signal, exiting.");
119: #endif
120: exit(1);
121: case SIGALRM:
122: #ifdef DEBUG
123: Log_Subprocess(LOG_DEBUG, "Child got ALARM signal, exiting.");
124: #endif
125: exit(1);
126: }
127: }
128:
129: /**
130: * Read bytes from a pipe of a forked child process.
131: * In addition, this function makes sure that the child process is ignored
132: * after all data has been read or a fatal error occurred.
133: */
134: GLOBAL size_t
135: Proc_Read(PROC_STAT *proc, void *buffer, size_t buflen)
136: {
137: ssize_t bytes_read = 0;
138:
139: assert(buffer != NULL);
140: assert(buflen > 0);
141:
142: bytes_read = read(proc->pipe_fd, buffer, buflen);
143: if (bytes_read < 0) {
144: if (errno == EAGAIN)
145: return 0;
146: Log(LOG_CRIT, "Can't read from child process %ld: %s",
147: proc->pid, strerror(errno));
148: Proc_Close(proc);
149: bytes_read = 0;
150: } else if (bytes_read == 0) {
151: /* EOF: clean up */
152: LogDebug("Child process %ld: EOF reached, closing pipe.",
153: proc->pid);
154: Proc_Close(proc);
155: }
156: return (size_t)bytes_read;
157: }
158:
159: /**
160: * Close pipe to a forked child process.
161: */
162: GLOBAL void
163: Proc_Close(PROC_STAT *proc)
164: {
165: /* Close socket, if it exists */
166: if (proc->pipe_fd >= 0)
167: io_close(proc->pipe_fd);
168:
169: Proc_InitStruct(proc);
170: }
171:
172: /* -eof- */
CVSweb