1 /* 2 * Copyright (c) 2014 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 /* 35 * Support routines 36 */ 37 38 #include "svc.h" 39 40 void 41 sfree(char **strp) 42 { 43 if (*strp) 44 free(*strp); 45 } 46 47 void 48 sreplace(char **strp, const char *orig) 49 { 50 if (*strp) { 51 free(*strp); 52 *strp = NULL; 53 } 54 if (orig) 55 *strp = strdup(orig); 56 } 57 58 void 59 sdup(char **strp) 60 { 61 if (*strp) 62 *strp = strdup(*strp); 63 } 64 65 void 66 afree(char ***aryp) 67 { 68 char **ary = *aryp; 69 int i; 70 71 if (ary) { 72 for (i = 0; ary[i]; ++i) 73 free(ary[i]); 74 free(ary); 75 } 76 *aryp = NULL; 77 } 78 79 void 80 adup(char ***aryp) 81 { 82 char **ary = *aryp; 83 char **nary; 84 int i; 85 86 if (ary) { 87 for (i = 0; ary[i]; ++i) 88 ; 89 nary = calloc(sizeof(char *), i + 1); 90 bcopy(ary, nary, sizeof(char *) * (i + 1)); 91 for (i = 0; nary[i]; ++i) 92 nary[i] = strdup(nary[i]); 93 *aryp = nary; 94 } 95 } 96 97 /* 98 * Sets up the pidfile and unix domain socket. We do not yet know the 99 * pid to store in the pidfile. 100 */ 101 int 102 setup_pid_and_socket(command_t *cmd, int *lfdp, int *pfdp) 103 { 104 struct sockaddr_un sou; 105 size_t len; 106 char *pidfile; 107 108 /* 109 * Create and test the pidfile. 110 */ 111 asprintf(&pidfile, "%s/service.%s.pid", cmd->piddir, cmd->label); 112 *lfdp = -1; 113 *pfdp = open(pidfile, O_RDWR|O_CREAT|O_EXLOCK|O_NONBLOCK, 0640); 114 free(pidfile); 115 if (*pfdp < 0) { 116 if (errno == EWOULDBLOCK) { 117 fprintf(cmd->fp, "Cannot init, %s is already active\n", 118 cmd->label); 119 } else { 120 fprintf(cmd->fp, 121 "Cannot init, unable to create \"%s\": %s\n", 122 cmd->label, 123 strerror(errno)); 124 } 125 return 1; 126 } 127 ftruncate(*pfdp, 0); 128 129 /* 130 * Create the unix-domain socket. 131 */ 132 bzero(&sou, sizeof(sou)); 133 if ((*lfdp = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0) { 134 sou.sun_family = AF_UNIX; 135 snprintf(sou.sun_path, sizeof(sou.sun_path), 136 "%s/service.%s.sk", cmd->piddir, cmd->label); 137 len = strlen(sou.sun_path); 138 len = offsetof(struct sockaddr_un, sun_path[len+1]); 139 140 /* remove stale file before trying to bind */ 141 remove(sou.sun_path); 142 143 if (bind(*lfdp, (void *)&sou, len) < 0) { 144 fprintf(cmd->fp, "Unable to bind \"%s\"\n", 145 sou.sun_path); 146 close(*lfdp); 147 *lfdp = -1; 148 } else if (listen(*lfdp, 32) < 0) { 149 fprintf(cmd->fp, "Unable to listen on \"%s\"\n", 150 sou.sun_path); 151 close(*lfdp); 152 *lfdp = -1; 153 } 154 } else { 155 fprintf(cmd->fp, "Unable to create unix-domain socket\n"); 156 } 157 if (*lfdp >= 0) { 158 return 0; 159 } else { 160 close(*pfdp); 161 *pfdp = -1; 162 163 return 1; 164 } 165 } 166 167 void 168 remove_pid_and_socket(command_t *cmd, const char *label) 169 { 170 char *pidpath, *skpath; 171 172 asprintf(&pidpath, "%s/service.%s.pid", cmd->piddir, label); 173 remove(pidpath); 174 asprintf(&skpath, "%s/service.%s.sk", cmd->piddir, label); 175 remove(skpath); 176 177 free(pidpath); 178 free(skpath); 179 } 180