martin 98/01/26 08:46:20
Modified: . STATUS src README.EBCDIC src/main buff.c buff.h http_bprintf.c http_core.c http_protocol.c src/modules/standard mod_cgi.c mod_include.c src/os/bs2000 ebcdic.c os.c os.h Log: Fix CGI-Execution for EBCDIC hosts. Revision Changes Path 1.129 +1 -0 apachen/STATUS Index: STATUS =================================================================== RCS file: /home/cvs/apachen/STATUS,v retrieving revision 1.128 retrieving revision 1.129 diff -u -u -r1.128 -r1.129 --- STATUS 1998/01/25 18:41:51 1.128 +++ STATUS 1998/01/26 16:46:05 1.129 @@ -134,6 +134,7 @@ (enable with #define NEED_HASHBANG_EMUL) * more mod_mime_magic cleanup * Add more compile time diagnosis to main's -V switch + * [Port] Fix CGI-Execution for EBCDIC hosts. Available Patches: 1.2 +11 -7 apachen/src/README.EBCDIC Index: README.EBCDIC =================================================================== RCS file: /home/cvs/apachen/src/README.EBCDIC,v retrieving revision 1.1 retrieving revision 1.2 diff -u -u -r1.1 -r1.2 --- README.EBCDIC 1998/01/13 23:11:04 1.1 +++ README.EBCDIC 1998/01/26 16:46:06 1.2 @@ -58,17 +58,22 @@ AddType text/x-ascii-html .ahtml AddType text/x-ascii-plain .ascii Similarly, any text/XXXX MIME type can be served as "raw ASCII" by - configuring a MIME text/x-ascii-XXXX for it. + configuring a MIME type "text/x-ascii-XXXX" for it using AddType. * Non-text documents are always served "binary" without conversion. This seems to be the most sensible choice for, .e.g., GIF/ZIP/AU - file types. + file types. This of course requires the user to copy them to the + mainframe host using the "rcp -b" binary switch. * Server parsed files are always assumed to be in native (i.e., EBCDIC) format as used on the machine, and are converted after processing. -* +* For CGI output, the CGI script determines whether a conversion is + needed or not: by setting the appropriate Content-Type, text files + can be converted, or GIF output can be passed through unmodified. + An example for the latter case is the wwwcount program which we ported + as well. What works: - In the following list, @@ -87,7 +92,7 @@ mod_auth_dbm.c - / no libdbm mod_autoindex.c + mod_cern_meta.c ? - mod_cgi.c - / exec of scripts via #! doesn't work + mod_cgi.c + mod_digest.c - / MD5 not ported yet mod_dir.c + mod_dld.c - / no shared libs @@ -96,7 +101,7 @@ mod_expires.c + mod_headers.c + mod_imap.c + - mod_include.c + / only <!--#exec cgi= doesn't work (see mod_cgi). + mod_include.c + mod_info.c + / some flaws mod_log_agent.c + mod_log_config.c + @@ -118,6 +123,5 @@ What doesn't work yet: - no DBM or DB authentication (library missing) - no MD5 hash or digest (not ported yet) -- no execution of #! scripts (needs porting) - Martin Kraemer, 22-Dec-1997 + Martin Kraemer, 25-Jan-1998 1.59 +63 -60 apachen/src/main/buff.c Index: buff.c =================================================================== RCS file: /home/cvs/apachen/src/main/buff.c,v retrieving revision 1.58 retrieving revision 1.59 diff -u -u -r1.58 -r1.59 --- buff.c 1998/01/22 21:00:06 1.58 +++ buff.c 1998/01/26 16:46:07 1.59 @@ -283,6 +283,10 @@ else fb->outbase = NULL; +#ifdef CHARSET_EBCDIC + fb->flags |= (flags & B_SOCKET) ? (B_EBCDIC2ASCII | B_ASCII2EBCDIC) : 0; +#endif /*CHARSET_EBCDIC*/ + fb->inptr = fb->inbase; fb->incnt = 0; @@ -370,7 +374,12 @@ bflush(fb); } /* assume there's enough space now */ +#ifdef CHARSET_EBCDIC + /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */ + ebcdic2ascii(&fb->outbase[fb->outcnt], chunksize, chunk_header_size); +#else /*CHARSET_EBCDIC*/ memcpy(&fb->outbase[fb->outcnt], chunksize, chunk_header_size); +#endif /*CHARSET_EBCDIC*/ fb->outchunk = fb->outcnt; fb->outcnt += chunk_header_size; fb->outchunk_header_size = chunk_header_size; @@ -417,6 +426,7 @@ fb->outbase[i - 1] = '\015'; } #ifdef CHARSET_EBCDIC + /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */ ebcdic2ascii(&fb->outbase[fb->outchunk], &fb->outbase[fb->outchunk], fb->outchunk_header_size); #endif /*CHARSET_EBCDIC*/ @@ -598,6 +608,11 @@ * buffer from before we went unbuffered. */ if (fb->incnt) { i = (fb->incnt > nbyte) ? nbyte : fb->incnt; +#ifdef CHARSET_EBCDIC + if (fb->flags & B_ASCII2EBCDIC) + ascii2ebcdic(buf, fb->inptr, i); + else +#endif /*CHARSET_EBCDIC*/ memcpy(buf, fb->inptr, i); fb->incnt -= i; fb->inptr += i; @@ -610,6 +625,11 @@ nrd = fb->incnt; /* can we fill the buffer */ if (nrd >= nbyte) { +#ifdef CHARSET_EBCDIC + if (fb->flags & B_ASCII2EBCDIC) + ascii2ebcdic(buf, fb->inptr, nbyte); + else +#endif /*CHARSET_EBCDIC*/ memcpy(buf, fb->inptr, nbyte); fb->incnt = nrd - nbyte; fb->inptr += nbyte; @@ -617,6 +637,11 @@ } if (nrd > 0) { +#ifdef CHARSET_EBCDIC + if (fb->flags & B_ASCII2EBCDIC) + ascii2ebcdic(buf, fb->inptr, nrd); + else +#endif /*CHARSET_EBCDIC*/ memcpy(buf, fb->inptr, nrd); nbyte -= nrd; buf = nrd + (char *) buf; @@ -629,6 +654,10 @@ if (nbyte >= fb->bufsiz) { /* read directly into buffer */ i = read_with_errors(fb, buf, nbyte); +#ifdef CHARSET_EBCDIC + if (i > 0 && bgetflag(fb, B_ASCII2EBCDIC)) + ascii2ebcdic(buf, buf, nbyte); +#endif /*CHARSET_EBCDIC*/ if (i == -1) { return nrd ? nrd : -1; } @@ -643,6 +672,11 @@ fb->incnt = i; if (i > nbyte) i = nbyte; +#ifdef CHARSET_EBCDIC + if (fb->flags & B_ASCII2EBCDIC) + ascii2ebcdic(buf, fb->inptr, i); + else +#endif /*CHARSET_EBCDIC*/ memcpy(buf, fb->inptr, i); fb->incnt -= i; fb->inptr += i; @@ -702,8 +736,8 @@ continue; /* restart with the new data */ } -#ifndef CHARSET_EBCDIC ch = fb->inptr[i++]; +#ifndef CHARSET_EBCDIC if (ch == '\012') { /* got LF */ if (ct == 0) buff[ct++] = '\n'; @@ -716,15 +750,9 @@ i--; /* no room for LF */ break; } - if (ct == n - 1) { - i--; /* push back ch */ - break; - } - - buff[ct++] = ch; - } #else /* an EBCDIC machine: do the same, but convert to EBCDIC on the fly: */ - ch = os_toebcdic[(unsigned char)fb->inptr[i++]]; + if (fb->flags & B_ASCII2EBCDIC) + ch = os_toebcdic[(unsigned char)ch]; if (ch == os_toebcdic['\012']) { /* got LF */ if (ct == 0) buff[ct++] = '\n'; @@ -737,6 +765,7 @@ i--; /* no room for LF */ break; } +#endif if (ct == n - 1) { i--; /* push back ch */ break; @@ -744,7 +773,6 @@ buff[ct++] = ch; } -#endif fb->incnt -= i; fb->inptr += i; @@ -787,7 +815,9 @@ #ifndef CHARSET_EBCDIC *buff = fb->inptr[0]; #else /*CHARSET_EBCDIC*/ - *buff = os_toebcdic[(unsigned char)fb->inptr[0]]; + *buff = (fb->flags & B_ASCII2EBCDIC) + ? os_toebcdic[(unsigned char)fb->inptr[0]] + : fb->inptr[0]; #endif /*CHARSET_EBCDIC*/ return 1; } @@ -837,11 +867,7 @@ char ss[1]; int rc; -#ifndef CHARSET_EBCDIC ss[0] = c; -#else - ss[0] = os_toascii[(unsigned char)c]; -#endif rc = bwrite(fb, ss, 1); /* We do start_chunk() here so that the bputc macro can be smaller * and faster @@ -865,11 +891,7 @@ if (i != 1) return EOF; else -#ifndef CHARSET_EBCDIC return buf[0]; -#else /*CHARSET_EBCDIC*/ - return os_toebcdic[(unsigned char)buf[0]]; -#endif /*CHARSET_EBCDIC*/ } @@ -1007,6 +1029,10 @@ /* without writev() this has poor performance, too bad */ ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte); +#ifdef CHARSET_EBCDIC + /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */ + ebcdic2ascii(chunksize, chunksize, strlen(chunksize)); +#endif /*CHARSET_EBCDIC*/ if (write_it_all(fb, chunksize, strlen(chunksize)) == -1) return -1; if (write_it_all(fb, buf, nbyte) == -1) @@ -1019,6 +1045,7 @@ vec[0].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte); #ifdef CHARSET_EBCDIC + /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */ ebcdic2ascii(chunksize, chunksize, strlen(chunksize)); #endif /*CHARSET_EBCDIC*/ vec[1].iov_base = (void *) buf; /* cast is to avoid const warning */ @@ -1058,6 +1085,7 @@ vec[nvec].iov_len = ap_snprintf(chunksize, sizeof(chunksize), "%x\015\012", nbyte); #ifdef CHARSET_EBCDIC + /* Chunks are an HTTP/1.1 Protocol feature. They must ALWAYS be in ASCII */ ebcdic2ascii(chunksize, chunksize, strlen(chunksize)); #endif /*CHARSET_EBCDIC*/ ++nvec; @@ -1090,6 +1118,22 @@ API_EXPORT(int) bwrite(BUFF *fb, const void *buf, int nbyte) { int i, nwr; +#ifdef CHARSET_EBCDIC + static char *cbuf = NULL; + static int csize = 0; + + if (bgetflag(fb, B_EBCDIC2ASCII)) { + if (nbyte > csize) { + if (cbuf != NULL) + free(cbuf); + cbuf = malloc(csize = nbyte+HUGE_STRING_LEN); + if (cbuf == NULL) + csize = 0; + } + ebcdic2ascii((cbuf) ? cbuf : (void*)buf, buf, nbyte); + buf = (cbuf) ? cbuf : buf; + } +#endif /*CHARSET_EBCDIC*/ if (fb->flags & (B_WRERR | B_EOUT)) return -1; @@ -1298,54 +1342,17 @@ return rc3; } -#ifdef CHARSET_EBCDIC -/* - * returns the number of bytes written or -1 on error - */ -API_EXPORT(int) bnputs(const char *x, BUFF *fb, size_t amount) -{ - int i; - const char *endp = &x[amount]; - /* @@@FIXME: This probably could use some performance improvement */ - for ( ; x < endp; ++x) { - int ch = *x; - /* This test is a workaround: at many places in Apache, the (ASCII) - * constants \012 and \015 are used in strings in place of \n and \r. - * In an EBCDIC environment, the rest of the strings is interpreted - * as EBCDIC characters, so we need the EBCDIC equivalent of \n and \r - * instead of \012 and \015. So, for the HTTP protocol level, - * conversion is limited to characters other than \012 and \015 (in - * ebcdic2ascii(), I handled it similarly). - * Of course, on all ASCII based environments, the decision to use - * \012 and \015 in strings makes perfectly sense, because on, e.g., - * OS-9/68k machines (or MACs), \n is compiled to \015 - * (as is \r; the \012 escape must be written \l) which would violate - * the HTTP protocol. - */ - if (ch == '\012' || ch == '\015') - ch = os_toebcdic[ch]; - if (bputc(ch, fb) != 0) - return -1; - } - return amount; -} -#endif /*CHARSET_EBCDIC*/ - /* * returns the number of bytes written or -1 on error */ API_EXPORT(int) bputs(const char *x, BUFF *fb) { -#ifndef CHARSET_EBCDIC int i, j = strlen(x); i = bwrite(fb, x, j); if (i != j) return -1; else return j; -#else /*CHARSET_EBCDIC*/ - return bnputs(x, fb, strlen(x)); -#endif /*CHARSET_EBCDIC*/ } /* @@ -1363,11 +1370,7 @@ if (x == NULL) break; j = strlen(x); -#ifndef CHARSET_EBCDIC i = bwrite(fb, x, j); -#else /*CHARSET_EBCDIC*/ - i = bputs(x, fb); -#endif /*CHARSET_EBCDIC*/ if (i != j) { va_end(v); return -1; 1.33 +8 -5 apachen/src/main/buff.h Index: buff.h =================================================================== RCS file: /home/cvs/apachen/src/main/buff.h,v retrieving revision 1.32 retrieving revision 1.33 diff -u -u -r1.32 -r1.33 --- buff.h 1998/01/21 19:17:35 1.32 +++ buff.h 1998/01/26 16:46:08 1.33 @@ -83,6 +83,10 @@ #define B_SAFEREAD (128) /* buffer is a socket */ #define B_SOCKET (256) +#ifdef CHARSET_EBCDIC +#define B_ASCII2EBCDIC 0x40000000 /* Enable conversion for this buffer */ +#define B_EBCDIC2ASCII 0x80000000 /* Enable conversion for this buffer */ +#endif /*CHARSET_EBCDIC*/ typedef struct buff_struct BUFF; @@ -149,9 +153,6 @@ API_EXPORT(int) bskiplf(BUFF *fb); API_EXPORT(int) bwrite(BUFF *fb, const void *buf, int nbyte); API_EXPORT(int) bflush(BUFF *fb); -#ifdef CHARSET_EBCDIC -API_EXPORT(int) bnputs(const char *x, BUFF *fb, size_t amount); -#endif /*CHARSET_EBCDIC*/ API_EXPORT(int) bputs(const char *x, BUFF *fb); API_EXPORT(int) bvputs(BUFF *fb,...); API_EXPORT_NONSTD(int) bprintf(BUFF *fb, const char *fmt,...) @@ -174,11 +175,13 @@ #else /*CHARSET_EBCDIC*/ #define bgetc(fb) ( ((fb)->incnt == 0) ? bfilbuf(fb) : \ - ((fb)->incnt--, os_toebcdic[(unsigned char)*((fb)->inptr++)]) ) + ((fb)->incnt--, (fb->flags & B_ASCII2EBCDIC)\ + ?os_toebcdic[(unsigned char)*((fb)->inptr++)]:*((fb)->inptr++)) ) #define bputc(c, fb) ((((fb)->flags & (B_EOUT|B_WRERR|B_WR)) != B_WR || \ (fb)->outcnt == (fb)->bufsiz) ? bflsbuf(c, (fb)) : \ - ((fb)->outbase[(fb)->outcnt++] = os_toascii[(unsigned char)c], 0)) + ((fb)->outbase[(fb)->outcnt++] = (fb->flags & B_EBCDIC2ASCII)\ + ?os_toascii[(unsigned char)c]:(c), 0)) #endif /*CHARSET_EBCDIC*/ API_EXPORT(int) spawn_child_err_buff(pool *, int (*)(void *), void *, 1.15 +0 -10 apachen/src/main/http_bprintf.c Index: http_bprintf.c =================================================================== RCS file: /home/cvs/apachen/src/main/http_bprintf.c,v retrieving revision 1.14 retrieving revision 1.15 diff -u -u -r1.14 -r1.15 --- http_bprintf.c 1998/01/13 23:11:08 1.14 +++ http_bprintf.c 1998/01/26 16:46:08 1.15 @@ -95,13 +95,8 @@ if (percentPtr == NULL) percentPtr = fStop; if (percentPtr != f) { -#ifndef CHARSET_EBCDIC if (bwrite(bp, f, percentPtr - f) < 0) goto ErrorReturn; -#else - if (bnputs(f, bp, percentPtr - f) < percentPtr - f) - goto ErrorReturn; -#endif streamCount += percentPtr - f; f = percentPtr; if (f == fStop) @@ -559,13 +554,8 @@ } /* for (;;) */ ap_assert(buffCount < buffLen); if (buffCount > 0) { -#ifndef CHARSET_EBCDIC if (bwrite(bp, buffPtr, buffCount) < 0) goto ErrorReturn; -#else /*CHARSET_EBCDIC*/ - if (bnputs(buffPtr, bp, buffCount) != buffCount) - goto ErrorReturn; -#endif /*CHARSET_EBCDIC*/ streamCount += buffCount; } else if (buffCount < 0) 1.148 +2 -22 apachen/src/main/http_core.c Index: http_core.c =================================================================== RCS file: /home/cvs/apachen/src/main/http_core.c,v retrieving revision 1.147 retrieving revision 1.148 diff -u -u -r1.147 -r1.148 --- http_core.c 1998/01/21 22:15:56 1.147 +++ http_core.c 1998/01/26 16:46:09 1.148 @@ -1823,9 +1823,6 @@ #ifdef USE_MMAP_FILES caddr_t mm; #endif -#ifdef CHARSET_EBCDIC - int convert_to_ascii = 0; -#endif /*CHARSET_EBCDIC*/ /* This handler has no use for a request body (yet), but we still * need to read and discard it if the client sent one. @@ -1907,35 +1904,18 @@ * the type to the real text/{plain,html,...} type. Otherwise, we * set a flag that translation is required later on. */ - - /* Conversion is applied to text/ files only, if ever. */ - if (strncmp(r->content_type, "text/", 5)==0) { - if (strncasecmp(r->content_type, ASCIITEXT_MAGIC_TYPE_PREFIX, sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) - r->content_type = pstrcat(r->pool, "text/", r->content_type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL); - else - /* translate EBCDIC to ASCII */ - convert_to_ascii = 1; - } + os_checkconv(r); #endif /*CHARSET_EBCDIC*/ + send_http_header (r); if (!r->header_only) { if (!rangestatus) -#ifdef CHARSET_EBCDIC - if (convert_to_ascii) - send_fd_length_cnv(f, r, -1, 1); - else -#endif /*CHARSET_EBCDIC*/ send_fd (f, r); else { long offset, length; while (each_byterange(r, &offset, &length)) { fseek(f, offset, SEEK_SET); -#ifdef CHARSET_EBCDIC - if (convert_to_ascii) - send_fd_length_cnv(f, r, length, 1); - else -#endif /*CHARSET_EBCDIC*/ send_fd_length(f, r, length); } } 1.179 +25 -21 apachen/src/main/http_protocol.c Index: http_protocol.c =================================================================== RCS file: /home/cvs/apachen/src/main/http_protocol.c,v retrieving revision 1.178 retrieving revision 1.179 diff -u -u -r1.178 -r1.179 --- http_protocol.c 1998/01/23 04:11:32 1.178 +++ http_protocol.c 1998/01/26 16:46:10 1.179 @@ -800,6 +800,9 @@ /* Get the request... */ +#ifdef CHARSET_EBCDIC + bsetflag(r->connection->client, B_ASCII2EBCDIC|B_EBCDIC2ASCII, 1); +#endif /* CHARSET_EBCDIC */ keepalive_timeout("read request line", r); if (!read_request_line(r)) { kill_timeout(r); @@ -1059,6 +1062,9 @@ void basic_http_header(request_rec *r) { char *protocol; +#ifdef CHARSET_EBCDIC + int convert = bgetflag(r->connection->client, B_EBCDIC2ASCII); +#endif /*CHARSET_EBCDIC*/ if (r->assbackwards) return; @@ -1079,6 +1085,10 @@ else protocol = SERVER_PROTOCOL; +#ifdef CHARSET_EBCDIC + bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif /*CHARSET_EBCDIC*/ + /* Output the HTTP/1.x Status-Line and the Date and Server fields */ bvputs(r->connection->client, @@ -1089,6 +1099,10 @@ table_unset(r->headers_out, "Date"); /* Avoid bogosity */ table_unset(r->headers_out, "Server"); +#ifdef CHARSET_EBCDIC + if (!convert) + bsetflag(r->connection->client, B_EBCDIC2ASCII, convert); +#endif /*CHARSET_EBCDIC*/ } /* Navigator versions 2.x, 3.x and 4.0 betas up to and including 4.0b2 @@ -1207,6 +1221,9 @@ { int i; const long int zero = 0L; +#ifdef CHARSET_EBCDIC + int convert = bgetflag(r->connection->client, B_EBCDIC2ASCII); +#endif /*CHARSET_EBCDIC*/ if (r->assbackwards) { if (!r->main) @@ -1228,6 +1245,10 @@ basic_http_header(r); +#ifdef CHARSET_EBCDIC + bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif /*CHARSET_EBCDIC*/ + set_keepalive(r); if (r->chunked) { @@ -1279,6 +1300,10 @@ /* Set buffer flags for the body */ if (r->chunked) bsetflag(r->connection->client, B_CHUNK, 1); +#ifdef CHARSET_EBCDIC + if (!convert) + bsetflag(r->connection->client, B_EBCDIC2ASCII, convert); +#endif /*CHARSET_EBCDIC*/ } /* finalize_request_protocol is called at completion of sending the @@ -1615,18 +1640,6 @@ } API_EXPORT(long) send_fd_length(FILE *f, request_rec *r, long length) -#ifdef CHARSET_EBCDIC -{ - return send_fd_length_cnv(f, r, length, 0); -} - -API_EXPORT(long) send_fd_cnv(FILE *f, request_rec *r) -{ - return send_fd_length_cnv(f, r, -1, 1); -} - -API_EXPORT(long) send_fd_length_cnv(FILE *f, request_rec *r, long length, int convert_to_ascii) -#endif /*CHARSET_EBCDIC*/ { char buf[IOBUFSIZE]; long total_bytes_sent = 0; @@ -1647,11 +1660,6 @@ && ferror(f) && errno == EINTR && !r->connection->aborted) continue; -#ifdef CHARSET_EBCDIC - if (convert_to_ascii) - ebcdic_to_ascii(buf, buf, n); -#endif /*CHARSET_EBCDIC*/ - if (n < 1) { break; } @@ -1903,11 +1911,7 @@ if (x == NULL) break; j = strlen(x); -#ifndef CHARSET_EBCDIC i = bwrite(fb, x, j); -#else /*CHARSET_EBCDIC*/ - i = bputs(x, fb); -#endif /*CHARSET_EBCDIC*/ if (i != j) { va_end(args); return -1; 1.68 +11 -0 apachen/src/modules/standard/mod_cgi.c Index: mod_cgi.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_cgi.c,v retrieving revision 1.67 retrieving revision 1.68 diff -u -u -r1.67 -r1.68 --- mod_cgi.c 1998/01/24 19:00:23 1.67 +++ mod_cgi.c 1998/01/26 16:46:14 1.68 @@ -410,6 +410,12 @@ cld.nph = nph; cld.debug = conf->logname ? 1 : 0; +#ifdef CHARSET_EBCDIC + /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */ + /* Or must we check the Content-Type first? */ + bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif /*CHARSET_EBCDIC*/ + /* * we spawn out of r->main if it's there so that we can avoid * waiting for free_proc_chain to cleanup in the middle of an @@ -486,6 +492,11 @@ if ((ret = scan_script_header_err_buff(r, script_in, sbuf))) { return log_script(r, conf, ret, dbuf, sbuf, script_in, script_err); } + +#ifdef CHARSET_EBCDIC + /* Now check the Content-Type to decide if conversion is needed */ + os_checkconv(r); +#endif /*CHARSET_EBCDIC*/ location = table_get(r->headers_out, "Location"); 1.66 +8 -13 apachen/src/modules/standard/mod_include.c Index: mod_include.c =================================================================== RCS file: /home/cvs/apachen/src/modules/standard/mod_include.c,v retrieving revision 1.65 retrieving revision 1.66 diff -u -u -r1.65 -r1.66 --- mod_include.c 1998/01/24 19:00:24 1.65 +++ mod_include.c 1998/01/26 16:46:14 1.66 @@ -169,20 +169,11 @@ * errors is and little can really be done to help the error in * any case. */ -#ifndef CHARSET_EBCDIC #define FLUSH_BUF(r) \ { \ rwrite(outbuf, outind, r); \ outind = 0; \ } -#else /*CHARSET_EBCDIC*/ -#define FLUSH_BUF(r) \ - { \ - ebcdic2ascii(outbuf, outbuf, outind); \ - rwrite(outbuf, outind, r); \ - outind = 0; \ - } -#endif /*CHARSET_EBCDIC*/ /* * f: file handle being read from @@ -689,6 +680,9 @@ } } +#ifdef CHARSET_EBCDIC + bsetflag(rr->connection->client, B_EBCDIC2ASCII, 0); +#endif if (!error_fmt && run_sub_req(rr)) { error_fmt = "unable to include \"%s\" in parsed file %s"; } @@ -806,11 +800,7 @@ return -1; } -#ifndef CHARSET_EBCDIC send_fd(f, r); -#else /*CHARSET_EBCDIC*/ - send_fd_length_cnv(f, r, -1, 1); -#endif /*CHARSET_EBCDIC*/ pfclose(r->pool, f); /* will wait for zombie when * r->pool is cleared */ @@ -2304,6 +2294,11 @@ add_include_vars(r, DEFAULT_TIME_FORMAT); } hard_timeout("send SSI", r); + +#ifdef CHARSET_EBCDIC + /* XXX:@@@ Is the generated/included output ALWAYS in text/ebcdic format? */ + bsetflag(r->connection->client, B_EBCDIC2ASCII, 1); +#endif send_parsed_content(f, r); 1.3 +114 -10 apachen/src/os/bs2000/ebcdic.c Index: ebcdic.c =================================================================== RCS file: /home/cvs/apachen/src/os/bs2000/ebcdic.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -u -r1.2 -r1.3 --- ebcdic.c 1998/01/16 14:23:33 1.2 +++ ebcdic.c 1998/01/26 16:46:16 1.3 @@ -1,12 +1,66 @@ +/* ==================================================================== + * Copyright (c) 1998 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * [EMAIL PROTECTED] + * + * 5. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + + #ifdef CHARSET_EBCDIC #include "ebcdic.h" /* - Initial Port for pache-1.3 by <[EMAIL PROTECTED]> + Initial Port for Apache-1.3 by <[EMAIL PROTECTED]> "BS2000 OSD" is a POSIX on a main frame. It is made by Siemens Nixdorf AG, Germany. Within the POSIX subsystem, the same character set was chosen as in -"native BS2000", namely EBCDIC. Yes, tcsh now runs on EBCDIC platforms, too. +"native BS2000", namely EBCDIC. EBCDIC Table. (Yes, in EBCDIC, the letters 'a'..'z' are not contiguous!) This table is bijective, i.e. there are no ambigous or duplicate characters @@ -27,7 +81,9 @@ e0 d9 f7 53 54 55 56 57 58 59 5a b2 d4 d6 d2 d3 d5 *..STUVWXYZ......* f0 30 31 32 33 34 35 36 37 38 39 b3 7b dc 7d da 7e *0123456789.{.}.~* */ -unsigned char os_toascii[256] = { + +/* The bijective ebcdic-to-ascii table: */ +unsigned char os_toascii_strictly[256] = { /*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, 0x87, 0x8d, 0x8e, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/ /*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, @@ -59,12 +115,62 @@ /*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ......*/ /*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/ + 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/ +}; + +/* This table is (almost) identical to the previous one. The only difference + * is the fact that it maps every EBCDIC *except 0x0A* to its ASCII + * equivalent. The reason for this table is simple: Throughout the + * server, protocol strings are used in the form + * "Content-Type: text/plain\015\012". Now all the characters in the string + * are stored as EBCDIC, only the semantics of \012 is completely + * different from LF (look it up in the table above). \015 happens to be + * mapped to \015 anyway, so there's no special case for it. + * + * In THIS table, EBCDIC-\012 is mapped to ASCII-\012. + * This table is therefore used wherever an EBCDIC to ASCII conversion is + * needed in the server. + */ +/* ebcdic-to-ascii with \012 mapped to ASCII-\n */ +unsigned char os_toascii[256] = { +/*00*/ 0x00, 0x01, 0x02, 0x03, 0x85, 0x09, 0x86, 0x7f, + 0x87, 0x8d, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, /*................*/ +/*10*/ 0x10, 0x11, 0x12, 0x13, 0x8f, 0x0a, 0x08, 0x97, + 0x18, 0x19, 0x9c, 0x9d, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/ +/*20*/ 0x80, 0x81, 0x82, 0x83, 0x84, 0x92, 0x17, 0x1b, + 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x05, 0x06, 0x07, /*................*/ +/*30*/ 0x90, 0x91, 0x16, 0x93, 0x94, 0x95, 0x96, 0x04, + 0x98, 0x99, 0x9a, 0x9b, 0x14, 0x15, 0x9e, 0x1a, /*................*/ +/*40*/ 0x20, 0xa0, 0xe2, 0xe4, 0xe0, 0xe1, 0xe3, 0xe5, + 0xe7, 0xf1, 0x60, 0x2e, 0x3c, 0x28, 0x2b, 0x7c, /* .........`.<(+|*/ +/*50*/ 0x26, 0xe9, 0xea, 0xeb, 0xe8, 0xed, 0xee, 0xef, + 0xec, 0xdf, 0x21, 0x24, 0x2a, 0x29, 0x3b, 0x9f, /*&.........!$*);.*/ +/*60*/ 0x2d, 0x2f, 0xc2, 0xc4, 0xc0, 0xc1, 0xc3, 0xc5, + 0xc7, 0xd1, 0x5e, 0x2c, 0x25, 0x5f, 0x3e, 0x3f, /*-/........^,%_>?*/ +/*70*/ 0xf8, 0xc9, 0xca, 0xcb, 0xc8, 0xcd, 0xce, 0xcf, + 0xcc, 0xa8, 0x3a, 0x23, 0x40, 0x27, 0x3d, 0x22, /*..........:#@'="*/ +/*80*/ 0xd8, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, + 0x68, 0x69, 0xab, 0xbb, 0xf0, 0xfd, 0xfe, 0xb1, /*.abcdefghi......*/ +/*90*/ 0xb0, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, + 0x71, 0x72, 0xaa, 0xba, 0xe6, 0xb8, 0xc6, 0xa4, /*.jklmnopqr......*/ +/*a0*/ 0xb5, 0xaf, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, + 0x79, 0x7a, 0xa1, 0xbf, 0xd0, 0xdd, 0xde, 0xae, /*..stuvwxyz......*/ +/*b0*/ 0xa2, 0xa3, 0xa5, 0xb7, 0xa9, 0xa7, 0xb6, 0xbc, + 0xbd, 0xbe, 0xac, 0x5b, 0x5c, 0x5d, 0xb4, 0xd7, /*...........[\]..*/ +/*c0*/ 0xf9, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, + 0x48, 0x49, 0xad, 0xf4, 0xf6, 0xf2, 0xf3, 0xf5, /*.ABCDEFGHI......*/ +/*d0*/ 0xa6, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, + 0x51, 0x52, 0xb9, 0xfb, 0xfc, 0xdb, 0xfa, 0xff, /*.JKLMNOPQR......*/ +/*e0*/ 0xd9, 0xf7, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, + 0x59, 0x5a, 0xb2, 0xd4, 0xd6, 0xd2, 0xd3, 0xd5, /*..STUVWXYZ......*/ +/*f0*/ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, + 0x38, 0x39, 0xb3, 0x7b, 0xdc, 0x7d, 0xda, 0x7e /*0123456789.{.}.~*/ }; -/* The same, for ascii-in-ebcdic + +/* The ascii-to-ebcdic table: 00 00 01 02 03 37 2d 2e 2f 16 05 15 0b 0c 0d 0e 0f *................* 10 10 11 12 13 3c 3d 32 26 18 19 3f 27 1c 1d 1e 1f *................* -20 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 * !"#$%&'()*+,-./* +20 40 5a 7f 7b 5b 6c 50 7d 4d 5d 5c 4e 6b 60 4b 61 * !"#$%&'()*+,-./ 30 f0 f1 f2 f3 f4 f5 f6 f7 f8 f9 7a 5e 4c 7e 6e 6f *0123456789:;<=>?* 40 7c c1 c2 c3 c4 c5 c6 c7 c8 c9 d1 d2 d3 d4 d5 d6 [EMAIL PROTECTED] 50 d7 d8 d9 e2 e3 e4 e5 e6 e7 e8 e9 bb bc bd 6a 6d *PQRSTUVWXYZ[\]^_* @@ -85,7 +191,7 @@ /*10*/ 0x10, 0x11, 0x12, 0x13, 0x3c, 0x3d, 0x32, 0x26, 0x18, 0x19, 0x3f, 0x27, 0x1c, 0x1d, 0x1e, 0x1f, /*................*/ /*20*/ 0x40, 0x5a, 0x7f, 0x7b, 0x5b, 0x6c, 0x50, 0x7d, - 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./*/ + 0x4d, 0x5d, 0x5c, 0x4e, 0x6b, 0x60, 0x4b, 0x61, /* !"#$%&'()*+,-./ */ /*30*/ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0x7a, 0x5e, 0x4c, 0x7e, 0x6e, 0x6f, /*0123456789:;<=>?*/ /*40*/ 0x7c, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, @@ -122,9 +228,7 @@ ebcdic2ascii(unsigned char *dest, const unsigned char *srce, size_t count) { while (count-- != 0) { - *dest++ = (*srce == '\015' || *srce=='\012') - ? *srce : os_toascii[*srce]; - ++srce; + *dest++ = os_toascii[*srce++]; } } void 1.2 +85 -0 apachen/src/os/bs2000/os.c Index: os.c =================================================================== RCS file: /home/cvs/apachen/src/os/bs2000/os.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -u -r1.1 -r1.2 --- os.c 1998/01/13 23:11:32 1.1 +++ os.c 1998/01/26 16:46:16 1.2 @@ -1,6 +1,91 @@ +/* ==================================================================== + * Copyright (c) 1998 The Apache Group. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. All advertising materials mentioning features or use of this + * software must display the following acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * 4. The names "Apache Server" and "Apache Group" must not be used to + * endorse or promote products derived from this software without + * prior written permission. For written permission, please contact + * [EMAIL PROTECTED] + * + * 5. Redistributions of any form whatsoever must retain the following + * acknowledgment: + * "This product includes software developed by the Apache Group + * for use in the Apache HTTP server project (http://www.apache.org/)." + * + * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY + * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE APACHE GROUP OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Group and was originally based + * on public domain software written at the National Center for + * Supercomputing Applications, University of Illinois, Urbana-Champaign. + * For more information on the Apache Group and the Apache HTTP server + * project, please see <http://www.apache.org/>. + * + */ + /* * This file will include OS specific functions which are not inlineable. * Any inlineable functions should be defined in os-inline.c instead. */ #include "os.h" + +/* Check the Content-Type to decide if conversion is needed */ +int os_checkconv(struct request_rec *r) +{ + int convert_to_ascii; + + /* To make serving of "raw ASCII text" files easy (they serve faster + * since they don't have to be converted from EBCDIC), a new + * "magic" type prefix was invented: text/x-ascii-{plain,html,...} + * If we detect one of these content types here, we simply correct + * the type to the real text/{plain,html,...} type. Otherwise, we + * set a flag that translation is required later on. + */ + + /* If no content type is set then treat it as (ebcdic) text/plain */ + convert_to_ascii = (r->content_type == NULL); + + /* Conversion is applied to text/ files only, if ever. */ + if (r->content_type && strncasecmp(r->content_type, "text/", 5)==0) { + if (strncasecmp(r->content_type, ASCIITEXT_MAGIC_TYPE_PREFIX, + sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1) == 0) + r->content_type = pstrcat(r->pool, "text/", + r->content_type+sizeof(ASCIITEXT_MAGIC_TYPE_PREFIX)-1, NULL); + else + /* translate EBCDIC to ASCII */ + convert_to_ascii = 1; + } + bsetflag(r->connection->client, B_EBCDIC2ASCII, convert_to_ascii); + + return convert_to_ascii; +} + 1.2 +10 -0 apachen/src/os/bs2000/os.h Index: os.h =================================================================== RCS file: /home/cvs/apachen/src/os/bs2000/os.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -u -r1.1 -r1.2 --- os.h 1998/01/13 23:11:32 1.1 +++ os.h 1998/01/26 16:46:17 1.2 @@ -1,9 +1,13 @@ +#ifndef AP_OS_BS2000_OS_H +#define AP_OS_BS2000_OS_H /* * This file in included in all Apache source code. It contains definitions * of facilities available on _this_ operating system (HAVE_* macros), * and prototypes of OS specific functions defined in os.c or os-inline.c */ +#include "httpd.h" + #if !defined(INLINE) && defined(USE_GNU_INLINE) /* Compiler supports inline, so include the inlineable functions as * part of the header @@ -18,3 +22,9 @@ */ extern int os_is_path_absolute(char *f); #endif + +/* Sorry if this is ugly, but the include order doesn't allow me + * to use request_rec here... */ +struct request_rec; +extern int os_checkconv(struct request_rec *r); +#endif /*AP_OS_BS2000_OS_H*/