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