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/>.
25 #include <sys/socket.h>
38 static void usage(FILE *out)
40 fprintf(out, "usge: htpipe [-h] [-CS] SOCKET-PATH [CHILD ARGS...]\n");
43 static int clconnect(char *path)
46 struct sockaddr_un unm;
48 if((sk = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
50 memset(&unm, 0, sizeof(unm));
51 unm.sun_family = AF_UNIX;
52 strcpy(unm.sun_path, path);
53 if(connect(sk, (struct sockaddr *)&unm, sizeof(unm))) {
60 static int mklisten(char *path)
63 struct sockaddr_un unm;
66 if(!stat(path, &sb) && S_ISSOCK(sb.st_mode))
68 if((sk = socket(AF_UNIX, SOCK_SEQPACKET, 0)) < 0)
70 memset(&unm, 0, sizeof(unm));
71 unm.sun_family = AF_UNIX;
72 strcpy(unm.sun_path, path);
73 if(bind(sk, (struct sockaddr *)&unm, sizeof(unm)) || listen(sk, 128)) {
80 static void runclient(int sk)
86 if((fd = recvreq(0, &req)) < 0) {
89 flog(LOG_ERR, "htpipe: error in recvreq: %s", strerror(errno));
92 if(sendreq(sk, req, fd)) {
93 flog(LOG_ERR, "htpipe: could not pass request across pipe: %s", strerror(errno));
101 static void runserver(int lsk, int ch)
103 int i, o, ret, rfd, ncl, *cl, acl;
108 struct pollfd pfd[ncl + 1];
109 for(i = 0; i < ncl; i++) {
111 pfd[i].events= POLLIN;
114 pfd[i].events = POLLIN;
115 if((ret = poll(pfd, ncl + 1, -1)) < 0) {
117 flog(LOG_ERR, "htpipe: error in poll: %s", strerror(errno));
121 for(i = 0; i < ncl; i++) {
122 if(pfd[i].revents & POLLIN) {
123 if((rfd = recvreq(cl[i], &req)) < 0) {
125 flog(LOG_ERR, "htpipe: error from client: %s", strerror(errno));
128 if(sendreq(ch, req, rfd)) {
129 flog(LOG_ERR, "htpipe: could not pass request to child: %s", strerror(errno));
137 if(pfd[i].revents & POLLIN) {
138 if((acl = accept(lsk, NULL, 0)) < 0) {
139 flog(LOG_ERR, "htpipe: error in accept: %s", strerror(errno));
141 cl = srealloc(cl, sizeof(*cl) * (ncl + 1));
145 for(i = o = 0; i < ncl; i++) {
153 int main(int argc, char **argv)
155 int c, cli, srv, sk, ch, sst;
157 char *path, **chspec;
160 while((c = getopt(argc, argv, "+hCS")) >= 0) {
173 if(argc - optind < 1) {
177 path = argv[optind++];
178 chspec = argv + optind;
180 if((sk = clconnect(path)) < 0) {
181 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
190 if((sk = mklisten(path)) < 0) {
191 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
194 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
195 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
204 if((sk = clconnect(path)) < 0) {
205 if((sproc = fork()) < 0)
208 if((sk = mklisten(path)) < 0) {
209 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
212 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
213 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
220 if((waitpid(sproc, &sst, 0)) != sproc) {
221 flog(LOG_ERR, "htpipe: could not wait for server process: %s", strerror(errno));
224 if((sk = clconnect(path)) < 0) {
225 flog(LOG_ERR, "htpipe: could not connect to newly forked server: %s", strerror(errno));