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;
109 struct pollfd pfd[ncl + 1];
110 for(i = 0; i < ncl; i++) {
112 pfd[i].events= POLLIN;
115 pfd[i].events = POLLIN;
116 if((ret = poll(pfd, ncl + 1, -1)) < 0) {
118 flog(LOG_ERR, "htpipe: error in poll: %s", strerror(errno));
122 for(i = 0; i < ncl; i++) {
123 if(pfd[i].revents & POLLIN) {
124 if((rfd = recvreq(cl[i], &req)) < 0) {
126 flog(LOG_ERR, "htpipe: error from client: %s", strerror(errno));
130 if(sendreq(ch, req, rfd)) {
131 flog(LOG_ERR, "htpipe: could not pass request to child: %s", strerror(errno));
139 if(pfd[i].revents & POLLIN) {
140 if((acl = accept(lsk, NULL, 0)) < 0) {
141 flog(LOG_ERR, "htpipe: error in accept: %s", strerror(errno));
143 cl = srealloc(cl, sizeof(*cl) * (ncl + 1));
147 for(i = o = 0; i < ncl; i++) {
155 int main(int argc, char **argv)
157 int c, cli, srv, sk, ch, sst;
159 char *path, **chspec;
162 while((c = getopt(argc, argv, "+hCS")) >= 0) {
175 if(argc - optind < 1) {
179 path = argv[optind++];
180 chspec = argv + optind;
182 if((sk = clconnect(path)) < 0) {
183 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
192 if((sk = mklisten(path)) < 0) {
193 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
196 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
197 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
206 if((sk = clconnect(path)) < 0) {
207 if((sproc = fork()) < 0)
210 if((sk = mklisten(path)) < 0) {
211 flog(LOG_ERR, "htpipe: %s: %s", path, strerror(errno));
214 if((ch = stdmkchild(chspec, NULL, NULL)) < 0) {
215 flog(LOG_ERR, "htpipe: could not fork child: %s", strerror(errno));
222 if((waitpid(sproc, &sst, 0)) != sproc) {
223 flog(LOG_ERR, "htpipe: could not wait for server process: %s", strerror(errno));
226 if((sk = clconnect(path)) < 0) {
227 flog(LOG_ERR, "htpipe: could not connect to newly forked server: %s", strerror(errno));