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 #include <sys/types.h> 363e2ea4ccSMatthew Dillon #include <sys/param.h> 373e2ea4ccSMatthew Dillon #include <sys/procctl.h> 383e2ea4ccSMatthew Dillon #include <sys/stat.h> 393e2ea4ccSMatthew Dillon #include <sys/time.h> 403e2ea4ccSMatthew Dillon #include <sys/socket.h> 413e2ea4ccSMatthew Dillon #include <sys/wait.h> 423e2ea4ccSMatthew Dillon #include <sys/un.h> 433c0c8010SSascha Wildner #include <sys/ttycom.h> 4421537d46SMatthew Dillon #include <sys/devfs.h> 4521537d46SMatthew Dillon #include <sys/mount.h> 4621537d46SMatthew Dillon #include <sys/jail.h> 47*2c3b1d1bSSascha Wildner #include <fcntl.h> 483e2ea4ccSMatthew Dillon #include <stdio.h> 493e2ea4ccSMatthew Dillon #include <stdarg.h> 503e2ea4ccSMatthew Dillon #include <stdlib.h> 513e2ea4ccSMatthew Dillon #include <stddef.h> 523e2ea4ccSMatthew Dillon #include <unistd.h> 533e2ea4ccSMatthew Dillon #include <string.h> 543e2ea4ccSMatthew Dillon #include <signal.h> 553e2ea4ccSMatthew Dillon #include <dirent.h> 563e2ea4ccSMatthew Dillon #include <assert.h> 573e2ea4ccSMatthew Dillon #include <errno.h> 583e2ea4ccSMatthew Dillon #include <ctype.h> 593e2ea4ccSMatthew Dillon #include <pwd.h> 603e2ea4ccSMatthew Dillon #include <grp.h> 613e2ea4ccSMatthew Dillon #include <pthread.h> 623e2ea4ccSMatthew Dillon 633e2ea4ccSMatthew Dillon typedef struct SvcCommand { 643e2ea4ccSMatthew Dillon int mountdev : 1; 653e2ea4ccSMatthew Dillon int cmdline : 1; 663e2ea4ccSMatthew Dillon int foreground : 1; 673e2ea4ccSMatthew Dillon int restart_some : 1; 683e2ea4ccSMatthew Dillon int restart_all : 1; 693e2ea4ccSMatthew Dillon int exit_mode : 1; 703e2ea4ccSMatthew Dillon int sync_mode : 1; 7182f39527SMatthew Dillon int tail_mode : 3; 723e2ea4ccSMatthew Dillon int jail_clean : 1; 7321537d46SMatthew Dillon int uid_mode : 1; 7421537d46SMatthew Dillon int gid_mode : 1; 753e2ea4ccSMatthew Dillon int manual_stop : 1; 76ee6361d4SMatthew Dillon int empty_label : 1; /* label not specified (vs 'all') */ 773e2ea4ccSMatthew Dillon int commanded : 1; /* command by system operator */ 78ee6361d4SMatthew Dillon int force_remove_files : 1; 7982f39527SMatthew Dillon FILE *fp; /* nominal output */ 803e2ea4ccSMatthew Dillon char *piddir; 813e2ea4ccSMatthew Dillon char *rootdir; 823e2ea4ccSMatthew Dillon char *jaildir; 833e2ea4ccSMatthew Dillon char *logfile; 843e2ea4ccSMatthew Dillon char *proctitle; 853e2ea4ccSMatthew Dillon char *directive; 863e2ea4ccSMatthew Dillon char *label; 873e2ea4ccSMatthew Dillon char **ext_av; 883e2ea4ccSMatthew Dillon int ext_ac; 893e2ea4ccSMatthew Dillon char **orig_av; 903e2ea4ccSMatthew Dillon int orig_ac; 913e2ea4ccSMatthew Dillon int restart_timo; 923e2ea4ccSMatthew Dillon int termkill_timo; 933e2ea4ccSMatthew Dillon int debug; 943e2ea4ccSMatthew Dillon int restart_per; 953e2ea4ccSMatthew Dillon int restart_count; 963e2ea4ccSMatthew Dillon struct passwd pwent; 973e2ea4ccSMatthew Dillon struct group grent; 983e2ea4ccSMatthew Dillon gid_t groups[NGROUPS]; 993e2ea4ccSMatthew Dillon int ngroups; 10082f39527SMatthew Dillon 10182f39527SMatthew Dillon pthread_cond_t logcond; /* wait for activity */ 10282f39527SMatthew Dillon char logbuf[8192]; /* must be power of 2 >= 2048 */ 10382f39527SMatthew Dillon int logwindex; 10482f39527SMatthew Dillon int logcount; 10582f39527SMatthew Dillon int logfds[2]; /* logfile pipe descriptors */ 10682f39527SMatthew Dillon int logfd; /* logfile file descriptor */ 1073e2ea4ccSMatthew Dillon } command_t; 1083e2ea4ccSMatthew Dillon 1093e2ea4ccSMatthew Dillon typedef enum { 1103e2ea4ccSMatthew Dillon RS_STOPPED, /* service died or stopped */ 1113e2ea4ccSMatthew Dillon RS_STARTED, /* service running */ 1123e2ea4ccSMatthew Dillon RS_STOPPING1, /* fresh pid to stop */ 1133e2ea4ccSMatthew Dillon RS_STOPPING2, /* TERM sent */ 1143e2ea4ccSMatthew Dillon RS_STOPPING3, /* KILL sent */ 1153e2ea4ccSMatthew Dillon } runstate_t; 1163e2ea4ccSMatthew Dillon 11782f39527SMatthew Dillon #define LOGCHUNK 1024 11882f39527SMatthew Dillon 1193e2ea4ccSMatthew Dillon extern pthread_mutex_t serial_mtx; 1203e2ea4ccSMatthew Dillon 1213e2ea4ccSMatthew Dillon int process_cmd(command_t *cmd, FILE *fp, int ac, char **av); 1223e2ea4ccSMatthew Dillon int execute_cmd(command_t *cmd); 1233e2ea4ccSMatthew Dillon void free_cmd(command_t *cmd); 1243e2ea4ccSMatthew Dillon 1253e2ea4ccSMatthew Dillon void sfree(char **strp); 1263e2ea4ccSMatthew Dillon void sreplace(char **strp, const char *orig); 1273e2ea4ccSMatthew Dillon void sdup(char **strp); 1283e2ea4ccSMatthew Dillon void afree(char ***aryp); 1293e2ea4ccSMatthew Dillon void adup(char ***aryp); 1303e2ea4ccSMatthew Dillon int setup_pid_and_socket(command_t *cmd, int *lfdp, int *pfdp); 131ee6361d4SMatthew Dillon void remove_pid_and_socket(command_t *cmd, const char *label); 1323e2ea4ccSMatthew Dillon 1333e2ea4ccSMatthew Dillon void remote_execute(command_t *cmd, const char *label); 1343e2ea4ccSMatthew Dillon void remote_listener(command_t *cmd, int lfd); 1353e2ea4ccSMatthew Dillon int remote_wait(void); 1363e2ea4ccSMatthew Dillon 1373e2ea4ccSMatthew Dillon int execute_init(command_t *cmd); 1383e2ea4ccSMatthew Dillon int execute_start(command_t *cmd); 1393e2ea4ccSMatthew Dillon int execute_stop(command_t *cmd); 1403e2ea4ccSMatthew Dillon int execute_restart(command_t *cmd); 1413e2ea4ccSMatthew Dillon int execute_exit(command_t *cmd); 1423e2ea4ccSMatthew Dillon int execute_list(command_t *cmd); 1433e2ea4ccSMatthew Dillon int execute_status(command_t *cmd); 1443e2ea4ccSMatthew Dillon int execute_log(command_t *cmd); 1453e2ea4ccSMatthew Dillon int execute_logfile(command_t *cmd); 146ee6361d4SMatthew Dillon int execute_help(command_t *cmd); 147