--- tiny.origin.c 2021-02-25 07:26:33.302592754 +0000
+++ tiny.13.c 2021-02-25 07:26:33.302592754 +0000
@@ -13,6 +13,17 @@
void clienterror(int fd, char *cause, char *errnum,
char *shortmsg, char *longmsg);
+// improved rio written
+void Im_rio_writen(int fd, void *usrbuf, size_t n) {
+ if (rio_writen(fd, usrbuf, n) != n) {
+ if (errno == EPIPE)
+ fprintf(stderr, "EPIPE error");
+
+ fprintf(stderr, "%s ", strerror(errno));
+ unix_error("client side has ended connection");
+ }
+}
+
int main(int argc, char **argv)
{
int listenfd, connfd;
@@ -26,6 +37,9 @@
exit(1);
}
+ if (Signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+ unix_error("mask signal pipe error");
+
listenfd = Open_listenfd(argv[1]);
while (1) {
clientlen = sizeof(clientaddr);
@@ -148,7 +162,7 @@
sprintf(buf, "%sConnection: close\r\n", buf);
sprintf(buf, "%sContent-length: %d\r\n", buf, filesize);
sprintf(buf, "%sContent-type: %s\r\n\r\n", buf, filetype);
- Rio_writen(fd, buf, strlen(buf)); //line:netp:servestatic:endserve
+ Im_rio_writen(fd, buf, strlen(buf)); //line:netp:servestatic:endserve
printf("Response headers:\n");
printf("%s", buf);
@@ -156,7 +170,7 @@
srcfd = Open(filename, O_RDONLY, 0); //line:netp:servestatic:open
srcp = Mmap(0, filesize, PROT_READ, MAP_PRIVATE, srcfd, 0);//line:netp:servestatic:mmap
Close(srcfd); //line:netp:servestatic:close
- Rio_writen(fd, srcp, filesize); //line:netp:servestatic:write
+ Im_rio_writen(fd, srcp, filesize); //line:netp:servestatic:write
Munmap(srcp, filesize); //line:netp:servestatic:munmap
}
@@ -186,11 +200,13 @@
/* Return first part of HTTP response */
sprintf(buf, "HTTP/1.0 200 OK\r\n");
- Rio_writen(fd, buf, strlen(buf));
+ Im_rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Server: Tiny Web Server\r\n");
- Rio_writen(fd, buf, strlen(buf));
+ Im_rio_writen(fd, buf, strlen(buf));
if (Fork() == 0) { /* Child */ //line:netp:servedynamic:fork
+ if (Signal(SIGPIPE, SIG_DFL) == SIG_ERR)
+ unix_error("unmask signal pipe error");
/* Real server would set all CGI vars here */
setenv("QUERY_STRING", cgiargs, 1); //line:netp:servedynamic:setenv
Dup2(fd, STDOUT_FILENO); /* Redirect stdout to client */ //line:netp:servedynamic:dup2
@@ -216,10 +232,10 @@
/* Print the HTTP response */
sprintf(buf, "HTTP/1.0 %s %s\r\n", errnum, shortmsg);
- Rio_writen(fd, buf, strlen(buf));
+ Im_rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-type: text/html\r\n");
- Rio_writen(fd, buf, strlen(buf));
+ Im_rio_writen(fd, buf, strlen(buf));
sprintf(buf, "Content-length: %d\r\n\r\n", (int)strlen(body));
- Rio_writen(fd, buf, strlen(buf));
- Rio_writen(fd, body, strlen(body));
+ Im_rio_writen(fd, buf, strlen(buf));
+ Im_rio_writen(fd, body, strlen(body));
}
ignore SIGPIPE and show more friendly errer message.
unmask SIGPIPE, leave child process to handle it.