* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
+#ifdef __linux__
+# define _XOPEN_SOURCE 500 /* needed for pwrite */
+#endif
+
#include <sys/types.h>
#include <sys/select.h>
#include <sys/time.h>
#include <arpa/inet.h>
#ifdef __linux__
-#include <netinet/ether.h>
+# include <netinet/ether.h>
#endif
#include <errno.h>
#include <fcntl.h>
#include "config.h"
#include "common.h"
#ifdef ENABLE_ARP
-#include "arp.h"
+# include "arp.h"
#endif
#include "client.h"
#include "configure.h"
#include "dhcp.h"
#include "dhcpcd.h"
#ifdef ENABLE_INFO
-#include "info.h"
+# include "info.h"
#endif
#include "interface.h"
#include "logger.h"
memset (dhcp, 0, sizeof (dhcp_t)); \
}
-static int daemonise (const char *pidfile)
+static bool daemonise (int *pidfd)
{
+ char pid[16];
+
logger (LOG_DEBUG, "forking to background");
if (daemon (0, 0) < 0) {
logger (LOG_ERR, "daemon: %s", strerror (errno));
- return -1;
+ return (false);
}
- make_pid (pidfile);
+ if (ftruncate (*pidfd, 0) == -1) {
+ logger (LOG_ERR, "ftruncate: %s", strerror (errno));
+ return (false);
+ }
+
+ snprintf (pid, sizeof (pid), "%u", getpid());
+ if (pwrite (*pidfd, pid, strlen(pid), 0) != (ssize_t) strlen (pid)) {
+ logger (LOG_ERR, "pwrite: %s", strerror (errno));
+ return (false);
+ }
+
+ close (*pidfd);
+ *pidfd = -1;
- return 0;
+ return (true);
}
static unsigned long random_xid (void)
/* This state machine is based on the one from udhcpc
written by Russ Dill */
-int dhcp_run (const options_t *options)
+int dhcp_run (const options_t *options, int *pidfd)
{
interface_t *iface;
int mode = SOCKET_CLOSED;
iface->start_uptime = uptime ();
if (! daemonised && options->daemonise) {
- if ((daemonise (options->pidfile)) < 0) {
+ if ((daemonise (pidfd)) < 0) {
retval = -1;
goto eexit;
}
}
if (! daemonised && options->daemonise) {
- if ((daemonise (options->pidfile)) < 0 ) {
+ if ((daemonise (pidfd)) < 0 ) {
retval = EXIT_FAILURE;
goto eexit;
}
#define _POSIX_SOURCE
#endif
+#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
return pid;
}
-void make_pid (const char *pidfile)
-{
- FILE *fp;
-
- if ((fp = fopen (pidfile, "w")) == NULL) {
- logger (LOG_ERR, "fopen `%s': %s", pidfile, strerror (errno));
- return;
- }
-
- fprintf (fp, "%u\n", getpid ());
- fclose (fp);
-}
-
static void usage ()
{
printf ("usage: "PACKAGE" [-adknpEGHMNRSY] [-c script] [-h hostame] [-i classID]\n"
pid_t pid;
int debug = 0;
int i;
+ int pidfd;
const struct option longopts[] = {
{"arp", no_argument, NULL, 'a'},
exit (EXIT_FAILURE);
}
- make_pid (options.pidfile);
+ pidfd = open (options.pidfile,
+ O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0660);
+ if (pidfd == -1) {
+ logger (LOG_ERR, "open `%s': %s", options.pidfile, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
+
+ /* Lock the file so that only one instance of dhcpcd runs on an interface */
+ if (flock (pidfd, LOCK_EX | LOCK_NB) == -1) {
+ logger (LOG_ERR, "flock `%s': %s", options.pidfile, strerror (errno));
+ exit (EXIT_FAILURE);
+ }
logger (LOG_INFO, PACKAGE " " VERSION " starting");
- if (dhcp_run (&options)) {
+ if (dhcp_run (&options, &pidfd)) {
+ if (pidfd > -1)
+ close (pidfd);
unlink (options.pidfile);
exit (EXIT_FAILURE);
}