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

  1. /*
  2.  * str.c: string utility things
  3.  * 
  4.  * 3/21/93 Rob McCool
  5.  * 
  6.  */
  7.  
  8.  
  9. #include "httpd.h"
  10.  
  11. char *get_time() {
  12.     time_t t;
  13.     char *time_string;
  14.  
  15.     t=time(NULL);
  16.     time_string = ctime(&t);
  17.     time_string[strlen(time_string) - 1] = '\0';
  18.     return (time_string);
  19. }
  20.  
  21. char *gm_timestr_822(time_t sec) {
  22.     return ht_time(sec,HTTP_TIME_FORMAT, 1);
  23. }
  24.  
  25. char *ht_time(time_t t, char *fmt, int gmt) {
  26.     static char ts[MAX_STRING_LEN];
  27.     struct tm *tms;
  28.  
  29.     tms = (gmt ? gmtime(&t) : localtime(&t));
  30.  
  31.     /* check return code? */
  32.     strftime(ts,MAX_STRING_LEN,fmt,tms);
  33.     return ts;
  34. }
  35.  
  36. /* What a pain in the ass. */
  37. struct tm *get_gmtoff(long *tz) {
  38.     time_t tt;
  39.     struct tm *t;
  40.  
  41.     tt = time(NULL);
  42.     t = localtime(&tt);
  43. #if defined(BSD) && !defined(AUX) && !defined(APOLLO)
  44.     *tz = t->tm_gmtoff;
  45. #else
  46.     *tz = - timezone;
  47.     if(t->tm_isdst)
  48.         *tz += 3600;
  49. #endif
  50.     return t;
  51. }
  52.  
  53.  
  54. static char *months[] = {
  55.     "Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"
  56. };
  57.  
  58.  
  59. int find_month(char *mon) {
  60.     register int x;
  61.  
  62.     for(x=0;x<12;x++)
  63.         if(!strcmp(months[x],mon))
  64.             return x;
  65.     return -1;
  66. }
  67.  
  68. /* Roy owes Rob beer. */
  69. /* This would be considerably easier if strptime or timegm were portable */
  70.  
  71. int later_than(struct tm *lms, char *ims) {
  72.     char *ip;
  73.     char mname[MAX_STRING_LEN];
  74.     int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0, x;
  75.  
  76.     /* Whatever format we're looking at, it will start with weekday. */
  77.     /* Skip to first space. */
  78.     if(!(ip = strchr(ims,' ')))
  79.         return 0;
  80.     else
  81.         while(isspace(*ip))
  82.             ++ip;
  83.  
  84.     if(isalpha(*ip)) {
  85.         /* ctime */
  86.         sscanf(ip,"%s %d %d:%d:%d %*s %d",mname,&day,&hour,&min,&sec,&year);
  87.     }
  88.     else if(ip[2] == '-') {
  89.         /* RFC 850 (normal HTTP) */
  90.         char t[MAX_STRING_LEN];
  91.         sscanf(ip,"%s %d:%d:%d",t,&hour,&min,&sec);
  92.         t[2] = '\0';
  93.         day = atoi(t);
  94.         t[6] = '\0';
  95.         strcpy(mname,&t[3]);
  96.         x = atoi(&t[7]);
  97.         /* Prevent wraparound from ambiguity */
  98.         if(x < 70)
  99.             x += 100;
  100.         year = 1900 + x;
  101.     }
  102.     else {
  103.         /* RFC 822 */
  104.         sscanf(ip,"%d %s %d %d:%d:%d",&day,mname,&year,&hour,&min,&sec);
  105.     }
  106.     month = find_month(mname);
  107.  
  108.     if((x = (1900+lms->tm_year) - year))
  109.         return x < 0;
  110.     if((x = lms->tm_mon - month))
  111.         return x < 0;
  112.     if((x = lms->tm_mday - day))
  113.         return x < 0;
  114.     if((x = lms->tm_hour - hour))
  115.         return x < 0;
  116.     if((x = lms->tm_min - min))
  117.         return x < 0;
  118.     if((x = lms->tm_sec - sec))
  119.         return x < 0;
  120.  
  121.     return 1;
  122. }
  123.  
  124.  
  125. /* Match = 0, NoMatch = 1, Abort = -1 */
  126. /* Based loosely on sections of wildmat.c by Rich Salz */
  127. int strcmp_match(char *str, char *exp) {
  128.     int x,y;
  129.  
  130.     for(x=0,y=0;exp[y];++y,++x) {
  131.         if((!str[x]) && (exp[y] != '*'))
  132.             return -1;
  133.         if(exp[y] == '*') {
  134.             while(exp[++y] == '*');
  135.             if(!exp[y])
  136.                 return 0;
  137.             while(str[x]) {
  138.                 int ret;
  139.                 if((ret = strcmp_match(&str[x++],&exp[y])) != 1)
  140.                     return ret;
  141.             }
  142.             return -1;
  143.         } else 
  144.             if((exp[y] != '?') && (str[x] != exp[y]))
  145.                 return 1;
  146.     }
  147.     return (str[x] != '\0');
  148. }
  149.  
  150. int is_matchexp(char *str) {
  151.     register int x;
  152.  
  153.     for(x=0;str[x];x++)
  154.         if((str[x] == '*') || (str[x] == '?'))
  155.             return 1;
  156.     return 0;
  157. }
  158.  
  159. void strsubfirst(int start,char *dest, char *src)
  160. {
  161.     char tmp[MAX_STRING_LEN];
  162.  
  163.     strcpy(tmp,&dest[start]);
  164.     strcpy(dest,src);
  165.     strcpy(&dest[strlen(src)],tmp);
  166. }
  167.  
  168. /*
  169.  * Parse .. so we don't compromise security
  170.  */
  171. void getparents(char *name)
  172. {
  173.     int l=0,w=0;
  174.     const char *lookfor="..";
  175.  
  176.     while(name[l]!='\0') {
  177.         if(name[l]!=lookfor[w]) (w>0 ? (l-=(w-1),w=0) : l++);
  178.         else {
  179.             if(lookfor[++w]=='\0') {
  180.                 if((name[l+1]=='\0') || (name[l+1]=='/') &&
  181.                    (((l > 3) && (name[l-2] == '/')) || (l<=3))) {
  182.                     register int m=l+1,n;
  183.  
  184.                     l=l-3;
  185.                     if(l>=0) {
  186.                         while((l!=0) && (name[l]!='/')) --l;
  187.                     }
  188.                     else l=0;
  189.                     n=l;
  190.                     while(name[n]=name[m]) (++n,++m);
  191.                     w=0;
  192.                 }
  193.                 else w=0;
  194.             }
  195.             else ++l;
  196.         }
  197.     }
  198. }
  199.  
  200. void no2slash(char *name) {
  201.     register int x,y;
  202.  
  203.     for(x=0; name[x]; x++)
  204.         if(x && (name[x-1] == '/') && (name[x] == '/'))
  205.             for(y=x+1;name[y-1];y++)
  206.                 name[y-1] = name[y];
  207. }
  208.  
  209. void make_dirstr(char *s, int n, char *d) {
  210.     register int x,f;
  211.  
  212.     for(x=0,f=0;s[x];x++) {
  213.         if((d[x] = s[x]) == '/')
  214.             if((++f) == n) {
  215.                 d[x] = '\0';
  216.                 return;
  217.             }
  218.     }
  219.     d[x] = '\0';
  220. }
  221.  
  222. int count_dirs(char *path) {
  223.     register int x,n;
  224.  
  225.     for(x=0,n=0;path[x];x++)
  226.         if(path[x] == '/') n++;
  227.     return n;
  228. }
  229.  
  230.  
  231. void strcpy_dir(char *d, char *s) {
  232.     register int x;
  233.  
  234.     for(x=0;s[x];x++)
  235.         d[x] = s[x];
  236.  
  237.     if(s[x-1] != '/') d[x++] = '/';
  238.     d[x] = '\0';
  239. }
  240.  
  241. void chdir_file(char *file) {
  242.     int i;
  243.  
  244.     if((i = rind(file,'/')) == -1)
  245.         return;
  246.     file[i] = '\0';
  247.     chdir(file);
  248.     file[i] = '/';
  249. }
  250.  
  251. void http2cgi(char *w) {
  252.     register int x;
  253.  
  254.     for(x=strlen(w);x != -1; --x)
  255.         w[x+5]= (w[x] == '-' ? '_' : toupper(w[x]));
  256.     strncpy(w,"HTTP_",5);
  257. }
  258.  
  259. void getline_timed_out() {
  260.     char errstr[MAX_STRING_LEN];
  261.  
  262.     sprintf(errstr,"timed out waiting for %s",remote_name);
  263.     log_error(errstr);
  264.     fclose(stdin);
  265.     fclose(stdout);
  266.     exit(0);
  267. }
  268.  
  269. int getline(char *s, int n, int f, unsigned int timeout) {
  270.     register int i=0, ret;
  271.  
  272.     signal(SIGALRM,getline_timed_out);
  273.     alarm(timeout);
  274.     while(1) {
  275.         if((ret = read(f,&s[i],1)) <= 0) {
  276.             /* Mmmmm, Solaris.  */
  277.             if((ret == -1) && (errno == EINTR))
  278.                 continue;
  279.             s[i] = '\0';
  280.             return 1;
  281.         }
  282.  
  283.         if(s[i] == CR)
  284.             read(f,&s[i],1);
  285.  
  286.         if((s[i] == LF) || (i == (n-1))) {
  287.             alarm(0);
  288.             signal(SIGALRM,SIG_IGN);
  289.             s[i] = '\0';
  290.             return 0;
  291.         }
  292.         ++i;
  293.     }
  294. }
  295.  
  296. void getword(char *word, char *line, char stop) {
  297.     int x = 0,y;
  298.  
  299.     for(x=0;((line[x]) && (line[x] != stop));x++)
  300.         word[x] = line[x];
  301.  
  302.     word[x] = '\0';
  303.     if(line[x]) ++x;
  304.     y=0;
  305.  
  306.     while(line[y++] = line[x++]);
  307. }
  308.  
  309. void cfg_getword(char *word, char *line) {
  310.     int x=0,y;
  311.     
  312.     for(x=0;line[x] && isspace(line[x]);x++);
  313.     y=0;
  314.     while(1) {
  315.         if(!(word[y] = line[x]))
  316.             break;
  317.         if(isspace(line[x]))
  318.             if((!x) || (line[x-1] != '\\'))
  319.                 break;
  320.         if(line[x] != '\\') ++y;
  321.         ++x;
  322.     }
  323.     word[y] = '\0';
  324.     while(line[x] && isspace(line[x])) ++x;
  325.     for(y=0;line[y] = line[x];++x,++y);
  326. }
  327.  
  328. int cfg_getline(char *s, int n, FILE *f) {
  329.     register int i=0;
  330.     register char c;
  331.  
  332.     s[0] = '\0';
  333.     /* skip leading whitespace */
  334.     while(1) {
  335.         c=(char)fgetc(f);
  336.         if((c != '\t') && (c != ' '))
  337.             break;
  338.     }
  339.     while(1) {
  340.         if((c == '\t') || (c == ' ')) {
  341.             s[i++] = ' ';
  342.             while((c == '\t') || (c == ' ')) 
  343.                 c=(char)fgetc(f);
  344.         }
  345.         if(c == CR) {
  346.             c = fgetc(f);
  347.         }
  348.         if((c == 0x4) || (c == LF) || (i == (n-1))) {
  349.             /* blast trailing whitespace */
  350.             while(i && (s[i-1] == ' ')) --i;
  351.             s[i] = '\0';
  352.             return (feof(f) ? 1 : 0);
  353.         }
  354.         s[i] = c;
  355.         ++i;
  356.         c = (char)fgetc(f);
  357.     }
  358. }
  359.  
  360. void escape_shell_cmd(char *cmd) {
  361.     register int x,y,l;
  362.  
  363.     l=strlen(cmd);
  364.     for(x=0;cmd[x];x++) {
  365.         if(ind("&;`'\"|*?~<>^()[]{}$\\",cmd[x]) != -1){
  366.             for(y=l+1;y>x;y--)
  367.                 cmd[y] = cmd[y-1];
  368.             l++; /* length has been increased */
  369.             cmd[x] = '\\';
  370.             x++; /* skip the character */
  371.         }
  372.     }
  373. }
  374.  
  375. void plustospace(char *str) {
  376.     register int x;
  377.  
  378.     for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
  379. }
  380.  
  381. void spacetoplus(char *str) {
  382.     register int x;
  383.  
  384.     for(x=0;str[x];x++) if(str[x] == ' ') str[x] = '+';
  385. }
  386.  
  387. char x2c(char *what) {
  388.     register char digit;
  389.  
  390.     digit = ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
  391.     digit *= 16;
  392.     digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
  393.     return(digit);
  394. }
  395.  
  396. void unescape_url(char *url) {
  397.     register int x,y;
  398.  
  399.     for(x=0,y=0;url[y];++x,++y) {
  400.         if((url[x] = url[y]) == '%') {
  401.             url[x] = x2c(&url[y+1]);
  402.             y+=2;
  403.         }
  404.     }
  405.     url[x] = '\0';
  406. }
  407.  
  408. #define c2x(what,where) sprintf(where,"%%%2x",what)
  409.  
  410. void escape_url(char *url) {
  411.     register int x,y;
  412.     register char digit;
  413.     char *copy;
  414.  
  415.     copy = strdup(url);
  416.             
  417.     for(x=0,y=0;copy[x];x++,y++) {
  418.         if(ind("% ?+&",url[y] = copy[x]) != -1) {
  419.             c2x(copy[x],&url[y]);
  420.             y+=2;
  421.         }
  422.     }
  423.     url[y] = '\0';
  424.     free(copy);
  425. }
  426.  
  427. void escape_uri(char *url) {
  428.     register int x,y;
  429.     register char digit;
  430.     char *copy;
  431.  
  432.     copy = strdup(url);
  433.             
  434.     for(x=0,y=0;copy[x];x++,y++) {
  435.         if(ind(":% ?+&",url[y] = copy[x]) != -1) {
  436.             c2x(copy[x],&url[y]);
  437.             y+=2;
  438.         }
  439.     }
  440.     url[y] = '\0';
  441.     free(copy);
  442. }
  443.  
  444. void make_full_path(char *src1,char *src2,char *dst) {
  445.     register int x,y;
  446.  
  447.     for(x=0;dst[x] = src1[x];x++);
  448.  
  449.     if(!x) dst[x++] = '/';
  450.     else if((dst[x-1] != '/'))
  451.         dst[x++] = '/';
  452.  
  453.     for(y=0;dst[x] = src2[y];x++,y++);
  454. }
  455.  
  456. int is_directory(char *path) {
  457.     struct stat finfo;
  458.  
  459.     if(stat(path,&finfo) == -1)
  460.         return 0; /* in error condition, just return no */
  461.  
  462.     return(S_ISDIR(finfo.st_mode));
  463. }
  464.  
  465. int is_url(char *u) {
  466.     register int x;
  467.  
  468.     for(x=0;u[x] != ':';x++)
  469.         if((!u[x]) || (!isalpha(u[x])))
  470.             return 0;
  471.  
  472.     if((u[x+1] == '/') && (u[x+2] == '/'))
  473.         return 1;
  474.     else return 0;
  475. }
  476.  
  477. char *make_env_str(char *name, char *value, FILE *out) {
  478.     char *t,*tp;
  479.  
  480.     if(!(t = (char *)malloc(strlen(name)+strlen(value)+2)))
  481.         die(NO_MEMORY,"make_env_str",out);
  482.  
  483.     for(tp=t;*tp = *name;tp++,name++);
  484.     for(*tp++ = '=';*tp = *value;tp++,value++);
  485.     return t;
  486. }
  487.  
  488. char **new_env(char **env, int to_add, int *pos) {
  489.     if(!env) {
  490.         *pos = 0;
  491.         return (char **)malloc((to_add+1)*sizeof(char *));
  492.     }
  493.     else {
  494.         int x;
  495.         char **newenv;
  496.  
  497.         for(x=0;env[x];x++);
  498.         if(!(newenv = (char **)malloc((to_add+x+1)*(sizeof(char *)))))
  499.             return NULL;
  500.         for(x=0;env[x];x++)
  501.             newenv[x] = env[x];
  502.         *pos = x;
  503.         free(env);
  504.         return newenv;
  505.     }
  506. }
  507.  
  508. void free_env(char **env) {
  509.     int x;
  510.  
  511.     for(x=0;env[x];x++)
  512.         free(env[x]);
  513.     free(env);
  514. }
  515.  
  516. int can_exec(struct stat *finfo) {
  517.     if(user_id == finfo->st_uid)
  518.         if(finfo->st_mode & S_IXUSR)
  519.             return 1;
  520.     if(group_id == finfo->st_gid)
  521.         if(finfo->st_mode & S_IXGRP)
  522.             return 1;
  523.     return (finfo->st_mode & S_IXOTH);
  524. }
  525.  
  526. #ifdef NEED_STRDUP
  527. char *strdup (char *str)
  528. {
  529.   char *dup;
  530.  
  531.   if(!(dup = (char *)malloc (strlen (str) + 1)))
  532.       return NULL;
  533.   dup = strcpy (dup, str);
  534.  
  535.   return dup;
  536. }
  537. #endif
  538.  
  539. /* The following two routines were donated for SVR4 by Andreas Vogel */
  540. #ifdef NEED_STRCASECMP
  541. int strcasecmp (const char *a, const char *b)
  542. {
  543.     const char *p = a;
  544.     const char *q = b;
  545.     for (p = a, q = b; *p && *q; p++, q++)
  546.     {
  547.       int diff = tolower(*p) - tolower(*q);
  548.       if (diff) return diff;
  549.     }
  550.     if (*p) return 1;       /* p was longer than q */
  551.     if (*q) return -1;      /* p was shorter than q */
  552.     return 0;               /* Exact match */
  553. }
  554.  
  555. #endif
  556.  
  557. #ifdef NEED_STRNCASECMP
  558. int strncasecmp (const char *a, const char *b, int n)
  559. {
  560.     const char *p = a;
  561.     const char *q = b;
  562.  
  563.     for (p = a, q = b; /*NOTHING*/; p++, q++)
  564.     {
  565.       int diff;
  566.       if (p == a + n) return 0;     /*   Match up to n characters */
  567.       if (!(*p && *q)) return *p - *q;
  568.       diff = tolower(*p) - tolower(*q);
  569.       if (diff) return diff;
  570.     }
  571.     /*NOTREACHED*/
  572. }
  573. #endif
  574.  
  575.  
  576.  
  577. #ifdef NEED_INITGROUPS
  578. int initgroups(const char *name, gid_t basegid)
  579. {
  580.   gid_t groups[NGROUPS_MAX];
  581.   struct group *g;
  582.   int index = 0;
  583.  
  584.   groups[index++] = basegid;
  585.  
  586.   while (index < NGROUPS_MAX && ((g = getgrent()) != NULL))
  587.     if (g->gr_gid != basegid)
  588.     {
  589.       char **names;
  590.  
  591.       for (names = g->gr_mem; *names != NULL; ++names)
  592.         if (!strcmp(*names, name))
  593.           groups[index++] = g->gr_gid;
  594.     }
  595.  
  596.   return setgroups(index, groups);
  597. }
  598. #endif
  599.  
  600. #ifdef NEED_WAITPID
  601. /* From ikluft@amdahl.com */
  602. /* this is not ideal but it works for SVR3 variants */
  603. /* httpd does not use the options so this doesn't implement them */
  604. int waitpid(pid_t pid, int *statusp, int options)
  605. {
  606.     int tmp_pid;
  607.     if ( kill ( pid,0 ) == -1) {
  608.         errno=ECHILD;
  609.         return -1;
  610.     }
  611.     while ((( tmp_pid = wait(statusp)) != pid) && ( tmp_pid != -1 ));
  612.     return tmp_pid;
  613. }
  614. #endif
  615.  
  616. int ind(char *s, char c) {
  617.     register int x;
  618.  
  619.     for(x=0;s[x];x++)
  620.         if(s[x] == c) return x;
  621.  
  622.     return -1;
  623. }
  624.  
  625. int rind(char *s, char c) {
  626.     register int x;
  627.  
  628.     for(x=strlen(s)-1;x != -1;x--)
  629.         if(s[x] == c) return x;
  630.  
  631.     return -1;
  632. }
  633.  
  634. void str_tolower(char *str) {
  635.     while(*str) {
  636.         *str = tolower(*str);
  637.         ++str;
  638.     }
  639. }
  640.         
  641. uid_t uname2id(char *name) {
  642.     struct passwd *ent;
  643.  
  644.     if(name[0] == '#') 
  645.         return(atoi(&name[1]));
  646.  
  647.     if(!(ent = getpwnam(name))) {
  648.         fprintf(stderr,"httpd: bad user name %s\n",name);
  649.         exit(1);
  650.     }
  651.     else return(ent->pw_uid);
  652. }
  653.  
  654. gid_t gname2id(char *name) {
  655.     struct group *ent;
  656.  
  657.     if(name[0] == '#') 
  658.         return(atoi(&name[1]));
  659.  
  660.     if(!(ent = getgrnam(name))) {
  661.         fprintf(stderr,"httpd: bad group name %s\n",name);
  662.         exit(1);
  663.     }
  664.     else return(ent->gr_gid);
  665. }
  666.  
  667. int get_portnum(int sd,FILE *out) {
  668.     struct sockaddr addr;
  669.     int len;
  670.  
  671.     len = sizeof(struct sockaddr);
  672.     if(getsockname(sd,&addr,&len) < 0)
  673.         die(SERVER_ERROR,"could not get port number",out);
  674.     return ntohs(((struct sockaddr_in *)&addr)->sin_port);
  675. }
  676.  
  677. char *find_fqdn(struct hostent *p) {
  678.     int x;
  679.  
  680.     if(ind(p->h_name,'.') == -1) {
  681.         for(x=0;p->h_aliases[x];++x) {
  682.             if((ind(p->h_aliases[x],'.') != -1) && 
  683.                (!strncmp(p->h_aliases[x],p->h_name,strlen(p->h_name))))
  684.                 return strdup(p->h_aliases[x]);
  685.         }
  686.         return NULL;
  687.     } else return strdup(p->h_name);
  688. }
  689.  
  690. void get_remote_host(int fd) {
  691.     struct sockaddr addr;
  692.     int len;
  693.     struct in_addr *iaddr;
  694.     struct hostent *hptr;
  695.  
  696.     len = sizeof(struct sockaddr);
  697.  
  698.     if ((getpeername(fd, &addr, &len)) < 0) {
  699.         remote_host=NULL;
  700.         remote_ip=NULL;
  701.         remote_name="UNKNOWN_HOST";
  702.         return;
  703.     }
  704.     iaddr = &(((struct sockaddr_in *)&addr)->sin_addr);
  705. #ifndef MINIMAL_DNS
  706.     hptr = gethostbyaddr((char *)iaddr, sizeof(struct in_addr), AF_INET);
  707.     if(hptr) {
  708.         remote_host = strdup(hptr->h_name);
  709.         str_tolower(remote_host);
  710.         remote_name = remote_host;
  711.     }
  712.     else 
  713. #endif
  714.         remote_host = NULL;
  715.  
  716. #ifdef MAXIMUM_DNS
  717.     /* Grrr. Check THAT name to make sure it's really the name of the addr. */
  718.     /* Code from Harald Hanche-Olsen <hanche@imf.unit.no> */
  719.     if(remote_host) {
  720.         char **haddr;
  721.         hptr = gethostbyname(remote_host);
  722.         if (hptr) {
  723.             for(haddr=hptr->h_addr_list;*haddr;haddr++) {
  724.                 if(((struct in_addr *)(*haddr))->s_addr == iaddr->s_addr)
  725.                     break;
  726.             }
  727.         }
  728.         if((!hptr) || (!(*haddr)))
  729.             remote_host = NULL;
  730.     }
  731. #endif
  732.     remote_ip = inet_ntoa(*iaddr);
  733.     if(!remote_host)
  734.         remote_name = remote_ip;
  735. }
  736.  
  737. char *get_remote_logname(FILE *fd) {
  738.     int len;
  739.     char *result;
  740. #ifdef NEXT
  741.     struct sockaddr sa_server, sa_client;
  742. #else
  743.     struct sockaddr_in sa_server,sa_client;
  744. #endif
  745.  
  746.     len = sizeof(sa_client);
  747.     if(getpeername(fileno(stdout),&sa_client,&len) != -1) {
  748.         len = sizeof(sa_server);
  749.         if(getsockname(fileno(stdout),&sa_server,&len) == -1)
  750.             result = "unknown";
  751.         else
  752.             result = rfc931((struct sockaddr_in *) & sa_client,
  753.                                     (struct sockaddr_in *) & sa_server);
  754.     }
  755.     else result = "unknown";
  756.  
  757.     return result; /* robm=pinhead */
  758. }
  759.  
  760. void get_local_host()
  761. {
  762.     char str[128];
  763.     int len = 128;
  764.  
  765.     if(!server_hostname) {
  766.         struct hostent *p;
  767.         gethostname(str, len);
  768.         if((!(p=gethostbyname(str))) || (!(server_hostname = find_fqdn(p)))) {
  769.             fprintf(stderr,"httpd: cannot determine local host name.\n");
  770.             fprintf(stderr,"Use ServerName to set it manually.\n");
  771.             exit(1);
  772.         }
  773.     }
  774. }
  775.  
  776. void construct_url(char *d, char *s) {
  777.     sprintf(d,"http://%s:%d%s",server_hostname,port,s);
  778. /*    escape_url(d); */
  779. }
  780.  
  781. /* aaaack but it's fast and const should make it shared text page. */
  782. const int pr2six[256]={
  783.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  784.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,62,64,64,64,63,
  785.     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,
  786.     10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,64,64,64,64,64,64,26,27,
  787.     28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,
  788.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  789.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  790.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  791.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  792.     64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,
  793.     64,64,64,64,64,64,64,64,64,64,64,64,64
  794. };
  795.  
  796. void uudecode(char *bufcoded, unsigned char *bufplain, int outbufsize) {
  797.     int nbytesdecoded, j;
  798.     register char *bufin = bufcoded;
  799.     register unsigned char *bufout = bufplain;
  800.     register int nprbytes;
  801.     
  802.     /* Strip leading whitespace. */
  803.     
  804.     while(*bufcoded==' ' || *bufcoded == '\t') bufcoded++;
  805.     
  806.     /* Figure out how many characters are in the input buffer.
  807.      * If this would decode into more bytes than would fit into
  808.      * the output buffer, adjust the number of input bytes downwards.
  809.      */
  810.     bufin = bufcoded;
  811.     while(pr2six[*(bufin++)] <= 63);
  812.     nprbytes = bufin - bufcoded - 1;
  813.     nbytesdecoded = ((nprbytes+3)/4) * 3;
  814.     if(nbytesdecoded > outbufsize) {
  815.         nprbytes = (outbufsize*4)/3;
  816.     }
  817.     
  818.     bufin = bufcoded;
  819.     
  820.     while (nprbytes > 0) {
  821.         *(bufout++) = 
  822.             (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
  823.         *(bufout++) = 
  824.             (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
  825.         *(bufout++) = 
  826.             (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
  827.         bufin += 4;
  828.         nprbytes -= 4;
  829.     }
  830.     
  831.     if(nprbytes & 03) {
  832.         if(pr2six[bufin[-2]] > 63)
  833.             nbytesdecoded -= 2;
  834.         else
  835.             nbytesdecoded -= 1;
  836.     }
  837.     bufplain[nbytesdecoded] = '\0';
  838. }
  839.