source: trunk/lang/tcl/src/RpDaemon.c @ 1264

Last change on this file since 1264 was 1018, checked in by gah, 16 years ago

Massive changes: New directory/file layout

File size: 3.3 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-2007  Purdue Research Foundation
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
22static int RpDaemonCmd _ANSI_ARGS_((ClientData cdata,
23    Tcl_Interp *interp, int argc, CONST84 char *argv[]));
24
25/*
26 * ------------------------------------------------------------------------
27 *  RpDaemon_Init()
28 *
29 *  Called in Rappture_Init() to initialize the commands defined
30 *  in this file.
31 * ------------------------------------------------------------------------
32 */
33int
34RpDaemon_Init(interp)
35    Tcl_Interp *interp;  /* interpreter being initialized */
36{
37    /* install the daemon command */
38    Tcl_CreateCommand(interp, "::Rappture::daemon", RpDaemonCmd,
39        (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL);
40
41    return TCL_OK;
42}
43
44/*
45 * ------------------------------------------------------------------------
46 *  RpDaemonCmd()
47 *
48 *  Invoked whenever someone uses the "daemon" command to fork
49 *  and dissociate this process from its parent.  Handles the
50 *  following syntax:
51 *
52 *      daemon
53 *
54 *  Returns TCL_OK on success, and TCL_ERROR (along with an error
55 *  message in the interpreter) if anything goes wrong.
56 *
57 *  For details, see W. Richard Stevens, "Advanced Programming in
58 *  the Unix Environment," p. 418, Addison Wesley, 1992.
59 * ------------------------------------------------------------------------
60 */
61static int
62RpDaemonCmd(cdata, interp, argc, argv)
63    ClientData cdata;         /* not used */
64    Tcl_Interp *interp;       /* interpreter handling this request */
65    int argc;                 /* number of command line args */
66    CONST84 char *argv[];     /* strings for command line args */
67{
68    pid_t pid;
69
70    if ( (pid=fork()) < 0) {
71        Tcl_AppendResult(interp, "can't fork daemon", (char*)NULL);
72        if (errno == EAGAIN) {
73            Tcl_AppendResult(interp, ": resource limit",
74                (char*)NULL);
75        } else if (errno == ENOMEM) {
76            Tcl_AppendResult(interp, ": out of memory",
77                (char*)NULL);
78        }
79        return TCL_ERROR;
80    }
81    else if (pid != 0) {
82        Tcl_Exit(0);  /* parent exits here */
83    }
84
85    /* child continues... */
86    setsid();    /* become session leader */
87    chdir("/");  /* root never goes away, so sit here */
88
89    /* close at least this much, so pipes in exec'ing process get closed */
90    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN));
91    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT));
92    Tcl_UnregisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR));
93
94    /* make sure that these are really closed */
95    close(0);
96    close(1);
97    close(2);
98
99    Tcl_ResetResult(interp);  /* in case there was an error above */
100    return TCL_OK;
101}
Note: See TracBrowser for help on using the repository browser.