source: branches/fc15-dev/server/common/oursrc/execsys/static-cat.c.pre @ 2040

Last change on this file since 2040 was 1464, checked in by mitchb, 15 years ago
What's that? I can't hear you over the static! o Make Apache, suEXEC, and static-cat case-insensitive about extensions o Add wav, mid, and midi as static extensions o Add missing mime-type for svg files
File size: 9.0 KB
Line 
1/*
2 * static-cat
3 * Copyright (C) 2006  Jeff Arnold <jbarnold@mit.edu>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
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.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 *
19 * See /COPYRIGHT in this repository for more information.
20 */
21
22#include <fcntl.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <time.h>
28
29// Map from extensions to content-types
30
31// START-AUTOGENERATED: DO NOT EDIT THIS SECTION, INCLUDING THIS LINE!
32// This section is populated by the script upd-execsys
33// END-AUTOGENERATED: DO NOT EDIT THIS SECTION, INCLUDING THIS LINE!
34
35// Start code from w3c's libwww library
36// (as obtained from http://www.w3.org/Library/src/HTWWWStr.html)
37
38char *months[12] = {
39        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
40        "Oct", "Nov", "Dec"
41};
42
43char *wkdays[7] = {
44        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
45};
46
47/*
48**      Returns a string pointer to a static area of the current calendar
49**      time in RFC 1123 format, for example
50**
51**              Sun, 06 Nov 1994 08:49:37 GMT
52**
53**      The result can be given in both local and GMT dependent on the flag
54*/
55const char *HTDateTimeStr(time_t * calendar, int local)
56{
57        static char buf[40];
58
59#ifdef HAVE_STRFTIME
60        if (local) {
61                /*
62                 ** Solaris 2.3 has a bug so we _must_ use reentrant version
63                 ** Thomas Maslen <tmaslen@verity.com>
64                 */
65#if defined(HT_REENTRANT) || defined(SOLARIS)
66                struct tm loctime;
67                localtime_r(calendar, &loctime);
68                strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", &loctime);
69#else
70                struct tm *loctime = localtime(calendar);
71                strftime(buf, 40, "%a, %d %b %Y %H:%M:%S", loctime);
72#endif                          /* SOLARIS || HT_REENTRANT */
73        } else {
74#if defined(HT_REENTRANT) || defined(SOLARIS)
75                struct tm gmt;
76                gmtime_r(calendar, &gmt);
77                strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", &gmt);
78#else
79                struct tm *gmt = gmtime(calendar);
80                strftime(buf, 40, "%a, %d %b %Y %H:%M:%S GMT", gmt);
81#endif                          /* SOLARIS || HT_REENTRANT */
82        }
83#else
84        if (local) {
85#if defined(HT_REENTRANT)
86                struct tm loctime;
87                localtime_r(calendar, &loctime);
88#else
89                struct tm *loctime = localtime(calendar);
90#endif                          /* HT_REENTRANT */
91                sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d",
92                        wkdays[loctime->tm_wday],
93                        loctime->tm_mday,
94                        months[loctime->tm_mon],
95                        loctime->tm_year + 1900,
96                        loctime->tm_hour, loctime->tm_min,
97                        loctime->tm_sec);
98        } else {
99#if defined(HT_REENTRANT) || defined(SOLARIS)
100                struct tm gmt;
101                gmtime_r(calendar, &gmt);
102#else
103                struct tm *gmt = gmtime(calendar);
104#endif
105                sprintf(buf, "%s, %02d %s %04d %02d:%02d:%02d GMT",
106                        wkdays[gmt->tm_wday],
107                        gmt->tm_mday,
108                        months[gmt->tm_mon],
109                        gmt->tm_year + 1900, gmt->tm_hour, gmt->tm_min,
110                        gmt->tm_sec);
111        }
112#endif
113        return buf;
114}
115
116// End code from w3c's libwww library
117
118// Start code from gnu
119// (as obtained from "apt-get source coreutils" on debian sarge)
120
121// JBA: included by safe_read.h, safe_write.h, full_read.h, and full_write.h
122#include <stddef.h>
123
124// JBA: included by safe_read.c and full_write.c
125#if HAVE_CONFIG_H
126# include <config.h>
127#endif
128
129// JBA: included by safe_read.c and full_write.c
130#include <errno.h>
131#ifndef errno
132extern int errno;
133#endif
134
135// Code from system.h:
136
137#ifndef STDOUT_FILENO
138# define STDOUT_FILENO 1
139#endif
140
141// Code from safe_read.h:
142
143#define SAFE_READ_ERROR ((size_t) -1)
144
145// Code from safe_write.h
146
147#define SAFE_WRITE_ERROR ((size_t) -1)
148
149// Code from safe_read.c
150
151/* Get ssize_t.  */
152#include <sys/types.h>
153#if HAVE_UNISTD_H
154# include <unistd.h>
155#endif
156
157#ifdef EINTR
158# define IS_EINTR(x) ((x) == EINTR)
159#else
160# define IS_EINTR(x) 0
161#endif
162
163#include <limits.h>
164
165/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
166   interrupted.  Return the actual number of bytes read(written), zero for EOF,
167   or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error.  */
168size_t safe_read(int fd, void *buf, size_t count)
169{
170        size_t result;
171
172        /* POSIX limits COUNT to SSIZE_MAX, but we limit it further, requiring
173           that COUNT <= INT_MAX, to avoid triggering a bug in Tru64 5.1.
174           When decreasing COUNT, keep the file pointer block-aligned.
175           Note that in any case, read(write) may succeed, yet read(write)
176           fewer than COUNT bytes, so the caller must be prepared to handle
177           partial results.  */
178        if (count > INT_MAX)
179                count = INT_MAX & ~8191;
180
181        do {
182                result = read(fd, buf, count);
183        }
184        while (result < 0 && IS_EINTR(errno));
185
186        return (size_t) result;
187}
188
189/* Read(write) up to COUNT bytes at BUF from(to) descriptor FD, retrying if
190   interrupted.  Return the actual number of bytes read(written), zero for EOF,
191   or SAFE_READ_ERROR(SAFE_WRITE_ERROR) upon error.  */
192size_t safe_write(int fd, const void *buf, size_t count)
193{
194        size_t result;
195
196        /* POSIX limits COUNT to SSIZE_MAX, but we limit it further, requiring
197           that COUNT <= INT_MAX, to avoid triggering a bug in Tru64 5.1.
198           When decreasing COUNT, keep the file pointer block-aligned.
199           Note that in any case, read(write) may succeed, yet read(write)
200           fewer than COUNT bytes, so the caller must be prepared to handle
201           partial results.  */
202        if (count > INT_MAX)
203                count = INT_MAX & ~8191;
204
205        do {
206                result = write(fd, buf, count);
207        }
208        while (result < 0 && IS_EINTR(errno));
209
210        return (size_t) result;
211}
212
213// Code from full_write.c
214
215/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
216   interrupted or if a partial write(read) occurs.  Return the number
217   of bytes transferred.
218   When writing, set errno if fewer than COUNT bytes are written.
219   When reading, if fewer than COUNT bytes are read, you must examine
220   errno to distinguish failure from EOF (errno == 0).  */
221size_t full_read(int fd, void *buf, size_t count)
222{
223        size_t total = 0;
224        char *ptr = buf;
225
226        while (count > 0) {
227                size_t n_rw = safe_read(fd, ptr, count);
228                if (n_rw == (size_t) - 1)
229                        break;
230                if (n_rw == 0) {
231                        errno = 0;
232                        break;
233                }
234                total += n_rw;
235                ptr += n_rw;
236                count -= n_rw;
237        }
238
239        return total;
240}
241
242/* Write(read) COUNT bytes at BUF to(from) descriptor FD, retrying if
243   interrupted or if a partial write(read) occurs.  Return the number
244   of bytes transferred.
245   When writing, set errno if fewer than COUNT bytes are written.
246   When reading, if fewer than COUNT bytes are read, you must examine
247   errno to distinguish failure from EOF (errno == 0).  */
248size_t full_write(int fd, const void *buf, size_t count)
249{
250        size_t total = 0;
251        const char *ptr = buf;
252
253        while (count > 0) {
254                size_t n_rw = safe_write(fd, ptr, count);
255                if (n_rw == (size_t) - 1)
256                        break;
257                if (n_rw == 0) {
258                        errno = ENOSPC;
259                        break;
260                }
261                total += n_rw;
262                ptr += n_rw;
263                count -= n_rw;
264        }
265
266        return total;
267}
268
269// Code from cat.c
270
271/* Nonzero if a non-fatal error has occurred.  */
272static int exit_status = 0;
273
274static int input_desc;
275
276/* Plain cat.  Copies the file behind `input_desc' to STDOUT_FILENO.  */
277
278static void simple_cat(
279                              /* Pointer to the buffer, used by reads and writes.  */
280                              char *buf,
281                              /* Number of characters preferably read or written by each read and write
282                                 call.  */
283                              int bufsize)
284{
285        /* Actual number of characters read, and therefore written.  */
286        size_t n_read;
287
288        /* Loop until the end of the file.  */
289
290        for (;;) {
291                /* Read a block of input.  */
292
293                n_read = safe_read(input_desc, buf, bufsize);
294                if (n_read == SAFE_READ_ERROR) {
295                        // JBA: simplified to "exit_status=1; return;"
296                        exit_status = 1;
297                        return;
298                }
299
300                /* End of this file?  */
301
302                if (n_read == 0)
303                        break;
304
305                /* Write this block out.  */
306
307                {
308                        /* The following is ok, since we know that 0 < n_read.  */
309                        size_t n = n_read;
310                        if (full_write(STDOUT_FILENO, buf, n) != n)
311                                exit(1);        // JBA: simplified to "exit(1);"
312                }
313        }
314}
315
316// End code from gnu
317
318int main(int argc, char **argv)
319{
320        input_desc = open(argv[1], O_RDONLY);
321        if (input_desc == -1) {
322                input_desc =
323                    open("/mit/scripts/www/403-404.html", O_RDONLY);
324                if (input_desc == -1)
325                        exit(0);
326                printf("Status: 404 Not Found\n");
327                printf("Content-type: text/html;\n\n");
328        } else {
329                int i, j;
330                const char *content_type = "application/octet-stream";
331                for (i = strlen(argv[1]) - 1; i > 0; i--) {
332                        if (argv[1][i - 1] == '.')
333                                break;
334                }
335                if (i == 0)
336                        exit(0);
337                for (j = 0; j < 2 * NEXTS; j += 2) {
338                        if (strcasecmp(map[j], &argv[1][i]) == 0) {
339                                content_type = map[j + 1];
340                        }
341                }
342
343                struct stat statbuf;
344                if (fstat(input_desc, &statbuf) == 0) {
345                        const char *dtstr =
346                            HTDateTimeStr(&statbuf.st_mtime, 0);
347                        printf("Last-Modified: %s\n", dtstr);
348                }
349                printf("Content-type: %s\n\n", content_type);
350        }
351        fflush(stdout);
352        char *buf = malloc(4096);
353        simple_cat(buf, 4096);
354        free(buf);
355        close(input_desc);
356        return exit_status;
357}
Note: See TracBrowser for help on using the repository browser.