2 ashd - A Sane HTTP Daemon
3 Copyright (C) 2008 Fredrik Tolf <fredrik@dolda2000.com>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include <sys/socket.h>
39 static void usage(FILE *out)
41 fprintf(out, "usge: htpipe [-h] [-CS] SOCKET-PATH [CHILD ARGS...]\n");
44 static int clconnect(char *path)
47 struct sockaddr_un unm;
49 if((sk = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
51 memset(&unm, 0, sizeof(unm));
52 unm.sun_family = AF_UNIX;
53 strcpy(unm.sun_path, path);
54 if(connect(sk, (struct sockaddr *)&unm, sizeof(unm))) {
61 static int mklisten(char *path)
64 struct sockaddr_un unm;
67 if(!stat(path, &sb) && S_ISSOCK(sb.st_mode))
69 if((sk = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
71 memset(&unm, 0, sizeof(unm));
72 unm.sun_family = AF_UNIX;
73 strcpy(unm.sun_path, path);
74 if(bind(sk, (struct sockaddr *)&unm, sizeof(unm)) || listen(sk, 128)) {
81 static void runclient(int sk)
87 if((fd = recvreq(0, &req)) < 0) {
90 flog(LOG_ERR, "htpipe: error in recvreq: %s", strerror(errno));
93 if(sendreq(sk, req, fd)) {
94 flog(LOG_ERR, "htpipe: could not pass request across pipe: %s", strerror(errno));
102 static void runserver(int lsk, int ch)
104 int i, o, ret, rfd, ncl, *cl, acl;
110 struct pollfd pfd[ncl + 1];
111 for(i = 0; i < ncl; i++) {
113 pfd[i].events= POLLIN;
116 pfd[i].events = POLLIN;
117 if((ret = poll(pfd, ncl + 1, -1)) < 0) {
119 flog(LOG_ERR, "htpipe: error in poll: %s", strerror(errno));
123 for(i = 0; i < ncl; i++) {
124 if(pfd[i].revents & POLLIN) {
125 if((rfd = recvreq(cl[i], &req)) < 0) {
127 flog(LOG_ERR, "htpipe: error from client: %s", strerror(errno));
131 if(sendreq(ch, req, rfd)) {
132 flog(LOG_ERR, "htpipe: could not pass request to child: %s", strerror(errno));
140 if(pfd[i].revents & POLLIN) {
141 if((acl = accept(lsk, NULL, 0)) < 0) {
142 flog(LOG_ERR, "htpipe: error in accept: %s", strerror(errno));
144 cl = srealloc(cl, sizeof(*cl) * (ncl + 1));
148 for(i = o = 0; i < ncl; i++) {
156 int main(int argc, char **argv)
158 int c, cli, srv, sk, ch, sst;
160 char *path, **chspec;
163 while((c = getopt(argc, argv, "+hCS")) >= 0) {
176 if(argc - optind < 1) {
180 path = argv[optind++];
181 chspec = argv + optind;
183 if((sk = clconnect(path)) < 0) {
184 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
193 if((sk = mklisten(path)) < 0) {
194 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
197 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
198 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
207 if((sk = clconnect(path)) < 0) {
208 if((sproc = fork()) < 0)
211 if((sk = mklisten(path)) < 0) {
212 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
215 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
216 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
223 if((waitpid(sproc, &sst, 0)) != sproc) {
224 flog(LOG_ERR, "htpipe: could not wait for server process: %s", strerror(errno));
227 if((sk = clconnect(path)) < 0) {
228 flog(LOG_ERR, "htpipe: could not connect to newly forked server: %s", strerror(errno));