Home | History | Annotate | Download | only in gen
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 
     22 /*
     23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     24  * Use is subject to license terms.
     25  */
     26 
     27 #include "lint.h"
     28 #include "file64.h"
     29 #include "mtlib.h"
     30 
     31 #include <stdio.h>
     32 #include <stdlib.h>
     33 #include <unistd.h>
     34 #include <fcntl.h>
     35 
     36 #include "stdiom.h"
     37 
     38 /*
     39  * Use fork/setsid/fork to go into background and permanently remove
     40  * controlling terminal.
     41  */
     42 int
     43 daemon(int nochdir, int noclose)
     44 {
     45 	int retv, fd;
     46 
     47 	/*
     48 	 * By the first fork+setsid, we disconnect from our current controlling
     49 	 * terminal and become a session group leader.
     50 	 */
     51 	retv = fork();
     52 	if (retv == -1)
     53 		return (-1);
     54 	if (retv != 0)
     55 		_exit(EXIT_SUCCESS);
     56 	if (setsid() == -1)
     57 		return (-1);
     58 	/*
     59 	 * By forking again without calling setsid again, we make certain
     60 	 * that we are not the session group leader and can never reacquire
     61 	 * a controlling terminal.
     62 	 */
     63 	retv = fork();
     64 	if (retv == -1)
     65 		return (-1);
     66 	if (retv != 0)
     67 		_exit(EXIT_SUCCESS);
     68 
     69 	if (nochdir == 0)
     70 		(void) chdir("/");
     71 
     72 	if (noclose == 0) {
     73 		/*
     74 		 * Missing the PRIV_FILE_READ privilege may be one of the
     75 		 * reasons that prevent the opening of /dev/null to succeed.
     76 		 */
     77 		if ((fd = open("/dev/null", O_RDWR)) == -1)
     78 			return (-1);
     79 
     80 		/*
     81 		 * Also, if any of the descriptor redirects fails we should
     82 		 * return with error to signal to the caller that his request
     83 		 * cannot be fulfilled properly. It is up to the caller to
     84 		 * do the cleanup.
     85 		 */
     86 		if ((fd != STDIN_FILENO) && (dup2(fd, STDIN_FILENO) < 0)) {
     87 			(void) close(fd);
     88 			return (-1);
     89 		}
     90 		if ((fd != STDOUT_FILENO) && (dup2(fd, STDOUT_FILENO) < 0)) {
     91 			(void) close(fd);
     92 			return (-1);
     93 		}
     94 		if ((fd != STDERR_FILENO) && (dup2(fd, STDERR_FILENO) < 0)) {
     95 			(void) close(fd);
     96 			return (-1);
     97 		}
     98 
     99 		if (fd > STDERR_FILENO)
    100 			(void) close(fd);
    101 	}
    102 	return (0);
    103 }
    104