1/* $Id: daemonize.c,v 1.2 2009/02/20 10:21:23 jmaggard Exp $ */
2/* MiniUPnP project
3 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
4 * (c) 2006 Thomas Bernard
5 * This software is subject to the conditions detailed
6 * in the LICENCE file provided within the distribution */
7
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <unistd.h>
11#include <fcntl.h>
12#include <stdio.h>
13#include <stdlib.h>
14#include <errno.h>
15#include <string.h>
16#include <signal.h>
17
18#include "daemonize.h"
19#include "config.h"
20#include "log.h"
21
22#ifndef USE_DAEMON
23
24int
25daemonize(void)
26{
27	int pid, i;
28
29	switch(fork())
30	{
31	/* fork error */
32	case -1:
33		perror("fork()");
34		exit(1);
35
36	/* child process */
37	case 0:
38		/* obtain a new process group */
39		if( (pid = setsid()) < 0)
40		{
41			perror("setsid()");
42			exit(1);
43		}
44
45		/* close all descriptors */
46		for (i=getdtablesize();i>=0;--i) close(i);
47
48		i = open("/dev/null",O_RDWR); /* open stdin */
49		dup(i); /* stdout */
50		dup(i); /* stderr */
51
52		umask(027);
53		chdir("/"); /* chdir to /tmp ? */
54
55		return pid;
56
57	/* parent process */
58	default:
59		exit(0);
60	}
61}
62#endif
63
64int
65writepidfile(const char * fname, int pid)
66{
67	char pidstring[16];
68	int pidstringlen;
69	int pidfile;
70
71	if(!fname || (strlen(fname) == 0))
72		return -1;
73
74	if( (pidfile = open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666)) < 0)
75	{
76		DPRINTF(E_ERROR, L_GENERAL, "Unable to open pidfile for writing %s: %s\n", fname, strerror(errno));
77		return -1;
78	}
79
80	pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid);
81	if(pidstringlen <= 0)
82	{
83		DPRINTF(E_ERROR, L_GENERAL,
84			"Unable to write to pidfile %s: snprintf(): FAILED\n", fname);
85		close(pidfile);
86		return -1;
87	}
88	else
89	{
90		if(write(pidfile, pidstring, pidstringlen) < 0)
91			DPRINTF(E_ERROR, L_GENERAL, "Unable to write to pidfile %s: %s\n", fname, strerror(errno));
92	}
93
94	close(pidfile);
95
96	return 0;
97}
98
99int
100checkforrunning(const char * fname)
101{
102	char buffer[64];
103	int pidfile;
104	pid_t pid;
105
106	if(!fname || (strlen(fname) == 0))
107		return -1;
108
109	if( (pidfile = open(fname, O_RDONLY)) < 0)
110		return 0;
111
112	memset(buffer, 0, 64);
113
114	if(read(pidfile, buffer, 63))
115	{
116		if( (pid = atol(buffer)) > 0)
117		{
118			if(!kill(pid, 0))
119			{
120				close(pidfile);
121				return -2;
122			}
123		}
124	}
125
126	close(pidfile);
127
128	return 0;
129}
130
131