source: branches/uq/lang/tcl/src/RpDaemon.c @ 5679

Last change on this file since 5679 was 5679, checked in by ldelgass, 9 years ago

Full merge 1.3 branch to uq branch to sync. Fixed partial subdirectory merge
by removing mergeinfo from lang/python/Rappture directory.

  • Property svn:eol-style set to native
File size: 3.4 KB
Line 
1/*
2 * ----------------------------------------------------------------------
3 *  Rappture::daemon
4 *
5 *  Programs call this to dissociate themselves from their parents,
6 *  so they can continue to run in the background as a daemon process.
7 * ======================================================================
8 *  AUTHOR:  Michael McLennan, Purdue University
9 *  Copyright (c) 2004-2012  HUBzero Foundation, LLC
10 *
11 *  See the file "license.terms" for information on usage and
12 *  redistribution of this file, and for a DISCLAIMER OF ALL WARRANTIES.
13 * ======================================================================
14 */
15#include <tcl.h>
16#include <unistd.h>
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <fcntl.h>
20#include <errno.h>
21#include <assert.h>
22
23static int RpDaemonCmd _ANSI_ARGS_((ClientData cdata,
24    Tcl_Interp *interp, int argc, CONST84 char *argv[]));
25
26/*
27 * ------------------------------------------------------------------------
28 *  RpDaemon_Init()
29 *
30 *  Called in Rappture_Init() to initialize the commands defined
31 *  in this file.
32 * ------------------------------------------------------------------------
33 */
34int
35RpDaemon_Init(interp)
36    Tcl_Interp *interp;  /* interpreter being initialized */
37{
38    /* install the daemon command */
39    Tcl_CreateCommand(interp, "::Rappture::daemon", RpDaemonCmd,
40        (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
41
42    return TCL_OK;
43}
44
45/*
46 * ------------------------------------------------------------------------
47 *  RpDaemonCmd()
48 *
49 *  Invoked whenever someone uses the "daemon" command to fork
50 *  and dissociate this process from its parent.  Handles the
51 *  following syntax:
52 *
53 *      daemon
54 *
55 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
56 *  message in the interpreter) if anything goes wrong.
57 *
58 *  For details, see W. Richard Stevens, "Advanced Programming in
59 *  the Unix Environment," p. 418, Addison Wesley, 1992.
60 * ------------------------------------------------------------------------
61 */
62static int
63RpDaemonCmd(cdata, interp, argc, argv)
64    ClientData cdata;         /* not used */
65    Tcl_Interp *interp;       /* interpreter handling this request */
66    int argc;                 /* number of command line args */
67    CONST84 char *argv[];     /* strings for command line args */
68{
69    pid_t pid;
70    int result;
71
72    pid = fork();
73    if (pid < 0) {
74        Tcl_AppendResult(interp, "can't fork daemon", (char*)NULL);
75        if (errno == EAGAIN) {
76            Tcl_AppendResult(interp, ": resource limit",
77                (char*)NULL);
78        } else if (errno == ENOMEM) {
79            Tcl_AppendResult(interp, ": out of memory",
80                (char*)NULL);
81        }
82        return TCL_ERROR;
83    }
84    else if (pid != 0) {
85        Tcl_Exit(0);  /* parent exits here */
86    }
87
88    /* child continues... */
89    setsid();    /* become session leader */
90    result = chdir("/");  /* root never goes away, so sit here */
91    assert(result == 0);
92    /* close at least this much, so pipes in exec'ing process get closed */
93    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
94    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
95    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
96
97    /* make sure that these are really closed */
98    close(0);
99    close(1);
100    close(2);
101
102    Tcl_ResetResult(interp);  /* in case there was an error above */
103    return TCL_OK;
104}
Note: See TracBrowser for help on using the repository browser.