home *** CD-ROM | disk | FTP | other *** search
/ Il CD di internet / CD.iso / SOURCE / CONTRIB / HTTPD / HTTPD_SO.TAR / httpd_1.3 / src / http_include.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-05-07  |  18.6 KB  |  643 lines

  1. /*
  2.  * http_include.c: Handles the server-parsed HTML documents
  3.  * 
  4.  * Rob McCool
  5.  * 
  6.  */
  7.  
  8. #include "httpd.h"
  9.  
  10. #define STARTING_SEQUENCE "<!--#"
  11. #define ENDING_SEQUENCE "-->"
  12. #define DEFAULT_ERROR_MSG "[an error occurred while processing this directive]"
  13. #define DEFAULT_TIME_FORMAT "%A, %d-%b-%y %T %Z"
  14. #define SIZEFMT_BYTES 0
  15. #define SIZEFMT_KMG 1
  16.  
  17. /* These are stored statically so that they can be reformatted quickly */
  18. static time_t date,lm;
  19.  
  20. /* ------------------------ Environment function -------------------------- */
  21.  
  22. #define NUM_INCLUDE_VARS 5
  23.  
  24. char **add_include_vars(char **env,char *file, char *path_args, char *args, 
  25.                         char *timefmt,FILE *out)
  26. {
  27.     int x;
  28.     struct stat finfo;
  29.     char ufile[HUGE_STRING_LEN];
  30.     char *t;
  31.  
  32.     if(!(env = new_env(env,NUM_INCLUDE_VARS,&x)))
  33.         die(NO_MEMORY,"add_include_vars",out);
  34.     date = time(NULL);
  35.     env[x++] = make_env_str("DATE_LOCAL",ht_time(date,timefmt,0),out);
  36.     env[x++] = make_env_str("DATE_GMT",ht_time(date,timefmt,1),out);
  37.  
  38.     if(stat(file,&finfo) != -1) {
  39.         lm = finfo.st_mtime;
  40.         env[x++] = make_env_str("LAST_MODIFIED",ht_time(lm,timefmt,0),out);
  41.     }
  42.     strcpy(ufile,file);
  43.     unmunge_name(ufile);
  44.     env[x++] = make_env_str("DOCUMENT_URI",ufile,out);
  45.     if(t = strrchr(ufile,'/'))
  46.         ++t;
  47.     else
  48.         t = ufile;
  49.     env[x++] = make_env_str("DOCUMENT_NAME",t,out);
  50.     env[x] = NULL;
  51.     return env;
  52. }
  53.  
  54. #define GET_CHAR(f,c,r) \
  55.  { \
  56.    int i = getc(f); \
  57.    if(feof(f) || ferror(f) || (i == -1)) { \
  58.         fclose(f); \
  59.         return r; \
  60.    } \
  61.    c = (char)i; \
  62.  }
  63.  
  64. /* --------------------------- Parser functions --------------------------- */
  65.  
  66. int find_string(FILE *in,char *str, FILE *out) {
  67.     int x,l=strlen(str),p;
  68.     char c;
  69.  
  70.     p=0;
  71.     while(1) {
  72.         GET_CHAR(in,c,1);
  73.         if(c == str[p]) {
  74.             if((++p) == l)
  75.                 return 0;
  76.         }
  77.         else {
  78.             if(out) {
  79.                 if(p) {
  80.                     for(x=0;x<p;x++) {
  81.                         putc(str[x],out);
  82.                         ++bytes_sent;
  83.                     }
  84.                 }
  85.                 putc(c,out);
  86.                 ++bytes_sent;
  87.             }
  88.             p=0;
  89.         }
  90.     }
  91. }
  92.  
  93. char *get_tag(FILE *in, char *tag) {
  94.     char *t = tag, *tag_val, c;
  95.     int n;
  96.  
  97.     n = 0;
  98.     while(1) {
  99.         GET_CHAR(in,c,NULL);
  100.         if(!isspace(c)) break;
  101.     }
  102.     /* problem: this drops tags starting with - or -- (tough s***) */
  103.     if(c == '-') {
  104.         GET_CHAR(in,c,NULL);
  105.         if(c == '-') {
  106.             GET_CHAR(in,c,NULL);
  107.             if(c == '>') {
  108.                 strcpy(tag,"done");
  109.                 return tag;
  110.             }
  111.         }
  112.     }
  113.     /* this parser is very rigid, needs quotes around value and no spaces */
  114.     while(1) {
  115.         if(++n == MAX_STRING_LEN) {
  116.             t[MAX_STRING_LEN - 1] = '\0';
  117.             return NULL;
  118.         }
  119.         if((*t = c) == '\\') {
  120.             GET_CHAR(in,c,NULL);
  121.             *t = c;
  122.         } else if(*t == '=') {
  123.             *t++ = '\0';
  124.             tag_val = t;
  125.             GET_CHAR(in,c,NULL);
  126.             if(c == '\"') {
  127.                 while(1) {
  128.                     GET_CHAR(in,c,NULL);
  129.                     if(++n == MAX_STRING_LEN) {
  130.                         t[MAX_STRING_LEN - 1] = '\0';
  131.                         return NULL;
  132.                     }
  133.                     if((*t = c) == '\\') {
  134.                         GET_CHAR(in,c,NULL);
  135.                         *t = c;
  136.                     } else if(*t == '\"') {
  137.                         *t = '\0';
  138.                         return tag_val;
  139.                     }
  140.                     ++t;
  141.                 }
  142.             } else 
  143.                 return NULL;
  144.         }
  145.         ++t;
  146.         GET_CHAR(in,c,NULL);
  147.     }
  148. }
  149.  
  150. int get_directive(FILE *in,char *d) {
  151.     char c;
  152.  
  153.     /* skip initial whitespace */
  154.     while(1) {
  155.         GET_CHAR(in,c,1);
  156.         if(!isspace(c))
  157.             break;
  158.     }
  159.     /* now get directive */
  160.     while(1) {
  161.         *d++ = c;
  162.         GET_CHAR(in,c,1);
  163.         if(isspace(c))
  164.             break;
  165.     }
  166.     *d = '\0';
  167.     return 0;
  168. }
  169.  
  170. /* --------------------------- Action handlers ---------------------------- */
  171.  
  172.  
  173. void send_parsed_content(char *file, FILE *f, FILE *fd, 
  174.                          char *path_args, char *args,
  175.                          char **env,int noexec);
  176.  
  177. int send_included_file(char *file, FILE *out, char **env, char *fn) 
  178. {
  179.     FILE *f;
  180.     struct stat finfo;
  181.     int allow;char op,i;
  182.  
  183.     if(stat(file,&finfo) == -1)
  184.         return -1;
  185.     evaluate_access(file,&finfo,M_GET,&allow,&op,out);
  186.     if(!allow)
  187.         return -1;
  188.     set_content_type(file);
  189.     if((op & OPT_INCLUDES) && (!strcmp(content_type,INCLUDES_MAGIC_TYPE))) {
  190.         if(!(f = fopen(file,"r")))
  191.             return -1;
  192.         send_parsed_content(file,f,out,"","",env,op & OPT_INCNOEXEC);
  193.         chdir_file(fn); /* grumble */
  194.     }
  195.     else if(!strcmp(content_type,CGI_MAGIC_TYPE))
  196.         return -1;
  197.     else {
  198.         if(!(f=fopen(file,"r")))
  199.             return -1;
  200.         send_fd(f,out,NULL);
  201.         fclose(f);
  202.     }
  203.     return 0;
  204. }
  205.  
  206. int handle_include(FILE *in, FILE *out, char *fn, char **env, char *error) {
  207.     char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
  208.     char *tag_val;
  209.  
  210.     while(1) {
  211.         if(!(tag_val = get_tag(in,tag)))
  212.             return 1;
  213.         if(!strcmp(tag,"file")) {
  214.             char dir[MAX_STRING_LEN],to_send[MAX_STRING_LEN];
  215.  
  216.             getparents(tag_val); /* get rid of any nasties */
  217.             getwd(dir);
  218.             make_full_path(dir,tag_val,to_send);
  219.             if(send_included_file(to_send,out,env,fn)) {
  220.                 sprintf(errstr,"unable to include %s in parsed file %s",
  221.                         tag_val, fn);
  222.                 log_error_noclose(errstr);
  223.                 bytes_sent += fprintf(out,"%s",error);
  224.             }            
  225.         } 
  226.         else if(!strcmp(tag,"virtual")) {
  227.             if(translate_name(tag_val,out) != STD_DOCUMENT) {
  228.                 bytes_sent += fprintf(out,"%s",error);
  229.                 log_error_noclose(errstr);
  230.             }  
  231.             else if(send_included_file(tag_val,out,env,fn)) {
  232.                 sprintf(errstr,"unable to include %s in parsed file %s",
  233.                         tag_val, fn);
  234.                 log_error_noclose(errstr);
  235.                 bytes_sent += fprintf(out,"%s",error);
  236.             }
  237.         } 
  238.         else if(!strcmp(tag,"done"))
  239.             return 0;
  240.         else {
  241.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,fn);
  242.             log_error_noclose(errstr);
  243.             bytes_sent += fprintf(out,"%s",error);
  244.         }
  245.     }
  246. }
  247.  
  248. int handle_echo(FILE *in, FILE *out, char *file, char *error, char **env) {
  249.     char tag[MAX_STRING_LEN];
  250.     char *tag_val;
  251.  
  252.     while(1) {
  253.         if(!(tag_val = get_tag(in,tag)))
  254.             return 1;
  255.         if(!strcmp(tag,"var")) {
  256.             int x,i;
  257.  
  258.             for(x=0;env[x] != NULL; x++) {
  259.                 i = ind(env[x],'=');
  260.                 if(!strncmp(env[x],tag_val,i)) {
  261.                     bytes_sent += fprintf(out,"%s",&env[x][i+1]);
  262.                     break;
  263.                 }
  264.             }
  265.             if(!env[x]) bytes_sent += fprintf(out,"(none)");
  266.         } else if(!strcmp(tag,"done"))
  267.             return 0;
  268.         else {
  269.             char errstr[MAX_STRING_LEN];
  270.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
  271.             log_error_noclose(errstr);
  272.             bytes_sent += fprintf(out,"%s",error);
  273.         }
  274.     }
  275. }
  276.  
  277. int include_cgi(char *s, char *pargs, char *args, char **env, FILE *out) 
  278. {
  279.     char *argp,op,d[HUGE_STRING_LEN];
  280.     int allow,check_cgiopt;
  281.     struct stat finfo;
  282.  
  283.     getparents(s);
  284.     if(s[0] == '/') {
  285.         strcpy(d,s);
  286.         if(translate_name(d,out) != SCRIPT_CGI)
  287.             return -1;
  288.         check_cgiopt=0;
  289.     } else {
  290.         char dir[MAX_STRING_LEN];
  291.         getwd(dir);
  292.         make_full_path(dir,s,d);
  293.         check_cgiopt=1;
  294.     }
  295.     /* No hardwired path info or query allowed */
  296.     if(stat(d,&finfo) == -1)
  297.         return -1;
  298.  
  299.     evaluate_access(d,&finfo,M_GET,&allow,&op,out);
  300.     if((!allow) || (check_cgiopt && (!(op & OPT_EXECCGI))))
  301.         return -1;
  302.  
  303.     if(cgi_stub("GET",d,pargs,args,env,&finfo,-1,out) == REDIRECT_URL)
  304.         bytes_sent += fprintf(out,"<A HREF=\"%s\">%s</A>",location,location);
  305.     return 0;
  306. }
  307.  
  308. static int ipid;
  309. void kill_include_child() {
  310.     char errstr[MAX_STRING_LEN];
  311.     sprintf(errstr,"killing command process %d",ipid);
  312.     log_error_noclose(errstr);
  313.     kill(ipid,SIGKILL);
  314.     waitpid(ipid,NULL,0);
  315. }
  316.  
  317. int include_cmd(char *s, char *pargs, char *args, char **env, FILE *out) {
  318.     int p[2],x;
  319.     FILE *f;
  320.  
  321.     if(pipe(p) == -1)
  322.         die(SERVER_ERROR,"httpd: could not create IPC pipe",out);
  323.     if((ipid = fork()) == -1)
  324.         die(SERVER_ERROR,"httpd: could not fork new process",out);
  325.     if(!ipid) {
  326.         char *argv0;
  327.  
  328.         if(pargs[0] || args[0]) {
  329.             if(!(env = new_env(env,4,&x)))
  330.                 return -1;
  331.             if(pargs[0]) {
  332.                 char p2[HUGE_STRING_LEN];
  333.                 
  334.                 escape_shell_cmd(pargs);
  335.                 env[x++] = make_env_str("PATH_INFO",pargs,out);
  336.                 strcpy(p2,pargs);
  337.                 translate_name(p2,out);
  338.                 env[x++] = make_env_str("PATH_TRANSLATED",p2,out);
  339.             }
  340.             if(args[0]) {
  341.                 env[x++] = make_env_str("QUERY_STRING",args,out);
  342.                 unescape_url(args);
  343.                 escape_shell_cmd(args);
  344.                 env[x++] = make_env_str("QUERY_STRING_UNESCAPED",args,out);
  345.             }
  346.             env[x] = NULL;
  347.         }
  348.  
  349.         close(p[0]);
  350.         if(p[1] != STDOUT_FILENO) {
  351.             dup2(p[1],STDOUT_FILENO);
  352.             close(p[1]);
  353.         }
  354.         error_log2stderr();
  355.         if(!(argv0 = strrchr(SHELL_PATH,'/')))
  356.             argv0=SHELL_PATH;
  357.         if(execle(SHELL_PATH,argv0,"-c",s,(char *)0,env) == -1) {
  358.             fprintf(stderr,"httpd: exec of %s failed, errno is %d\n",
  359.                     SHELL_PATH,errno);
  360.             exit(1);
  361.         }
  362.     }
  363.     close(p[1]);
  364.     if(!(f=fdopen(p[0],"r"))) {
  365.         waitpid(ipid,NULL,0);
  366.         return -1;
  367.     }
  368.     send_fd(f,out,kill_include_child);
  369.     fclose(f);
  370.     waitpid(ipid,NULL,0);
  371.     return 0;
  372. }
  373.  
  374.  
  375. int handle_exec(FILE *in, FILE *out, char *file, char *path_args, char *args,
  376.                 char *error, char **env)
  377. {
  378.     char tag[MAX_STRING_LEN],errstr[MAX_STRING_LEN];
  379.     char *tag_val;
  380.  
  381.     while(1) {
  382.         if(!(tag_val = get_tag(in,tag)))
  383.             return 1;
  384.         if(!strcmp(tag,"cmd")) {
  385.             if(include_cmd(tag_val,path_args,args,env,out) == -1) {
  386.                 sprintf(errstr,"invalid command exec %s in %s",tag_val,file);
  387.                 log_error_noclose(errstr);
  388.                 bytes_sent += fprintf(out,"%s",error);
  389.             }
  390.             /* just in case some stooge changed directories */
  391.             chdir_file(file);
  392.         } 
  393.         else if(!strcmp(tag,"cgi")) {
  394.             if(include_cgi(tag_val,path_args,args,env,out) == -1) {
  395.                 sprintf(errstr,"invalid CGI ref %s in %s",tag_val,file);
  396.                 log_error_noclose(errstr);
  397.                 bytes_sent += fprintf(out,"%s",error);
  398.             }
  399.             /* grumble groan */
  400.             chdir_file(file);
  401.         }
  402.         else if(!strcmp(tag,"done"))
  403.             return 0;
  404.         else {
  405.             char errstr[MAX_STRING_LEN];
  406.             sprintf(errstr,"unknown parameter %s to tag echo in %s",tag,file);
  407.             log_error_noclose(errstr);
  408.             bytes_sent += fprintf(out,"%s",error);
  409.         }
  410.     }
  411.  
  412. }
  413.  
  414. int handle_config(FILE *in, FILE *out, char *file, char *error, char *tf,
  415.                   int *sizefmt, char **env) {
  416.     char tag[MAX_STRING_LEN];
  417.     char *tag_val;
  418.  
  419.     while(1) {
  420.         if(!(tag_val = get_tag(in,tag)))
  421.             return 1;
  422.         if(!strcmp(tag,"errmsg"))
  423.             strcpy(error,tag_val);
  424.         else if(!strcmp(tag,"timefmt")) {
  425.             strcpy(tf,tag_val);
  426.             /* Replace DATE* and LAST_MODIFIED (they should be first) */
  427.             free(env[0]);
  428.             env[0] = make_env_str("DATE_LOCAL",ht_time(date,tf,0),out);
  429.             free(env[1]);
  430.             env[1] = make_env_str("DATE_GMT",ht_time(date,tf,1),out);
  431.             if(!strncmp(env[2],"LAST_MODIFIED",13)) {
  432.                 free(env[2]);
  433.                 env[2] = make_env_str("LAST_MODIFIED",ht_time(lm,tf,0),out);
  434.             }
  435.         }
  436.         else if(!strcmp(tag,"sizefmt")) {
  437.             if(!strcmp(tag_val,"bytes"))
  438.                 *sizefmt = SIZEFMT_BYTES;
  439.             else if(!strcmp(tag_val,"abbrev"))
  440.                 *sizefmt = SIZEFMT_KMG;
  441.         } 
  442.         else if(!strcmp(tag,"done"))
  443.             return 0;
  444.         else {
  445.             char errstr[MAX_STRING_LEN];
  446.             sprintf(errstr,"unknown parameter %s to tag config in %s",
  447.                     tag,file);
  448.             log_error_noclose(errstr);
  449.             bytes_sent += fprintf(out,"%s",error);
  450.         }
  451.     }
  452. }
  453.  
  454.  
  455.  
  456. int find_file(FILE *out, char *file, char *directive, char *tag, 
  457.               char *tag_val, struct stat *finfo, char *error)
  458. {
  459.     char errstr[MAX_STRING_LEN], dir[MAX_STRING_LEN], to_send[MAX_STRING_LEN];
  460.  
  461.     if(!strcmp(tag,"file")) {
  462.         getparents(tag_val); /* get rid of any nasties */
  463.         getwd(dir);
  464.         make_full_path(dir,tag_val,to_send);
  465.         if(stat(to_send,finfo) == -1) {
  466.             sprintf(errstr,
  467.                     "unable to get information about %s in parsed file %s",
  468.                     to_send,file);
  469.             log_error_noclose(errstr);
  470.             bytes_sent += fprintf(out,"%s",error);
  471.             return -1;
  472.         }
  473.         return 0;
  474.     }
  475.     else if(!strcmp(tag,"virtual")) {
  476.         if(translate_name(tag_val,out) != STD_DOCUMENT) {
  477.             bytes_sent += fprintf(out,"%s",error);
  478.             log_error_noclose(errstr);
  479.         }  
  480.         else if(stat(tag_val,finfo) == -1) {
  481.             sprintf(errstr,
  482.                     "unable to get information about %s in parsed file %s",
  483.                     to_send,file);
  484.             log_error_noclose(errstr);
  485.             bytes_sent += fprintf(out,"%s",error);
  486.             return -1;
  487.         }
  488.         return 0;
  489.     }
  490.     else {
  491.         sprintf(errstr,"unknown parameter %s to tag %s in %s",
  492.                 tag,directive,file);
  493.         log_error_noclose(errstr);
  494.         bytes_sent += fprintf(out,"%s",error);
  495.         return -1;
  496.     }
  497. }
  498.  
  499.  
  500. int handle_fsize(FILE *in, FILE *out, char *file, char *error, int sizefmt,
  501.                  char **env) 
  502. {
  503.     char tag[MAX_STRING_LEN];
  504.     char *tag_val;
  505.     struct stat finfo;
  506.  
  507.     while(1) {
  508.         if(!(tag_val = get_tag(in,tag)))
  509.             return 1;
  510.         else if(!strcmp(tag,"done"))
  511.             return 0;
  512.         else if(!find_file(out,file,"fsize",tag,tag_val,&finfo,error)) {
  513.             if(sizefmt == SIZEFMT_KMG) {
  514.                 send_size(finfo.st_size,out);
  515.                 bytes_sent += 5;
  516.             }
  517.             else {
  518.                 int l,x;
  519.                 sprintf(tag,"%ld",finfo.st_size);
  520.                 l = strlen(tag); /* grrr */
  521.                 for(x=0;x<l;x++) {
  522.                     if(x && (!((l-x) % 3))) {
  523.                         fputc(',',out);
  524.                         ++bytes_sent;
  525.                     }
  526.                     fputc(tag[x],out);
  527.                     ++bytes_sent;
  528.                 }
  529.             }
  530.         }
  531.     }
  532. }
  533.  
  534. int handle_flastmod(FILE *in, FILE *out, char *file, char *error, char *tf,
  535.                     char **env) 
  536. {
  537.     char tag[MAX_STRING_LEN];
  538.     char *tag_val;
  539.     struct stat finfo;
  540.  
  541.     while(1) {
  542.         if(!(tag_val = get_tag(in,tag)))
  543.             return 1;
  544.         else if(!strcmp(tag,"done"))
  545.             return 0;
  546.         else if(!find_file(out,file,"flastmod",tag,tag_val,&finfo,error))
  547.             bytes_sent += fprintf(out,"%s",ht_time(finfo.st_mtime,tf,0));
  548.     }
  549. }    
  550.  
  551.  
  552.  
  553. /* -------------------------- The main function --------------------------- */
  554.  
  555. /* This is a stub which parses a file descriptor. */
  556.  
  557. void send_parsed_content(char *file, FILE *f, FILE *fd, 
  558.                          char *path_args, char *args,
  559.                          char **env,int noexec)
  560. {
  561.     char directive[MAX_STRING_LEN], error[MAX_STRING_LEN], c;
  562.     char timefmt[MAX_STRING_LEN], errstr[MAX_STRING_LEN];
  563.     int ret, sizefmt;
  564.  
  565.     strcpy(error,DEFAULT_ERROR_MSG);
  566.     strcpy(timefmt,DEFAULT_TIME_FORMAT);
  567.     sizefmt = SIZEFMT_KMG;
  568.  
  569.     chdir_file(file);
  570.  
  571.     while(1) {
  572.         if(!find_string(f,STARTING_SEQUENCE,fd)) {
  573.             if(get_directive(f,directive))
  574.                 return;
  575.             if(!strcmp(directive,"exec")) {
  576.                 if(noexec) {
  577.                     sprintf(errstr,"httpd: exec used but not allowed in %s",
  578.                             file);
  579.                     log_error_noclose(errstr);
  580.                     bytes_sent += fprintf(fd,"%s",error);
  581.                     ret = find_string(f,ENDING_SEQUENCE,NULL);
  582.                 } else 
  583.                     ret=handle_exec(f,fd,file,path_args,args,error,env);
  584.             } 
  585.             else if(!strcmp(directive,"config"))
  586.                 ret=handle_config(f,fd,file,error,timefmt,&sizefmt,env);
  587.             else if(!strcmp(directive,"include"))
  588.                 ret=handle_include(f,fd,file,env,error);
  589.             else if(!strcmp(directive,"echo"))
  590.                 ret=handle_echo(f,fd,file,error,env);
  591.             else if(!strcmp(directive,"fsize"))
  592.                 ret=handle_fsize(f,fd,file,error,sizefmt,env);
  593.             else if(!strcmp(directive,"flastmod"))
  594.                 ret=handle_flastmod(f,fd,file,error,timefmt,env);
  595.             else {
  596.                 sprintf(errstr,"httpd: unknown directive %s in parsed doc %s",
  597.                         directive,file);
  598.                 log_error_noclose(errstr);
  599.                 bytes_sent += fprintf(fd,"%s",error);
  600.                 ret=find_string(f,ENDING_SEQUENCE,NULL);
  601.             }
  602.             if(ret) {
  603.                 sprintf(errstr,"httpd: premature EOF in parsed file %s",file);
  604.                 log_error_noclose(errstr);
  605.                 return;
  606.             }
  607.         } else 
  608.             return;
  609.     }
  610. }
  611.  
  612. /* Called by send_file */
  613.  
  614. void send_parsed_file(char *file, FILE *fd, char *path_args, char *args,
  615.                       int noexec) 
  616. {
  617.     FILE *f;
  618.     char **env;
  619.  
  620.     if(!(f=fopen(file,"r"))) {
  621.         log_reason("file permissions deny server access",file);
  622.         unmunge_name(file);
  623.         die(FORBIDDEN,file,fd);
  624.     }
  625.     strcpy(content_type,"text/html");
  626.     if(!assbackwards)
  627.         send_http_header(fd);
  628.     if(header_only)
  629.         return;
  630.  
  631.     /* Make sure no children inherit our buffers */
  632.     fflush(fd);
  633.     assbackwards = 1; /* make sure no headers get inserted anymore */
  634.     alarm(timeout);
  635.  
  636.     env = add_include_vars(in_headers_env,file,path_args,args,
  637.                            DEFAULT_TIME_FORMAT,fd);
  638.     env = add_common_vars(env,fd);
  639.  
  640.     send_parsed_content(file,f,fd,path_args,args,env,noexec);
  641.     free_env(env);
  642. }
  643.