xref: /dflybsd-src/sbin/svc/subs.c (revision e9609839a028f230ada915e386b809541ebefc85)
13e2ea4ccSMatthew Dillon /*
23e2ea4ccSMatthew Dillon  * Copyright (c) 2014 The DragonFly Project.  All rights reserved.
33e2ea4ccSMatthew Dillon  *
43e2ea4ccSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
53e2ea4ccSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
63e2ea4ccSMatthew Dillon  *
73e2ea4ccSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
83e2ea4ccSMatthew Dillon  * modification, are permitted provided that the following conditions
93e2ea4ccSMatthew Dillon  * are met:
103e2ea4ccSMatthew Dillon  *
113e2ea4ccSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
123e2ea4ccSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
133e2ea4ccSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
143e2ea4ccSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
153e2ea4ccSMatthew Dillon  *    the documentation and/or other materials provided with the
163e2ea4ccSMatthew Dillon  *    distribution.
173e2ea4ccSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
183e2ea4ccSMatthew Dillon  *    contributors may be used to endorse or promote products derived
193e2ea4ccSMatthew Dillon  *    from this software without specific, prior written permission.
203e2ea4ccSMatthew Dillon  *
213e2ea4ccSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
223e2ea4ccSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
233e2ea4ccSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
243e2ea4ccSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
253e2ea4ccSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
263e2ea4ccSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
273e2ea4ccSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
283e2ea4ccSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
293e2ea4ccSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
303e2ea4ccSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
313e2ea4ccSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
323e2ea4ccSMatthew Dillon  * SUCH DAMAGE.
333e2ea4ccSMatthew Dillon  */
343e2ea4ccSMatthew Dillon /*
353e2ea4ccSMatthew Dillon  * Support routines
363e2ea4ccSMatthew Dillon  */
373e2ea4ccSMatthew Dillon 
383e2ea4ccSMatthew Dillon #include "svc.h"
393e2ea4ccSMatthew Dillon 
403e2ea4ccSMatthew Dillon void
sfree(char ** strp)413e2ea4ccSMatthew Dillon sfree(char **strp)
423e2ea4ccSMatthew Dillon {
433e2ea4ccSMatthew Dillon 	if (*strp)
443e2ea4ccSMatthew Dillon 		free(*strp);
453e2ea4ccSMatthew Dillon }
463e2ea4ccSMatthew Dillon 
473e2ea4ccSMatthew Dillon void
sreplace(char ** strp,const char * orig)483e2ea4ccSMatthew Dillon sreplace(char **strp, const char *orig)
493e2ea4ccSMatthew Dillon {
503e2ea4ccSMatthew Dillon 	if (*strp) {
513e2ea4ccSMatthew Dillon 		free(*strp);
523e2ea4ccSMatthew Dillon 		*strp = NULL;
533e2ea4ccSMatthew Dillon 	}
543e2ea4ccSMatthew Dillon 	if (orig)
553e2ea4ccSMatthew Dillon 		*strp = strdup(orig);
563e2ea4ccSMatthew Dillon }
573e2ea4ccSMatthew Dillon 
583e2ea4ccSMatthew Dillon void
sdup(char ** strp)593e2ea4ccSMatthew Dillon sdup(char **strp)
603e2ea4ccSMatthew Dillon {
613e2ea4ccSMatthew Dillon 	if (*strp)
623e2ea4ccSMatthew Dillon 		*strp = strdup(*strp);
633e2ea4ccSMatthew Dillon }
643e2ea4ccSMatthew Dillon 
653e2ea4ccSMatthew Dillon void
afree(char *** aryp)663e2ea4ccSMatthew Dillon afree(char ***aryp)
673e2ea4ccSMatthew Dillon {
683e2ea4ccSMatthew Dillon 	char **ary = *aryp;
693e2ea4ccSMatthew Dillon 	int i;
703e2ea4ccSMatthew Dillon 
713e2ea4ccSMatthew Dillon 	if (ary) {
723e2ea4ccSMatthew Dillon 		for (i = 0; ary[i]; ++i)
733e2ea4ccSMatthew Dillon 			free(ary[i]);
743e2ea4ccSMatthew Dillon 		free(ary);
753e2ea4ccSMatthew Dillon 	}
763e2ea4ccSMatthew Dillon 	*aryp = NULL;
773e2ea4ccSMatthew Dillon }
783e2ea4ccSMatthew Dillon 
793e2ea4ccSMatthew Dillon void
adup(char *** aryp)803e2ea4ccSMatthew Dillon adup(char ***aryp)
813e2ea4ccSMatthew Dillon {
823e2ea4ccSMatthew Dillon 	char **ary = *aryp;
833e2ea4ccSMatthew Dillon 	char **nary;
843e2ea4ccSMatthew Dillon 	int i;
853e2ea4ccSMatthew Dillon 
863e2ea4ccSMatthew Dillon 	if (ary) {
873e2ea4ccSMatthew Dillon 		for (i = 0; ary[i]; ++i)
883e2ea4ccSMatthew Dillon 			;
893e2ea4ccSMatthew Dillon 		nary = calloc(sizeof(char *), i + 1);
903e2ea4ccSMatthew Dillon 		bcopy(ary, nary, sizeof(char *) * (i + 1));
913e2ea4ccSMatthew Dillon 		for (i = 0; nary[i]; ++i)
923e2ea4ccSMatthew Dillon 			nary[i] = strdup(nary[i]);
933e2ea4ccSMatthew Dillon 		*aryp = nary;
943e2ea4ccSMatthew Dillon 	}
953e2ea4ccSMatthew Dillon }
963e2ea4ccSMatthew Dillon 
973e2ea4ccSMatthew Dillon /*
983e2ea4ccSMatthew Dillon  * Sets up the pidfile and unix domain socket.  We do not yet know the
993e2ea4ccSMatthew Dillon  * pid to store in the pidfile.
1003e2ea4ccSMatthew Dillon  */
1013e2ea4ccSMatthew Dillon int
setup_pid_and_socket(command_t * cmd,int * lfdp,int * pfdp)1023e2ea4ccSMatthew Dillon setup_pid_and_socket(command_t *cmd, int *lfdp, int *pfdp)
1033e2ea4ccSMatthew Dillon {
1043e2ea4ccSMatthew Dillon 	struct sockaddr_un sou;
1053e2ea4ccSMatthew Dillon 	size_t len;
1063e2ea4ccSMatthew Dillon 	char *pidfile;
1073e2ea4ccSMatthew Dillon 
1083e2ea4ccSMatthew Dillon 	/*
1093e2ea4ccSMatthew Dillon 	 * Create and test the pidfile.
1103e2ea4ccSMatthew Dillon 	 */
1113e2ea4ccSMatthew Dillon 	asprintf(&pidfile, "%s/service.%s.pid", cmd->piddir, cmd->label);
1123e2ea4ccSMatthew Dillon 	*lfdp = -1;
11382f39527SMatthew Dillon 	*pfdp = open(pidfile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0640);
114*e9609839SAntonio Huete Jimenez 	free(pidfile);
1153e2ea4ccSMatthew Dillon 	if (*pfdp < 0) {
1163e2ea4ccSMatthew Dillon 		if (errno == EWOULDBLOCK) {
1173e2ea4ccSMatthew Dillon 			fprintf(cmd->fp, "Cannot init, %s is already active\n",
1183e2ea4ccSMatthew Dillon 				cmd->label);
1193e2ea4ccSMatthew Dillon 		} else {
1203e2ea4ccSMatthew Dillon 			fprintf(cmd->fp,
1213e2ea4ccSMatthew Dillon 				"Cannot init, unable to create \"%s\": %s\n",
1223e2ea4ccSMatthew Dillon 				cmd->label,
1233e2ea4ccSMatthew Dillon 				strerror(errno));
1243e2ea4ccSMatthew Dillon 		}
1253e2ea4ccSMatthew Dillon 		return 1;
1263e2ea4ccSMatthew Dillon 	}
1273e2ea4ccSMatthew Dillon 	ftruncate(*pfdp, 0);
1283e2ea4ccSMatthew Dillon 
1293e2ea4ccSMatthew Dillon 	/*
1303e2ea4ccSMatthew Dillon 	 * Create the unix-domain socket.
1313e2ea4ccSMatthew Dillon 	 */
1323e2ea4ccSMatthew Dillon 	bzero(&sou, sizeof(sou));
1333e2ea4ccSMatthew Dillon 	if ((*lfdp = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) {
1343e2ea4ccSMatthew Dillon 		sou.sun_family = AF_UNIX;
1353e2ea4ccSMatthew Dillon 		snprintf(sou.sun_path, sizeof(sou.sun_path),
1363e2ea4ccSMatthew Dillon 			 "%s/service.%s.sk", cmd->piddir, cmd->label);
1373e2ea4ccSMatthew Dillon 		len = strlen(sou.sun_path);
1383e2ea4ccSMatthew Dillon 		len = offsetof(struct sockaddr_un, sun_path[len+1]);
1393e2ea4ccSMatthew Dillon 
1403e2ea4ccSMatthew Dillon 		/* remove stale file before trying to bind */
1413e2ea4ccSMatthew Dillon 		remove(sou.sun_path);
1423e2ea4ccSMatthew Dillon 
1433e2ea4ccSMatthew Dillon 		if (bind(*lfdp, (void *)&sou, len) < 0) {
1443e2ea4ccSMatthew Dillon 			fprintf(cmd->fp, "Unable to bind \"%s\"\n",
1453e2ea4ccSMatthew Dillon 				sou.sun_path);
1463e2ea4ccSMatthew Dillon 			close(*lfdp);
1473e2ea4ccSMatthew Dillon 			*lfdp = -1;
1483e2ea4ccSMatthew Dillon 		} else if (listen(*lfdp, 32) < 0) {
1493e2ea4ccSMatthew Dillon 			fprintf(cmd->fp, "Unable to listen on \"%s\"\n",
1503e2ea4ccSMatthew Dillon 				sou.sun_path);
1513e2ea4ccSMatthew Dillon 			close(*lfdp);
1523e2ea4ccSMatthew Dillon 			*lfdp = -1;
1533e2ea4ccSMatthew Dillon 		}
1543e2ea4ccSMatthew Dillon 	} else {
1553e2ea4ccSMatthew Dillon 		fprintf(cmd->fp, "Unable to create unix-domain socket\n");
1563e2ea4ccSMatthew Dillon 	}
1573e2ea4ccSMatthew Dillon 	if (*lfdp >= 0) {
1583e2ea4ccSMatthew Dillon 		return 0;
1593e2ea4ccSMatthew Dillon 	} else {
1603e2ea4ccSMatthew Dillon 		close(*pfdp);
1613e2ea4ccSMatthew Dillon 		*pfdp = -1;
1623e2ea4ccSMatthew Dillon 
1633e2ea4ccSMatthew Dillon 		return 1;
1643e2ea4ccSMatthew Dillon 	}
1653e2ea4ccSMatthew Dillon }
166ee6361d4SMatthew Dillon 
167ee6361d4SMatthew Dillon void
remove_pid_and_socket(command_t * cmd,const char * label)168ee6361d4SMatthew Dillon remove_pid_and_socket(command_t *cmd, const char *label)
169ee6361d4SMatthew Dillon {
170*e9609839SAntonio Huete Jimenez 	char *pidpath, *skpath;
171ee6361d4SMatthew Dillon 
172*e9609839SAntonio Huete Jimenez 	asprintf(&pidpath, "%s/service.%s.pid", cmd->piddir, label);
173*e9609839SAntonio Huete Jimenez 	remove(pidpath);
174*e9609839SAntonio Huete Jimenez 	asprintf(&skpath, "%s/service.%s.sk", cmd->piddir, label);
175*e9609839SAntonio Huete Jimenez 	remove(skpath);
176*e9609839SAntonio Huete Jimenez 
177*e9609839SAntonio Huete Jimenez 	free(pidpath);
178*e9609839SAntonio Huete Jimenez 	free(skpath);
179ee6361d4SMatthew Dillon }
180