home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 9 / CDACTUAL9.iso / share / Os2 / varios / APACHE / UTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-15  |  28.4 KB  |  1,129 lines

  1.  
  2. /* ====================================================================
  3.  * Copyright (c) 1995 The Apache Group.  All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  *
  9.  * 1. Redistributions of source code must retain the above copyright
  10.  *    notice, this list of conditions and the following disclaimer. 
  11.  *
  12.  * 2. Redistributions in binary form must reproduce the above copyright
  13.  *    notice, this list of conditions and the following disclaimer in
  14.  *    the documentation and/or other materials provided with the
  15.  *    distribution.
  16.  *
  17.  * 3. All advertising materials mentioning features or use of this
  18.  *    software must display the following acknowledgment:
  19.  *    "This product includes software developed by the Apache Group
  20.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  21.  *
  22.  * 4. The names "Apache Server" and "Apache Group" must not be used to
  23.  *    endorse or promote products derived from this software without
  24.  *    prior written permission.
  25.  *
  26.  * 5. Redistributions of any form whatsoever must retain the following
  27.  *    acknowledgment:
  28.  *    "This product includes software developed by the Apache Group
  29.  *    for use in the Apache HTTP server project (http://www.apache.org/)."
  30.  *
  31.  * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
  32.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  33.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  34.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
  35.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  36.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  37.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  38.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  40.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  41.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  42.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  43.  * ====================================================================
  44.  *
  45.  * This software consists of voluntary contributions made by many
  46.  * individuals on behalf of the Apache Group and was originally based
  47.  * on public domain software written at the National Center for
  48.  * Supercomputing Applications, University of Illinois, Urbana-Champaign.
  49.  * For more information on the Apache Group and the Apache HTTP server
  50.  * project, please see <http://www.apache.org/>.
  51.  *
  52.  */
  53.  
  54.  
  55. /*
  56.  * str.c: string utility things
  57.  * 
  58.  * 3/21/93 Rob McCool
  59.  * 
  60.  */
  61.  
  62.  
  63. #include "httpd.h"
  64. #include "http_conf_globals.h"    /* for user_id & group_id */
  65. #ifdef QNX
  66. #include <time.h>
  67. #endif
  68.  
  69. #ifdef NOTDEF
  70. extern char** environ;
  71.  
  72. /* taken from bdflush-1.5 for Linux source code */
  73. void inststr(char *dst[], int argc, char *src)
  74. {
  75.     if (strlen(src) <= strlen(dst[0]))
  76.     {
  77.         char *ptr;
  78.  
  79.         for (ptr = dst[0]; *ptr; *(ptr++) = '\0');
  80.  
  81.         strcpy(dst[0], src);
  82.     } else
  83.     {
  84.         /* stolen from the source to perl 4.036 (assigning to $0) */
  85.         char *ptr, *ptr2;
  86.         int count;
  87.         ptr = dst[0] + strlen(dst[0]);
  88.         for (count = 1; count < argc; count++) {
  89.             if (dst[count] == ptr + 1)
  90.                 ptr += strlen(++ptr);
  91.         }
  92.         if (environ[0] == ptr + 1) {
  93.             for (count = 0; environ[count]; count++)
  94.                 if (environ[count] == ptr + 1)
  95.                     ptr += strlen(++ptr);
  96.         }
  97.         count = 0;
  98.         for (ptr2 = dst[0]; ptr2 <= ptr; ptr2++) {
  99.             *ptr2 = '\0';
  100.             count++;
  101.         }
  102.         strncpy(dst[0], src, count);
  103.     }
  104. }
  105. #endif
  106.  
  107. char *get_time() {
  108.     time_t t;
  109.     char *time_string;
  110.  
  111.     t=time(NULL);
  112.     time_string = ctime(&t);
  113.     time_string[strlen(time_string) - 1] = '\0';
  114.     return (time_string);
  115. }
  116.  
  117. char *ht_time(pool *p, time_t t, char *fmt, int gmt) {
  118.     char ts[MAX_STRING_LEN];
  119.     struct tm *tms;
  120.  
  121.     tms = (gmt ? gmtime(&t) : localtime(&t));
  122.  
  123.     /* check return code? */
  124.     strftime(ts,MAX_STRING_LEN,fmt,tms);
  125.     return pstrdup (p, ts);
  126. }
  127.  
  128. char *gm_timestr_822(pool *p, time_t sec) {
  129.     return ht_time(p, sec, HTTP_TIME_FORMAT, 1);
  130. }
  131.  
  132. /* What a pain in the ass. */
  133. struct tm *get_gmtoff(long *tz) {
  134.     time_t tt;
  135.     struct tm *t;
  136.  
  137.     tt = time(NULL);
  138.     t = localtime(&tt);
  139. #if defined(HAS_GMTOFF)
  140.     *tz = t->tm_gmtoff;
  141. #elif !defined(NO_TIMEZONE)
  142.     *tz = - timezone;
  143.     if(t->tm_isdst)
  144.         *tz += 3600;
  145. #else
  146.   {
  147.     static struct tm loc_t;
  148.  
  149.     loc_t = *t;   /* save it */
  150.     t = gmtime(&tt);
  151.     *tz = mktime(&loc_t) - mktime(t);
  152.     t = &loc_t; /* return pointer to saved time */
  153.   }
  154. #endif
  155.     return t;
  156. }
  157.  
  158.  
  159. /* Match = 0, NoMatch = 1, Abort = -1 */
  160. /* Based loosely on sections of wildmat.c by Rich Salz
  161.  * Hmmm... shouldn't this really go component by component?
  162.  */
  163. int strcmp_match(char *str, char *exp) {
  164.     int x,y;
  165.  
  166.     for(x=0,y=0;exp[y];++y,++x) {
  167.         if((!str[x]) && (exp[y] != '*'))
  168.             return -1;
  169.         if(exp[y] == '*') {
  170.             while(exp[++y] == '*');
  171.             if(!exp[y])
  172.                 return 0;
  173.             while(str[x]) {
  174.                 int ret;
  175.                 if((ret = strcmp_match(&str[x++],&exp[y])) != 1)
  176.                     return ret;
  177.             }
  178.             return -1;
  179.         } else 
  180.             if((exp[y] != '?') && (str[x] != exp[y]))
  181.                 return 1;
  182.     }
  183.     return (str[x] != '\0');
  184. }
  185.  
  186. int is_matchexp(char *str) {
  187.     register int x;
  188.  
  189.     for(x=0;str[x];x++)
  190.         if((str[x] == '*') || (str[x] == '?'))
  191.             return 1;
  192.     return 0;
  193. }
  194.  
  195. /*
  196.  * Parse .. so we don't compromise security
  197.  */
  198. void getparents(char *name)
  199. {
  200.     int l, w;
  201.  
  202.     /* Four paseses, as per RFC 1808 */
  203.     /* a) remove ./ path segments */
  204.  
  205.     for (l=0, w=0; name[l] != '\0';)
  206.     {
  207.     if (name[l] == '.' && name[l+1] == '/' && (l == 0 || name[l-1] == '/'))
  208.         l += 2;
  209.     else
  210.         name[w++] = name[l++];
  211.     }
  212.  
  213.     /* b) remove trailing . path, segment */
  214.     if (w == 1 && name[0] == '.') w--;
  215.     else if (w > 1 && name[w-1] == '.' && name[w-2] == '/') w--;
  216.     name[w] = '\0';
  217.  
  218.     /* c) remove all xx/../ segments. (including leading ../ and /../) */
  219.     l = 0;
  220.  
  221.     while(name[l]!='\0') {
  222.         if(name[l] == '.' && name[l+1] == '.' && name[l+2] == '/' &&
  223.         (l == 0 || name[l-1] == '/')) {
  224.         register int m=l+3,n;
  225.  
  226.         l=l-2;
  227.         if(l>=0) {
  228.             while(l >= 0 && name[l] != '/') l--;
  229.             l++;
  230.         }
  231.         else l=0;
  232.         n=l;
  233.         while((name[n]=name[m])) (++n,++m);
  234.             }
  235.     else ++l;
  236.     }
  237.  
  238.     /* d) remove trailing xx/.. segment. */
  239.     if (l == 2 && name[0] == '.' && name[1] == '.') name[0] = '\0';
  240.     else if (l > 2 && name[l-1] == '.' && name[l-2] == '.' && name[l-3] == '/')
  241.     {
  242.     l = l - 4;
  243.     if (l >= 0)
  244.     {
  245.         while (l >= 0 && name[l] != '/') l--;
  246.         l++;
  247.     }
  248.     else l = 0;
  249.     name[l] = '\0';
  250.     }
  251.  
  252. void no2slash(char *name) {
  253.     register int x,y;
  254.  
  255.     for(x=0; name[x];)
  256.         if(x && (name[x-1] == '/') && (name[x] == '/'))
  257.             for(y=x+1;name[y-1];y++)
  258.                 name[y-1] = name[y];
  259.     else x++;
  260. }
  261.  
  262. char *make_dirstr(pool *p, char *s, int n) {
  263.     register int x,f;
  264.     char *res;
  265.  
  266.     for(x=0,f=0;s[x];x++) {
  267.         if(s[x] == '/')
  268.             if((++f) == n) {
  269.         res = palloc(p, x + 2);
  270.         strncpy (res, s, x);
  271.         res[x] = '/';
  272.         res[x+1] = '\0';
  273.                 return res;
  274.             }
  275.     }
  276.  
  277.     if (s[strlen(s) - 1] == '/')
  278.         return pstrdup (p, s);
  279.     else
  280.         return pstrcat (p, s, "/", NULL);
  281. }
  282.  
  283. int count_dirs(char *path) {
  284.     register int x,n;
  285.  
  286.     for(x=0,n=0;path[x];x++)
  287.         if(path[x] == '/') n++;
  288.     return n;
  289. }
  290.  
  291.  
  292. void chdir_file(char *file) {
  293.     int i;
  294.  
  295.     if((i = rind(file,'/')) == -1)
  296.         return;
  297.     file[i] = '\0';
  298.     chdir(file);
  299.     file[i] = '/';
  300. }
  301.  
  302. char *getword(pool* atrans, char **line, char stop) {
  303.     int pos = ind(*line, stop);
  304.     char *res;
  305.  
  306.     if (pos == -1) {
  307.         res = pstrdup (atrans, *line);
  308.     *line += strlen (*line);
  309.     return res;
  310.     }
  311.   
  312.     res = palloc(atrans, pos + 1);
  313.     strncpy (res, *line, pos);
  314.     res[pos] = '\0';
  315.     
  316.     while ((*line)[pos] == stop) ++pos;
  317.     
  318.     *line += pos;
  319.     
  320.     return res;
  321. }
  322.  
  323. /* Get a word, (new) config-file style --- quoted strings and backslashes
  324.  * all honored
  325.  */
  326.  
  327. char *substring_conf (pool *p, char *start, int len)
  328. {
  329.     char *result = palloc (p, len + 2);
  330.     char *resp = result;
  331.     int i;
  332.  
  333.     for (i = 0; i < len; ++i) {
  334.         if (start[i] == '\\') 
  335.         *resp++ = start[++i];
  336.     else
  337.         *resp++ = start[i];
  338.     }
  339.  
  340.     *resp++ = '\0';
  341.     return result;
  342. }
  343.  
  344. char *getword_conf(pool* p, char **line) {
  345.     char *str = *line, *strend, *res;
  346.     char quote;
  347.  
  348.     while (*str && isspace (*str))
  349.         ++str;
  350.  
  351.     if (!*str) {
  352.         *line = str;
  353.         return "";
  354.     }
  355.  
  356.     if ((quote = *str) == '"' || quote == '\'') {
  357.         strend = str + 1;
  358.     while (*strend && *strend != quote) {
  359.         if (*strend == '\\' && strend[1]) strend += 2;
  360.         else ++strend;
  361.     }
  362.     res = substring_conf (p, str + 1, strend - str - 1);
  363.  
  364.     if (*strend == quote) ++strend;
  365.     } else {
  366.         strend = str;
  367.     while (*strend && !isspace (*strend))
  368.         if (*strend == '\\' && strend[1]) strend += 2;
  369.         else ++strend;
  370.  
  371.     res = substring_conf (p, str, strend - str);
  372.     }
  373.  
  374.     while (*strend && isspace(*strend)) ++ strend;
  375.     *line = strend;
  376.     return res;
  377. }
  378.  
  379. void cfg_getword(char *word, char *line) {
  380.     int x=0,y;
  381.     
  382.     for(x=0;line[x] && isspace(line[x]);x++);
  383.     y=0;
  384.     while(1) {
  385.         if(!(word[y] = line[x]))
  386.             break;
  387.         if(isspace(line[x]))
  388.             if((!x) || (line[x-1] != '\\'))
  389.                 break;
  390.         if(line[x] != '\\') ++y;
  391.         ++x;
  392.     }
  393.     word[y] = '\0';
  394.     while(line[x] && isspace(line[x])) ++x;
  395.     for(y=0;(line[y] = line[x]);++x,++y);
  396. }
  397.  
  398. int
  399. cfg_getline(char *s, int n, FILE *f) {
  400.     register int i=0, c;
  401.  
  402.     s[0] = '\0';
  403.     /* skip leading whitespace */
  404.     do {
  405.         c = getc(f);
  406.     } while (c == '\t' || c == ' ');
  407.  
  408.     while(1) {
  409.         if((c == '\t') || (c == ' ')) {
  410.             s[i++] = ' ';
  411.             while((c == '\t') || (c == ' ')) 
  412.                 c = getc(f);
  413.         }
  414.         if(c == CR) {
  415.             c = getc(f);
  416.         }
  417.         if(c == EOF || c == 0x4 || c == LF || i == (n-1)) {
  418.             /* blast trailing whitespace */
  419.             while(i && (s[i-1] == ' ')) --i;
  420.             s[i] = '\0';
  421.             return (feof(f) ? 1 : 0);
  422.         }
  423.         s[i] = c;
  424.         ++i;
  425.         c = getc(f);
  426.     }
  427. }
  428.  
  429. char *escape_shell_cmd(pool *p, char *s) {
  430.     register int x,y,l;
  431.     char *cmd;
  432.  
  433.     l=strlen(s);
  434.     cmd = palloc (p, 2 * l + 1); /* Be safe */
  435.     strcpy (cmd, s);
  436.     
  437.     for(x=0;cmd[x];x++) {
  438.  
  439. #ifdef __EMX__
  440.         /* Don't allow '&' in parameters under OS/2. */
  441.         /* This can be used to send commands to the shell. */
  442.         if (cmd[x] == '&') {
  443.             cmd[x] = ' ';
  444.         }
  445. #endif
  446.  
  447.         if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
  448.             for(y=l+1;y>x;y--)
  449.                 cmd[y] = cmd[y-1];
  450.             l++; /* length has been increased */
  451.             cmd[x] = '\\';
  452.             x++; /* skip the character */
  453.         }
  454.     }
  455.  
  456.     return cmd;
  457. }
  458.  
  459. void plustospace(char *str) {
  460.     register int x;
  461.  
  462.     for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
  463. }
  464.  
  465. void spacetoplus(char *str) {
  466.     register int x;
  467.  
  468.     for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
  469. }
  470.  
  471. char x2c(char *what) {
  472.     register char digit;
  473.  
  474.     digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
  475.     digit *= 16;
  476.     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
  477.     return(digit);
  478. }
  479.  
  480. /*
  481.  * Unescapes a URL.
  482.  * Returns 0 on success, non-zero on error
  483.  * Failure is due to
  484.  *   bad % escape       returns BAD_REQUEST
  485.  *
  486.  *   decoding %00 -> \0
  487.  *   decoding %2f -> /   (a special character)
  488.  *                      returns NOT_FOUND
  489.  */
  490. int
  491. unescape_url(char *url) {
  492.     register int x,y, badesc, badpath;
  493.  
  494.     badesc = 0;
  495.     badpath = 0;
  496.     for(x=0,y=0;url[y];++x,++y) {
  497.     if (url[y] != '%') url[x] = url[y];
  498.     else
  499.     {
  500.         if (!isxdigit(url[y+1]) || !isxdigit(url[y+2]))
  501.         {
  502.         badesc = 1;
  503.         url[x] = '%';
  504.         } else
  505.         {
  506.         url[x] = x2c(&url[y+1]);
  507.         y += 2;
  508.         if (url[x] == '/' || url[x] == '\0') badpath = 1;
  509.         }
  510.         }
  511.     }
  512.     url[x] = '\0';
  513.     if (badesc) return BAD_REQUEST;
  514.     else if (badpath) return NOT_FOUND;
  515.     else return OK;
  516. }
  517.  
  518. char *construct_url(pool *p, char *uri, server_rec *s) {
  519.     char portnum[10];        /* Long enough.  Really! */
  520.   
  521.     if (s->port == 80) {
  522.         return pstrcat (p, "http://", s->server_hostname, uri, NULL);
  523.     } else {
  524.         sprintf (portnum, "%d", s->port);
  525.     return pstrcat (p, "http://", s->server_hostname, ":", portnum, uri,
  526.             NULL);
  527.     }
  528. }
  529.  
  530. #define c2x(what,where) sprintf(where,"%%%02x",what)
  531.  
  532. /*
  533. escape_path_segment() escapes a path segment, as defined in RFC 1808. This
  534. routine is (should be) OS independent.
  535.  
  536. os_escape_path() converts an OS path to a URL, in an OS dependent way. In all
  537. cases if a ':' occurs before the first '/' in the URL, the URL should be
  538. prefixed with "./" (or the ':' escaped). In the case of Unix, this means
  539. leaving '/' alone, but otherwise doing what escape_path_segment() does. For
  540. efficiency reasons, we don't use escape_path_segment(), which is provided for
  541. reference. Again, RFC 1808 is where this stuff is defined.
  542. */
  543.  
  544. char *escape_path_segment(pool *p, const char *segment) {
  545.     register int x,y;
  546.     char *copy = palloc (p, 3 * strlen (segment) + 1);
  547.             
  548.     for(x=0,y=0; segment[x]; x++,y++) {
  549.       char c=segment[x];
  550.       if((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c >'9')
  551.      && ind("$-_.+!*'(),:@&=~",c) == -1)
  552.     {
  553.       c2x(c,©[y]);
  554.       y+=2;
  555.     }
  556.       else
  557.     copy[y]=c;
  558.     }
  559.     copy[y] = '\0';
  560.     return copy;
  561. }
  562.  
  563. char *os_escape_path(pool *p,const char *path) {
  564.   char *copy=palloc(p,3*strlen(path)+3);
  565.   char *s=copy;
  566.   int colon=ind(path,':');
  567.   int slash=ind(path,'/');
  568.  
  569.   if(colon >= 0 && (colon < slash || slash < 0))
  570.     {
  571.       *s++='.';
  572.       *s++='/';
  573.     }
  574.   for( ; *path ; ++path)
  575.     {
  576.       char c=*path;
  577.       if((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') && (c < '0' || c >'9')
  578.      && ind("$-_.+!*'(),:@&=/~",c) == -1)
  579.     {
  580.       c2x(c,s);
  581.       s+=3;
  582.     }
  583.       else
  584.     *s++=c;
  585.     }
  586.   *s='\0';
  587.   return copy;
  588. }
  589.  
  590. char *escape_uri(pool *p, char *uri) {
  591.     register int x,y;
  592.     char *copy = palloc (p, 3 * strlen (uri) + 1);
  593.             
  594.     for(x=0,y=0; uri[x]; x++,y++) {
  595.         if (ind (":% ?+&",(copy[y] = uri[x])) != -1) {
  596.             c2x(uri[x],©[y]);
  597.             y+=2;
  598.         }
  599.     }
  600.     copy[y] = '\0';
  601.     return copy;
  602. }
  603.  
  604. char *
  605. escape_html(pool *p, const char *s)
  606. {
  607.     int i, j;
  608.     char *x;
  609.  
  610. /* first, count the number of extra characters */
  611.     for (i=0, j=0; s[i] != '\0'; i++)
  612.     if (s[i] == '<' || s[i] == '>') j += 3;
  613.     else if (s[i] == '&') j += 4;
  614.  
  615.     if (j == 0) return pstrdup(p, s);
  616.     x = palloc(p, i + j + 1);
  617.     for (i=0, j=0; s[i] != '\0'; i++, j++)
  618.     if (s[i] == '<')
  619.     {
  620.         memcpy(&x[j], "<", 4);
  621.         j += 3;
  622.     } else if (s[i] == '>')
  623.     {
  624.         memcpy(&x[j], ">", 4);
  625.         j += 3;
  626.     } else if (s[i] == '&')
  627.     {
  628.         memcpy(&x[j], "&", 5);
  629.         j += 4;
  630.     } else
  631.             x[j] = s[i];
  632.  
  633.     x[j] = '\0';
  634.     return x;
  635. }
  636.  
  637. #ifdef NOTDEF
  638.  
  639. void escape_url(char *url) {
  640.     register int x,y;
  641.     register char digit;
  642.     char *copy;
  643.  
  644.     copy = strdup(url);
  645.             
  646.     for(x=0,y=0;copy[x];x++,y++) {
  647.         if(ind("% ?+&",url[y] = copy[x]) != -1) {
  648.             c2x(copy[x],&url[y]);
  649.             y+=2;
  650.         }
  651.     }
  652.     url[y] = '\0';
  653.     free(copy);
  654. }
  655.  
  656. #endif
  657.  
  658. int is_directory(char *path) {
  659.     struct stat finfo;
  660.  
  661.     if(stat(path,&finfo) == -1)
  662.         return 0; /* in error condition, just return no */
  663.  
  664.     return(S_ISDIR(finfo.st_mode));
  665. }
  666.  
  667. char *make_full_path(pool *a, char *src1,char *src2) {
  668.     register int x;
  669.  
  670.     x = strlen(src1);
  671.     if (x == 0) return pstrcat (a, "/", src2, NULL);
  672.  
  673.     if (src1[x - 1] != '/') return pstrcat (a, src1, "/", src2, NULL);
  674.     else return pstrcat (a, src1, src2, NULL);
  675. }
  676.  
  677. int is_url(char *u) {
  678.     register int x;
  679.  
  680.     for(x=0;u[x] != ':';x++)
  681.         if((!u[x]) || (!isalpha(u[x])))
  682.             return 0;
  683.  
  684.     if((u[x+1] == '/') && (u[x+2] == '/'))
  685.         return 1;
  686.     else return 0;
  687. }
  688.  
  689. int can_exec(struct stat *finfo) {
  690. #ifdef __EMX__
  691.     /* OS/2 dosen't have Users and Groups */
  692.     return (finfo->st_mode & S_IEXEC);
  693. #else    
  694.     if(user_id == finfo->st_uid)
  695.         if(finfo->st_mode & S_IXUSR)
  696.             return 1;
  697.     if(group_id == finfo->st_gid)
  698.         if(finfo->st_mode & S_IXGRP)
  699.             return 1;
  700.     return (finfo->st_mode & S_IXOTH);
  701. #endif
  702. }
  703.  
  704. #ifdef NEED_STRDUP
  705. char *strdup (char *str)
  706. {
  707.   char *dup;
  708.  
  709.   if(!(dup = (char *)malloc (strlen (str) + 1)))
  710.       return NULL;
  711.   dup = strcpy (dup, str);
  712.  
  713.   return dup;
  714. }
  715. #endif
  716.  
  717. /* The following two routines were donated for SVR4 by Andreas Vogel */
  718. #ifdef NEED_STRCASECMP
  719. int strcasecmp (const char *a, const char *b)
  720. {
  721.     const char *p = a;
  722.     const char *q = b;
  723.     for (p = a, q = b; *p && *q; p++, q++)
  724.     {
  725.       int diff = tolower(*p) - tolower(*q);
  726.       if (diff) return diff;
  727.     }
  728.     if (*p) return 1;       /* p was longer than q */
  729.     if (*q) return -1;      /* p was shorter than q */
  730.     return 0;               /* Exact match */
  731. }
  732.  
  733. #endif
  734.  
  735. #ifdef NEED_STRNCASECMP
  736. int strncasecmp (const char *a, const char *b, int n)
  737. {
  738.     const char *p = a;
  739.     const char *q = b;
  740.  
  741.     for (p = a, q = b; /*NOTHING*/; p++, q++)
  742.     {
  743.       int diff;
  744.       if (p == a + n) return 0;     /*   Match up to n characters */
  745.       if (!(*p && *q)) return *p - *q;
  746.       diff = tolower(*p) - tolower(*q);
  747.       if (diff) return diff;
  748.     }
  749.     /*NOTREACHED*/
  750. }
  751. #endif
  752.  
  753.  
  754.  
  755. #ifdef NEED_INITGROUPS
  756. int initgroups(const char *name, gid_t basegid)
  757. {
  758. #ifdef QNX
  759. /* QNX does not appear to support supplementary groups.
  760. Ben <ben@algroup.co.uk> */
  761.     return 0;
  762. #else /* ndef QNX */
  763.   gid_t groups[NGROUPS_MAX];
  764.   struct group *g;
  765.   int index = 0;
  766.  
  767.   setgrent();
  768.  
  769.   groups[index++] = basegid;
  770.  
  771.   while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
  772.     if (g->gr_gid != basegid)
  773.     {
  774.       char **names;
  775.  
  776.       for (names = g->gr_mem; *names != NULL; ++names)
  777.         if (!strcmp(*names, name))
  778.           groups[index++] = g->gr_gid;
  779.     }
  780.  
  781.   endgrent();
  782.  
  783.   return setgroups(index, groups);
  784. #endif /* def QNX */
  785. }
  786. #endif /* def NEED_INITGROUPS */
  787.  
  788. #ifdef NEED_WAITPID
  789. /* From ikluft@amdahl.com */
  790. /* this is not ideal but it works for SVR3 variants */
  791. /* httpd does not use the options so this doesn't implement them */
  792. int waitpid(pid_t pid, int *statusp, int options)
  793. {
  794.     int tmp_pid;
  795.     if ( kill ( pid,0 ) == -1) {
  796.         errno=ECHILD;
  797.         return -1;
  798.     }
  799.     while ((( tmp_pid = wait(statusp)) != pid) && ( tmp_pid != -1 ));
  800.     return tmp_pid;
  801. }
  802. #endif
  803.  
  804. int ind(const char *s, char c) {
  805.     register int x;
  806.  
  807.     for(x=0;s[x];x++)
  808.         if(s[x] == c) return x;
  809.  
  810.     return -1;
  811. }
  812.  
  813. int rind(const char *s, char c) {
  814.     register int x;
  815.  
  816.     for(x=strlen(s)-1;x != -1;x--)
  817.         if(s[x] == c) return x;
  818.  
  819.     return -1;
  820. }
  821.  
  822. void str_tolower(char *str) {
  823.     while(*str) {
  824.         *str = tolower(*str);
  825.         ++str;
  826.     }
  827. }
  828.         
  829. uid_t uname2id(char *name) {
  830.     struct passwd *ent;
  831.  
  832.     if(name[0] == '#') 
  833.         return(atoi(&name[1]));
  834.  
  835.     if(!(ent = getpwnam(name))) {
  836.         fprintf(stderr,"httpd: bad user name %s\n",name);
  837.         exit(1);
  838.     }
  839.     else return(ent->pw_uid);
  840. }
  841.  
  842. gid_t gname2id(char *name) {
  843.     struct group *ent;
  844.  
  845.     if(name[0] == '#') 
  846.         return(atoi(&name[1]));
  847.  
  848.     if(!(ent = getgrnam(name))) {
  849.         fprintf(stderr,"httpd: bad group name %s\n",name);
  850.         exit(1);
  851.     }
  852.     else return(ent->gr_gid);
  853. }
  854.  
  855. #if 0
  856. int get_portnum(int sd) {
  857.     struct sockaddr addr;
  858.     int len;
  859.  
  860.     len = sizeof(struct sockaddr);
  861.     if(getsockname(sd,&addr,&len) < 0)
  862.         return -1;
  863.     return ntohs(((struct sockaddr_in *)&addr)->sin_port);
  864. }
  865.  
  866. struct in_addr get_local_addr(int sd) {
  867.     struct sockaddr addr;
  868.     int len;
  869.  
  870.     len = sizeof(struct sockaddr);
  871.     if(getsockname(sd,&addr,&len) < 0) {
  872.         fprintf (stderr, "Can't get local host address!\n");
  873.     perror ("getsockname");
  874.     exit(1);
  875.     }
  876.          
  877.     return ((struct sockaddr_in *)&addr)->sin_addr;
  878. }
  879. #endif
  880.  
  881. unsigned long get_virthost_addr (char *w, int wild_allowed) {
  882.     struct hostent *hep;
  883.     unsigned long my_addr;
  884.     
  885.     if (wild_allowed && !strcmp(w, "*")) 
  886.     return htonl(INADDR_ANY);
  887.     
  888.     my_addr = inet_addr(w);
  889.     if (my_addr != ((unsigned long) 0xffffffff))
  890.     return my_addr;
  891.  
  892.     hep = gethostbyname(w);
  893.         
  894.     if ((!hep) || (hep->h_addrtype != AF_INET || !hep->h_addr_list[0])) {
  895.     fprintf (stderr, "Cannot resolve host name %s --- exiting!\n", w);
  896.     exit(1);
  897.     }
  898.         
  899.     if (hep->h_addr_list[1]) {
  900.     fprintf(stderr, "Host %s has multiple addresses ---\n", w);
  901.     fprintf(stderr, "you must choose one explicitly for use as\n");
  902.     fprintf(stderr, "a virtual host.  Exiting!!!\n");
  903.     exit(1);
  904.     }
  905.         
  906.     return ((struct in_addr *)(hep->h_addr))->s_addr;
  907. }
  908.  
  909. #ifdef DEBUG_ACCESS
  910. /* Host name and IP address used if getpeername() fails.
  911.  * The most frequent cause of this is running the server in inetd-mode
  912.  * with the tty as input and output, under the debugger.
  913.  */
  914. #define NO_SUCH_HOST_NAME "volterra.ai.mit.edu"
  915. #define NO_SUCH_HOST_ADDR "128.52.39.173"
  916. #else
  917. #define NO_SUCH_HOST_NAME "UNKNOWN_HOST"
  918. #define NO_SUCH_HOST_ADDR "UNKNOWN_IP"
  919. #endif
  920.  
  921. void get_remote_host(conn_rec *conn)
  922. {
  923.     struct sockaddr addr;
  924.     int len;
  925.     struct in_addr *iaddr;
  926. #if defined(MAXIMUM_DNS) || !defined(MINIMAL_DNS)
  927.     struct hostent *hptr;
  928. #endif
  929.  
  930.     len = sizeof(struct sockaddr);
  931.  
  932.     if ((getpeername(fileno(conn->client), &addr, &len)) < 0) {
  933.     conn->remote_name = conn->remote_host = NO_SUCH_HOST_NAME;
  934.     conn->remote_ip = NO_SUCH_HOST_ADDR;
  935.         return;
  936.     }
  937.  
  938.     iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
  939. #ifndef MINIMAL_DNS
  940.     hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
  941.     if(hptr) {
  942.         conn->remote_host = pstrdup(conn->pool, (void *)hptr->h_name);
  943.         conn->remote_name = conn->remote_host;
  944.         str_tolower (conn->remote_host);
  945.     }
  946.     else 
  947. #endif
  948.         conn->remote_host = NULL;
  949.  
  950. #ifdef MAXIMUM_DNS
  951.     /* Grrr. Check THAT name to make sure it's really the name of the addr. */
  952.     /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
  953.     if (conn->remote_host) {
  954.         char **haddr;
  955.  
  956.         hptr = gethostbyname(conn->remote_host);
  957.         if (hptr) {
  958.             for(haddr=hptr->h_addr_list;*haddr;haddr++) {
  959.                 if(((struct in_addr *)(*haddr))->s_addr == iaddr->s_addr)
  960.                     break;
  961.             }
  962.         }
  963.         if((!hptr) || (!(*haddr)))
  964.         conn->remote_host = conn->remote_name = NULL;
  965.     }
  966. #endif
  967.     conn->remote_ip = pstrdup (conn->pool, inet_ntoa(*iaddr));
  968.     if(!conn->remote_host){     
  969.         conn->remote_name = conn->remote_ip;
  970.     }
  971.     if (!conn->remote_name) {
  972.     conn->remote_name = "UNKNOWN_HOST";
  973.     }
  974. }
  975.  
  976. #ifdef NOTDEF    
  977.     
  978. char *get_remote_logname(FILE *fd) {
  979.     int len;
  980.     char *result;
  981. #if defined(NEXT) || defined(BSD4_4) || defined(SOLARIS2) || defined(LINUX) || defined(__EMX__)
  982.     struct sockaddr sa_server, sa_client;
  983. #else
  984.     struct sockaddr_in sa_server,sa_client;
  985. #endif
  986.  
  987.     len = sizeof(sa_client);
  988.     if(getpeername(fileno(stdout),&sa_client,&len) != -1) {
  989.         len = sizeof(sa_server);
  990.         if(getsockname(fileno(stdout),&sa_server,&len) == -1)
  991.             result = "unknown";
  992.         else
  993.             result = rfc931((struct sockaddr_in *) & sa_client,
  994.                                     (struct sockaddr_in *) & sa_server);
  995.     }
  996.     else result = "unknown";
  997.  
  998.     return result; /* robm=pinhead */
  999. }
  1000. #endif    
  1001.  
  1002. static char *find_fqdn(pool *a, struct hostent *p) {
  1003.     int x;
  1004.  
  1005.     if(ind(p->h_name,'.') == -1) {
  1006.         for(x=0;p->h_aliases[x];++x) {
  1007.             if((ind(p->h_aliases[x],'.') != -1) && 
  1008.                (!strncmp(p->h_aliases[x],p->h_name,strlen(p->h_name))))
  1009.                 return pstrdup(a, p->h_aliases[x]);
  1010.         }
  1011.         return NULL;
  1012.     } else return pstrdup(a, (void *)p->h_name);
  1013. }
  1014.  
  1015. char *get_local_host(pool *a)
  1016. {
  1017.     char str[128];
  1018.     int len = 128;
  1019.     char *server_hostname;
  1020.  
  1021.     struct hostent *p;
  1022.     gethostname(str, len);
  1023.     if((!(p=gethostbyname(str))) || (!(server_hostname = find_fqdn(a, p)))) {
  1024.         fprintf(stderr,"httpd: cannot determine local host name.\n");
  1025.     fprintf(stderr,"Use ServerName to set it manually.\n");
  1026.     exit(1);
  1027.     }
  1028.  
  1029.     return server_hostname;
  1030. }
  1031.  
  1032. /* aaaack but it's fast and const should make it shared text page. */
  1033. const int pr2six[256]={
  1034.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1035.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  1036.     52,53,54,55,56,57,58,59,60,61,64,64,64,64,64,64,64,0,1,2,3,4,5,6,7,8,9,
  1037.     10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  1038.     28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  1039.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1040.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1041.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1042.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1043.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  1044.     64,64,64,64,64,64,64,64,64,64,64,64,64
  1045. };
  1046.  
  1047. char *uudecode(pool *p, char *bufcoded) {
  1048.     int nbytesdecoded;
  1049.     register unsigned char *bufin;
  1050.     register char *bufplain;
  1051.     register unsigned char *bufout;
  1052.     register int nprbytes;
  1053.     
  1054.     /* Strip leading whitespace. */
  1055.     
  1056.     while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
  1057.     
  1058.     /* Figure out how many characters are in the input buffer.
  1059.      * Allocate this many from the per-transaction pool for the result.
  1060.      */
  1061.     bufin = (unsigned char *)bufcoded;
  1062.     while(pr2six[*(bufin++)] <= 63);
  1063.     nprbytes = (char *)bufin - bufcoded - 1;
  1064.     nbytesdecoded = ((nprbytes+3)/4) * 3;
  1065.  
  1066.     bufplain = palloc(p, nbytesdecoded + 1);
  1067.     bufout = (unsigned char *)bufplain;
  1068.     
  1069.     bufin = (unsigned char *)bufcoded;
  1070.     
  1071.     while (nprbytes > 0) {
  1072.         *(bufout++) = 
  1073.             (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  1074.         *(bufout++) = 
  1075.             (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  1076.         *(bufout++) = 
  1077.             (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  1078.         bufin += 4;
  1079.         nprbytes -= 4;
  1080.     }
  1081.     
  1082.     if(nprbytes & 03) {
  1083.         if(pr2six[bufin[-2]] > 63)
  1084.             nbytesdecoded -= 2;
  1085.         else
  1086.             nbytesdecoded -= 1;
  1087.     }
  1088.     bufplain[nbytesdecoded] = '\0';
  1089.     return bufplain;
  1090. }
  1091.  
  1092. #ifdef NEED_STRERROR
  1093. char *
  1094. strerror (int err) {
  1095.  
  1096.     char *p;
  1097.     extern char *const sys_errlist[];
  1098.  
  1099.     p = sys_errlist[err];
  1100.     return (p);
  1101. }
  1102. #endif
  1103.  
  1104. #ifdef __EMX__
  1105. void os2pathname(char *path) {
  1106.     char newpath[MAX_STRING_LEN];
  1107.     int loop;
  1108.     int offset;
  1109.  
  1110.     offset = 0;
  1111.     for (loop=0; loop < (strlen(path) + 1); loop++) {
  1112.         if (path[loop] == '/') {
  1113.             newpath[offset] = '\\';
  1114.             /*
  1115.             offset = offset + 1;
  1116.             newpath[offset] = '\\';
  1117.             */
  1118.         } else
  1119.             newpath[offset] = path[loop];
  1120.         offset = offset + 1;
  1121.     };
  1122.     /* Debugging code */
  1123.     /* fprintf(stderr, "%s \n", newpath); */
  1124.  
  1125.     strcpy(path, newpath);
  1126. };
  1127. #endif
  1128.