/* * websend - synthesize a Web retrieval header for a file, and send it * and the file to stdout (eg, for use with nc -cmd). * * websend content-type file-name * * The file-name is assumed to already have any necessary processing * (such as replacing \n with CRLF) performed. * * websend just synthesizes an HTTP header, including a Content-Length: * header giving the file size, with a Content-Type: header holding * the first argument, and spews it to stdout, followed by the file's * contents. It also supplies a Date: header giving the current time * in UTC, and a Last-Modified: header bearing the mtime from the * file. The rest of the header is fixed: * * HTTP/1.0 200 OK * Server: websend/1.0 */ #include #include #include #include #include #include #include #include extern const char *__progname; static const char *content_type; static const char *file_name; static int fd; static struct stat stb; static void header(void) { struct timeval tv; time_t tt; struct tm *tm; char buf[8192]; printf("HTTP/1.0 200 OK\r\n"); printf("Server: websend/1.0\r\n"); gettimeofday(&tv,0); tt = tv.tv_sec; tm = gmtime(&tt); strftime(&buf[0],sizeof(buf),"%a, %e %b %Y %T GMT",tm); printf("Date: %s\r\n",&buf[0]); tt = stb.st_mtime; tm = gmtime(&tt); strftime(&buf[0],sizeof(buf),"%a, %e %b %Y %T GMT",tm); printf("Last-Modified: %s\r\n",&buf[0]); printf("Content-Type: %s\r\n",content_type); printf("Content-Length: %llu\r\n",(unsigned long long int)stb.st_size); printf("\r\n"); } static void content(void) { off_t left; int n; int r; int wleft; int w; char *bp; char buf[8192]; left = stb.st_size; while (left > 0) { n = sizeof(buf); if (n > left) n = left; r = read(fd,&buf[0],n); if (r < 0) { fprintf(stderr,"%s: read from %s: %s\n",__progname,file_name,strerror(errno)); exit(1); } if (r == 0) { fprintf(stderr,"%s: premature EOF on %s (%llu left)\n",__progname,file_name,(unsigned long long int)left); exit(1); } left -= r; wleft = r; bp = &buf[0]; while (wleft > 0) { w = write(1,bp,wleft); if (w < 0) { fprintf(stderr,"%s: write error on stdout: %s\n",__progname,strerror(errno)); exit(1); } if (w == 0) { fprintf(stderr,"%s: zero write on stdout?\n",__progname); exit(1); } wleft -= w; bp += w; } } } int main(int, char **); int main(int ac, char **av) { if (ac != 3) { fprintf(stderr,"Usage: %s content-type file-name\n",__progname); exit(1); } content_type = av[1]; file_name = av[2]; fd = open(file_name,O_RDONLY,0); if (fd < 0) { fprintf(stderr,"%s: %s: %s\n",__progname,file_name,strerror(errno)); exit(1); } if (fstat(fd,&stb) < 0) { fprintf(stderr,"%s: fstat %s: %s\n",__progname,file_name,strerror(errno)); exit(1); } header(); fflush(stdout); content(); exit(0); }