Annotation of ircnowd/src/ngircd/proc.c, Revision 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