1/* MiniUPnP project
2 * http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
3 *
4 * Copyright (c) 2006, Thomas Bernard
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *     * Redistributions of source code must retain the above copyright
10 *       notice, this list of conditions and the following disclaimer.
11 *     * Redistributions in binary form must reproduce the above copyright
12 *       notice, this list of conditions and the following disclaimer in the
13 *       documentation and/or other materials provided with the distribution.
14 *     * The name of the author may not be used to endorse or promote products
15 *       derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 */
29#include <sys/types.h>
30#include <sys/stat.h>
31#include <unistd.h>
32#include <fcntl.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <errno.h>
36#include <string.h>
37#include <signal.h>
38
39#include "daemonize.h"
40#include "config.h"
41#include "log.h"
42
43int
44daemonize(void)
45{
46	int pid;
47#ifndef USE_DAEMON
48	int i;
49
50	switch(fork())
51	{
52	/* fork error */
53	case -1:
54		perror("fork()");
55		exit(1);
56
57	/* child process */
58	case 0:
59		/* obtain a new process group */
60		if( (pid = setsid()) < 0)
61		{
62			perror("setsid()");
63			exit(1);
64		}
65
66		/* close all descriptors */
67		for (i=getdtablesize();i>=0;--i) close(i);
68
69		i = open("/dev/null",O_RDWR); /* open stdin */
70		dup(i); /* stdout */
71		dup(i); /* stderr */
72
73		umask(027);
74		chdir("/");
75
76		break;
77	/* parent process */
78	default:
79		exit(0);
80	}
81#else
82/*
83	if( daemon(0, 0) < 0 )
84		perror("daemon()");
85*/
86	pid = getpid();
87#endif
88	return pid;
89}
90
91int
92writepidfile(const char * fname, int pid)
93{
94	char pidstring[16];
95	int pidstringlen;
96	int pidfile;
97
98	if(!fname || (strlen(fname) == 0))
99		return -1;
100
101	if( (pidfile = open(fname, O_WRONLY|O_CREAT, 0644)) < 0)
102	{
103		DPRINTF(E_ERROR, L_GENERAL, "Unable to open pidfile for writing %s: %s\n", fname, strerror(errno));
104		return -1;
105	}
106
107	pidstringlen = snprintf(pidstring, sizeof(pidstring), "%d\n", pid);
108	if(pidstringlen <= 0)
109	{
110		DPRINTF(E_ERROR, L_GENERAL,
111			"Unable to write to pidfile %s: snprintf(): FAILED\n", fname);
112		close(pidfile);
113		return -1;
114	}
115	else
116	{
117		if(write(pidfile, pidstring, pidstringlen) < 0)
118			DPRINTF(E_ERROR, L_GENERAL, "Unable to write to pidfile %s: %s\n", fname, strerror(errno));
119	}
120
121	close(pidfile);
122
123	return 0;
124}
125
126int
127checkforrunning(const char * fname)
128{
129	char buffer[64];
130	int pidfile;
131	pid_t pid;
132
133	if(!fname || (strlen(fname) == 0))
134		return -1;
135
136	if( (pidfile = open(fname, O_RDONLY)) < 0)
137		return 0;
138
139	memset(buffer, 0, 64);
140
141	if(read(pidfile, buffer, 63))
142	{
143		if( (pid = atol(buffer)) > 0)
144		{
145			if(!kill(pid, 0))
146			{
147				close(pidfile);
148				return -2;
149			}
150		}
151	}
152
153	close(pidfile);
154
155	return 0;
156}
157
158