main.c (3160B)
1 /* 2 * Copyright 2021-2023 Jacob R. Edwards 3 * 4 * ap -- audio player 5 * 6 * This program is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <https://www.gnu.org/licenses/>. 18 */ 19 20 #include <sys/socket.h> 21 #include <sys/wait.h> 22 23 #include <errno.h> 24 #include <limits.h> 25 #include <poll.h> 26 #include <regex.h> 27 #include <signal.h> 28 #include <stdio.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <unistd.h> 32 33 #include "aps.h" 34 #include "command.h" 35 #include "find.h" 36 #include "log.h" 37 #include "queue.h" 38 #include "util.h" 39 40 #include "config.h" 41 42 static struct aps *aps; 43 44 void 45 die(char *s) 46 { 47 aps_log(NULL, 0, FATAL, NULL, "%s: %s", s, errstr); 48 if (aps) 49 unlink(aps->con->path); 50 exit(1); 51 } 52 53 void 54 sigclose(int sig) 55 { 56 aps_log(aps, 0, FATAL, NULL, "close signal"); 57 aps->close = 1; 58 } 59 60 void 61 sigchld(int sig) 62 { 63 int status; 64 pid_t pid; 65 66 while ((pid = 67 waitpid(-1, &status, WCONTINUED | WNOHANG | WUNTRACED)) > 0) { 68 if (pid == aps->player->pid) { 69 aps_log(aps, 0, INFO, logsubjects[LogPlayer], "player status available"); 70 pupdate(aps->player, status); 71 } 72 } 73 } 74 75 void 76 sigint(int sig) 77 { 78 } 79 80 int 81 configure(struct aps *aps, char **argv) 82 { 83 int status; 84 pid_t pid; 85 86 pid = fork(); 87 if (pid < 0) 88 die("unable to fork"); 89 90 if (pid == 0) { 91 *argv = "apsrc"; 92 execvp("apc", argv); 93 perror("unable to execute apc"); 94 _exit(1); 95 } 96 97 if (aps_update(aps)) 98 return 1; 99 100 while (!aps->close && aps->nfds > 0) { 101 if (aps_update(aps) && errno != EINTR) 102 return 1; 103 } 104 105 if (waitpid(pid, &status, 0) < 0) 106 return 1; 107 return WIFEXITED(status) ? WEXITSTATUS(status) : 1; 108 } 109 110 int 111 run(struct aps *aps) 112 { 113 while (!aps->close) { 114 if (aps->queue) { 115 if (aps->player->state == COMPLETE) 116 queue_set(aps, aps->queue->next); 117 if (aps->player->state == OFF) 118 pplay(aps->player, aps->queue->path); 119 } 120 if (aps_update(aps) && errno != EINTR) 121 return 1; 122 } 123 return 0; 124 } 125 126 int 127 main(int argc, char *argv[]) 128 { 129 int error; 130 131 #ifdef __OpenBSD__ 132 if (pledge("stdio rpath cpath proc exec unix", NULL)) 133 die("pledge"); 134 #endif 135 136 openlog("aps", LOG_PID, LOG_DAEMON); 137 138 aps = aps_open(name, player); 139 if (aps == NULL) 140 die("unable to setup server"); 141 142 aps->logmask = logmask(ERROR); 143 144 aps->coms = commands; 145 aps->ncoms = LEN(commands); 146 147 signal(SIGHUP, SIG_IGN); 148 signal(SIGINT, sigint); 149 signal(SIGQUIT, sigclose); 150 signal(SIGTERM, sigclose); 151 152 if (configure(aps, argv)) 153 die("unable to re-configure"); 154 155 signal(SIGCHLD, sigchld); 156 157 error = fork(); 158 if (error == -1) 159 die("unable to fork"); 160 else if (error > 0) 161 return 0; 162 163 error = run(aps); 164 if (error == 0) 165 error = aps->close; 166 167 aps_close(aps); 168 closelog(); 169 170 return error; 171 }