root/cgi-src/ssi.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. internal_error
  2. not_found
  3. not_found2
  4. not_permitted
  5. unknown_directive
  6. unknown_tag
  7. unknown_value
  8. get_filename
  9. check_filename
  10. show_time
  11. show_size
  12. do_config
  13. do_include
  14. do_echo
  15. do_fsize
  16. do_flastmod
  17. parse
  18. slurp
  19. read_file
  20. main

   1 /* ssi - server-side-includes CGI program
   2 **
   3 ** Copyright (c) 1995 by Jef Poskanzer <jef@mail.acme.com>.
   4 ** Copyright (c) 2023 by Amelia Zabardast Ziabari <ame@psianesia.org>.
   5 ** All rights reserved.
   6 **
   7 ** Redistribution and use in source and binary forms, with or without
   8 ** modification, are permitted provided that the following conditions
   9 ** are met:
  10 ** 1. Redistributions of source code must retain the above copyright
  11 **    notice, this list of conditions and the following disclaimer.
  12 ** 2. Redistributions in binary form must reproduce the above copyright
  13 **    notice, this list of conditions and the following disclaimer in the
  14 **    documentation and/or other materials provided with the distribution.
  15 **
  16 ** THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17 ** ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19 ** ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20 ** FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21 ** DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22 ** OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23 ** HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24 ** LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25 ** OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26 ** SUCH DAMAGE.
  27 */
  28 
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <string.h>
  32 #include <time.h>
  33 #include <sys/types.h>
  34 #include <sys/stat.h>
  35 
  36 #include "config.h"
  37 #include "match.h"
  38 
  39 
  40 #define ST_GROUND 0
  41 #define ST_LESSTHAN 1
  42 #define ST_BANG 2
  43 #define ST_MINUS1 3
  44 #define ST_MINUS2 4
  45 
  46 
  47 static void read_file( char* vfilename, char* filename, FILE* fp );
  48 
  49 
  50 static char* argv0;
  51 static char* url;
  52 
  53 static char timefmt[100];
  54 static int sizefmt;
  55 #define SF_BYTES 0
  56 #define SF_ABBREV 1
  57 static struct stat sb;
  58 
  59 
  60 static void
  61 internal_error( char* reason )
  62     {
  63     char* title = "500 Internal Error";
  64 
  65     (void) printf( "\
  66 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
  67 <BODY><H2>%s</H2>\n\
  68 Something unusual went wrong during a server-side-includes request:\n\
  69 <BLOCKQUOTE>\n\
  70 %s\n\
  71 </BLOCKQUOTE>\n\
  72 </BODY></HTML>\n", title, title, reason );
  73     }
  74 
  75 
  76 static void
  77 not_found( char* filename )
  78     {
  79     char* title = "404 Not Found";
  80 
  81     (void) printf( "\
  82 <HTML><HEAD><TITLE>%s</TITLE></HEAD>\n\
  83 <BODY><H2>%s</H2>\n\
  84 The requested server-side-includes filename, %s,\n\
  85 does not seem to exist.\n\
  86 </BODY></HTML>\n", title, title, filename );
  87     }
  88 
  89 
  90 static void
  91 not_found2( char* directive, char* tag, char* filename2 )
  92     {
  93     char* title = "Not Found";
  94 
  95     (void) printf( "\
  96 <HR><H2>%s</H2>\n\
  97 The filename requested in a %s %s directive, %s,\n\
  98 does not seem to exist.\n\
  99 <HR>\n", title, directive, tag, filename2 );
 100     }
 101 
 102 
 103 static void
 104 not_permitted( char* directive, char* tag, char* val )
 105     {
 106     char* title = "Not Permitted";
 107 
 108     (void) printf( "\
 109 <HR><H2>%s</H2>\n\
 110 The filename requested in the %s %s=%s directive\n\
 111 may not be fetched.\n\
 112 <HR>\n", title, directive, tag, val );
 113     }
 114 
 115 
 116 static void
 117 unknown_directive( char* filename, char* directive )
 118     {
 119     char* title = "Unknown Directive";
 120 
 121     (void) printf( "\
 122 <HR><H2>%s</H2>\n\
 123 The requested server-side-includes filename, %s,\n\
 124 tried to use an unknown directive, %s.\n\
 125 <HR>\n", title, filename, directive );
 126     }
 127 
 128 
 129 static void
 130 unknown_tag( char* filename, char* directive, char* tag )
 131     {
 132     char* title = "Unknown Tag";
 133 
 134     (void) printf( "\
 135 <HR><H2>%s</H2>\n\
 136 The requested server-side-includes filename, %s,\n\
 137 tried to use the directive %s with an unknown tag, %s.\n\
 138 <HR>\n", title, filename, directive, tag );
 139     }
 140 
 141 
 142 static void
 143 unknown_value( char* filename, char* directive, char* tag, char* val )
 144     {
 145     char* title = "Unknown Value";
 146 
 147     (void) printf( "\
 148 <HR><H2>%s</H2>\n\
 149 The requested server-side-includes filename, %s,\n\
 150 tried to use the directive %s %s with an unknown value, %s.\n\
 151 <HR>\n", title, filename, directive, tag, val );
 152     }
 153 
 154 
 155 static int
 156 get_filename( char* vfilename, char* filename, char* directive, char* tag, char* val, char* fn, int fnsize )
 157     {
 158     int vl, fl;
 159     char* cp;
 160 
 161     /* Used for the various commands that accept a file name.
 162     ** These commands accept two tags:
 163     **   virtual
 164     **     Gives a virtual path to a document on the server.
 165     **   file
 166     **     Gives a pathname relative to the current directory. ../ cannot
 167     **     be used in this pathname, nor can absolute paths be used.
 168     */
 169     vl = strlen( vfilename );
 170     fl = strlen( filename );
 171     if ( strcmp( tag, "virtual" ) == 0 )
 172         {
 173         if ( strstr( val, "../" ) != (char*) 0 )
 174             {
 175             not_permitted( directive, tag, val );
 176             return -1;
 177             }
 178         /* Figure out root using difference between vfilename and filename. */
 179         if ( vl > fl ||
 180              strcmp( vfilename, &filename[fl - vl] ) != 0 )
 181             return -1;
 182         if ( fl - vl + strlen( val ) >= (size_t) fnsize )
 183             return -1;
 184         (void) strncpy( fn, filename, fl - vl );
 185         (void) strcpy( &fn[fl - vl], val );
 186         }
 187     else if ( strcmp( tag, "file" ) == 0 )
 188         {
 189         if ( val[0] == '/' || strstr( val, "../" ) != (char*) 0 )
 190             {
 191             not_permitted( directive, tag, val );
 192             return -1;
 193             }
 194         if ( fl + 1 + strlen( val ) >= (size_t) fnsize )
 195             return -1;
 196         (void) strcpy( fn, filename );
 197         cp = strrchr( fn, '/' );
 198         if ( cp == (char*) 0 )
 199             {
 200             cp = &fn[strlen( fn )];
 201             *cp = '/';
 202             }
 203         (void) strcpy( ++cp, val );
 204         }
 205     else
 206         {
 207         unknown_tag( filename, directive, tag );
 208         return -1;
 209         }
 210     return 0;
 211     }
 212 
 213 
 214 static int
 215 check_filename( char* filename )
 216     {
 217     static int inited = 0;
 218     static char* cgi_pattern;
 219     int fnl;
 220     char* cp;
 221     char* dirname;
 222     char* authname;
 223     struct stat sb2;
 224     int r;
 225 
 226     if ( ! inited )
 227         {
 228         /* Get the cgi pattern. */
 229         cgi_pattern = getenv( "CGI_PATTERN" );
 230 #ifdef CGI_PATTERN
 231         if ( cgi_pattern == (char*) 0 )
 232             cgi_pattern = CGI_PATTERN;
 233 #endif /* CGI_PATTERN */
 234         inited = 1;
 235         }
 236 
 237     /* ../ is not permitted. */
 238     if ( strstr( filename, "../" ) != (char*) 0 )
 239         return 0;
 240 
 241 #ifdef AUTH_FILE
 242     /* Ensure that we are not reading a basic auth password file. */
 243     fnl = strlen(filename);
 244     if ( strcmp( filename, AUTH_FILE ) == 0 ||
 245          ( fnl >= (int) sizeof(AUTH_FILE) &&
 246            strcmp( &filename[fnl - sizeof(AUTH_FILE) + 1], AUTH_FILE ) == 0 &&
 247            filename[fnl - sizeof(AUTH_FILE)] == '/' ) )
 248         return 0;
 249 
 250     /* Check for an auth file in the same directory.  We can't do an actual
 251     ** auth password check here because CGI programs are not given the
 252     ** authorization header, for security reasons.  So instead we just
 253     ** prohibit access to all auth-protected files.
 254     */
 255     dirname = strdup( filename );
 256     if ( dirname == (char*) 0 )
 257         return 0;       /* out of memory */
 258     cp = strrchr( dirname, '/' );
 259     if ( cp == (char*) 0 )
 260         (void) strcpy( dirname, "." );
 261     else
 262         *cp = '\0';
 263     authname = malloc( strlen( dirname ) + 1 + sizeof(AUTH_FILE) );
 264     if ( authname == (char*) 0 )
 265         {
 266         free( dirname );
 267         return 0;       /* out of memory */
 268         }
 269     (void) sprintf( authname, "%s/%s", dirname, AUTH_FILE );
 270     r = stat( authname, &sb2 );
 271     free( dirname );
 272     free( authname );
 273     if ( r == 0 )
 274         return 0;
 275 #endif /* AUTH_FILE */
 276 
 277     /* Ensure that we are not reading a CGI file. */
 278     if ( cgi_pattern != (char*) 0 && match( cgi_pattern, filename ) )
 279         return 0;
 280 
 281     return 1;
 282     }
 283 
 284 
 285 static void
 286 show_time( time_t t, int gmt )
 287     {
 288     struct tm* tmP;
 289     char tbuf[500];
 290 
 291     if ( gmt )
 292         tmP = gmtime( &t );
 293     else
 294         tmP = localtime( &t );
 295     if ( strftime( tbuf, sizeof(tbuf), timefmt, tmP ) > 0 )
 296         (void) fputs( tbuf, stdout );
 297     }
 298 
 299 
 300 static void
 301 show_size( off_t size )
 302     {
 303     switch ( sizefmt )
 304         {
 305         case SF_BYTES:
 306         (void) printf( "%ld", (long) size );  /* spec says should have commas */
 307         break;
 308         case SF_ABBREV:
 309         if ( size < 1024 )
 310             (void) printf( "%ld", (long) size );
 311         else if ( size < 1024*1024 )
 312             (void) printf( "%ldK", (long) size / 1024L );
 313         else if ( size < 1024*1024*1024 )
 314             (void) printf( "%ldM", (long) size / (1024L*1024L) );
 315         else
 316             (void) printf( "%ldG", (long) size / (1024L*1024L*1024L) );
 317         break;
 318         }
 319     }
 320 
 321 
 322 static void
 323 do_config( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
 324     {
 325     /* The config directive controls various aspects of the file parsing.
 326     ** There are two valid tags:
 327     **   timefmt
 328     **     Gives the server a new format to use when providing dates.  This
 329     **     is a string compatible with the strftime library call.
 330     **   sizefmt
 331     **     Determines the formatting to be used when displaying the size of
 332     **     a file.  Valid choices are bytes, for a formatted byte count
 333     **     (formatted as 1,234,567), or abbrev for an abbreviated version
 334     **     displaying the number of kilobytes or megabytes the file occupies.
 335     */
 336 
 337     (void) vfilename; /* XXX: gcc */
 338     (void) fp; /* XXX: gcc */
 339 
 340     if ( strcmp( tag, "timefmt" ) == 0 )
 341         {
 342         (void) strncpy( timefmt, val, sizeof(timefmt) - 1 );
 343         timefmt[sizeof(timefmt) - 1] = '\0';
 344         }
 345     else if ( strcmp( tag, "sizefmt" ) == 0 )
 346         {
 347         if ( strcmp( val, "bytes" ) == 0 )
 348             sizefmt = SF_BYTES;
 349         else if ( strcmp( val, "abbrev" ) == 0 )
 350             sizefmt = SF_ABBREV;
 351         else
 352             unknown_value( filename, directive, tag, val );
 353         }
 354     else
 355         unknown_tag( filename, directive, tag );
 356     }
 357 
 358 
 359 static void
 360 do_include( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
 361     {
 362     char vfilename2[1000];
 363     char filename2[1000];
 364     FILE* fp2;
 365 
 366     (void) fp; /* XXX: gcc */
 367 
 368     /* Inserts the text of another document into the parsed document. */
 369 
 370     if ( get_filename(
 371              vfilename, filename, directive, tag, val, filename2,
 372              sizeof(filename2) ) < 0 )
 373         return;
 374 
 375     if ( ! check_filename( filename2 ) )
 376         {
 377         not_permitted( directive, tag, filename2 );
 378         return;
 379         }
 380 
 381     fp2 = fopen( filename2, "r" );
 382     if ( fp2 == (FILE*) 0 )
 383         {
 384         not_found2( directive, tag, filename2 );
 385         return;
 386         }
 387 
 388     if ( strcmp( tag, "virtual" ) == 0 )
 389         {
 390         if ( strlen( val ) < sizeof( vfilename2 ) )
 391             (void) strcpy( vfilename2, val );
 392         else
 393             (void) strcpy( vfilename2, filename2 );  /* same size, has to fit */
 394         }
 395     else
 396         {
 397         if ( strlen( vfilename ) + 1 + strlen( val ) < sizeof(vfilename2) )
 398             {
 399             char* cp;
 400             (void) strcpy( vfilename2, vfilename );
 401             cp = strrchr( vfilename2, '/' );
 402             if ( cp == (char*) 0 )
 403                 {
 404                 cp = &vfilename2[strlen( vfilename2 )];
 405                 *cp = '/';
 406                 }
 407             (void) strcpy( ++cp, val );
 408             }
 409         else
 410             (void) strcpy( vfilename2, filename2 );  /* same size, has to fit */
 411         }
 412 
 413     read_file( vfilename2, filename2, fp2 );
 414     (void) fclose( fp2 );
 415     }
 416 
 417 
 418 static void
 419 do_echo( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
 420     {
 421     char* cp;
 422     time_t t;
 423 
 424     /* Prints the value of one of the include variables.  Any dates are
 425     ** printed subject to the currently configured timefmt.  The only valid
 426     ** tag is var, whose value is the name of the variable you wish to echo.
 427     */
 428 
 429     if ( strcmp( tag, "var" ) != 0 )
 430         unknown_tag( filename, directive, tag );
 431     else
 432         {
 433         if ( strcmp( val, "DOCUMENT_NAME" ) == 0 )
 434             {
 435             /* The current filename. */
 436             (void) fputs( filename, stdout );
 437             }
 438         else if ( strcmp( val, "DOCUMENT_URI" ) == 0 )
 439             {
 440             /* The virtual path to this file (such as /~robm/foo.shtml). */
 441             (void) fputs( vfilename, stdout );
 442             }
 443         else if ( strcmp( val, "QUERY_STRING_UNESCAPED" ) == 0 )
 444             {
 445             /* The unescaped version of any search query the client sent. */
 446             cp = getenv( "QUERY_STRING" );
 447             if ( cp != (char*) 0 )
 448                 (void) fputs( cp, stdout );
 449             }
 450         else if ( strcmp( val, "DATE_LOCAL" ) == 0 )
 451             {
 452             /* The current date, local time zone. */
 453             t = time( (time_t*) 0 );
 454             show_time( t, 0 );
 455             }
 456         else if ( strcmp( val, "DATE_GMT" ) == 0 )
 457             {
 458             /* Same as DATE_LOCAL but in Greenwich mean time. */
 459             t = time( (time_t*) 0 );
 460             show_time( t, 1 );
 461             }
 462         else if ( strcmp( val, "LAST_MODIFIED" ) == 0 )
 463             {
 464             /* The last modification date of the current document. */
 465             if ( fstat( fileno( fp ), &sb ) >= 0 )
 466                 show_time( sb.st_mtime, 0 );
 467             }
 468         else
 469             {
 470             /* Try an environment variable. */
 471             cp = getenv( val );
 472             if ( cp == (char*) 0 )
 473                 unknown_value( filename, directive, tag, val );
 474             else
 475                 (void) fputs( cp, stdout );
 476             }
 477         }
 478     }
 479 
 480 
 481 static void
 482 do_fsize( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
 483     {
 484     char filename2[1000];
 485 
 486     (void) fp; /* XXX: gcc */
 487 
 488     /* Prints the size of the specified file. */
 489 
 490     if ( get_filename(
 491              vfilename, filename, directive, tag, val, filename2,
 492              sizeof(filename2) ) < 0 )
 493         return;
 494     if ( stat( filename2, &sb ) < 0 )
 495         {
 496         not_found2( directive, tag, filename2 );
 497         return;
 498         }
 499     show_size( sb.st_size );
 500     }
 501 
 502 
 503 static void
 504 do_flastmod( char* vfilename, char* filename, FILE* fp, char* directive, char* tag, char* val )
 505     {
 506     char filename2[1000];
 507 
 508     (void) fp; /* XXX: gcc */
 509 
 510     /* Prints the last modification date of the specified file. */
 511 
 512     if ( get_filename(
 513              vfilename, filename, directive, tag, val, filename2,
 514              sizeof(filename2) ) < 0 )
 515         return;
 516     if ( stat( filename2, &sb ) < 0 )
 517         {
 518         not_found2( directive, tag, filename2 );
 519         return;
 520         }
 521     show_time( sb.st_mtime, 0 );
 522     }
 523 
 524 
 525 static void
 526 parse( char* vfilename, char* filename, FILE* fp, char* str )
 527     {
 528     char* directive;
 529     char* cp;
 530     int ntags;
 531     char* tags[200];
 532     int dirn;
 533 #define DI_CONFIG 0
 534 #define DI_INCLUDE 1
 535 #define DI_ECHO 2
 536 #define DI_FSIZE 3
 537 #define DI_FLASTMOD 4
 538     int i;
 539     char* val;
 540 
 541     directive = str;
 542     directive += strspn( directive, " \t\n\r" );
 543 
 544     ntags = 0;
 545     cp = directive;
 546     for (;;)
 547         {
 548         cp = strpbrk( cp, " \t\n\r\"" );
 549         if ( cp == (char*) 0 )
 550             break;
 551         if ( *cp == '"' )
 552             {
 553             cp = strpbrk( cp + 1, "\"" );
 554             ++cp;
 555             if ( *cp == '\0' )
 556                 break;
 557             }
 558         *cp++ = '\0';
 559         cp += strspn( cp, " \t\n\r" );
 560         if ( *cp == '\0' )
 561             break;
 562         if ( (size_t) ntags < sizeof(tags)/sizeof(*tags) )
 563             tags[ntags++] = cp;
 564         }
 565 
 566     if ( strcmp( directive, "config" ) == 0 )
 567         dirn = DI_CONFIG;
 568     else if ( strcmp( directive, "include" ) == 0 )
 569         dirn = DI_INCLUDE;
 570     else if ( strcmp( directive, "echo" ) == 0 )
 571         dirn = DI_ECHO;
 572     else if ( strcmp( directive, "fsize" ) == 0 )
 573         dirn = DI_FSIZE;
 574     else if ( strcmp( directive, "flastmod" ) == 0 )
 575         dirn = DI_FLASTMOD;
 576     else
 577         {
 578         unknown_directive( filename, directive );
 579         return;
 580         }
 581 
 582     for ( i = 0; i < ntags; ++i )
 583         {
 584         if ( i > 0 )
 585             putchar( ' ' );
 586         val = strchr( tags[i], '=' );
 587         if ( val == (char*) 0 )
 588             val = "";
 589         else
 590             *val++ = '\0';
 591         if ( *val == '"' && val[strlen( val ) - 1] == '"' )
 592             {
 593             val[strlen( val ) - 1] = '\0';
 594             ++val;
 595             }
 596         switch( dirn )
 597             {
 598             case DI_CONFIG:
 599             do_config( vfilename, filename, fp, directive, tags[i], val );
 600             break;
 601             case DI_INCLUDE:
 602             do_include( vfilename, filename, fp, directive, tags[i], val );
 603             break;
 604             case DI_ECHO:
 605             do_echo( vfilename, filename, fp, directive, tags[i], val );
 606             break;
 607             case DI_FSIZE:
 608             do_fsize( vfilename, filename, fp, directive, tags[i], val );
 609             break;
 610             case DI_FLASTMOD:
 611             do_flastmod( vfilename, filename, fp, directive, tags[i], val );
 612             break;
 613             }
 614         }
 615     }
 616 
 617 
 618 static void
 619 slurp( char* vfilename, char* filename, FILE* fp )
 620     {
 621     char buf[1000];
 622     int i;
 623     int state;
 624     int ich;
 625 
 626     /* Now slurp in the rest of the comment from the input file. */
 627     i = 0;
 628     state = ST_GROUND;
 629     while ( ( ich = getc( fp ) ) != EOF )
 630         {
 631         switch ( state )
 632             {
 633             case ST_GROUND:
 634             if ( ich == '-' )
 635                 state = ST_MINUS1;
 636             break;
 637             case ST_MINUS1:
 638             if ( ich == '-' )
 639                 state = ST_MINUS2;
 640             else
 641                 state = ST_GROUND;
 642             break;
 643             case ST_MINUS2:
 644             if ( ich == '>' )
 645                 {
 646                 buf[i - 2] = '\0';
 647                 parse( vfilename, filename, fp, buf );
 648                 return;
 649                 }
 650             else if ( ich != '-' )
 651                 state = ST_GROUND;
 652             break;
 653             }
 654         if ( (size_t) i < sizeof(buf) - 1 )
 655             buf[i++] = (char) ich;
 656         }
 657     }
 658 
 659 
 660 static void
 661 read_file( char* vfilename, char* filename, FILE* fp )
 662     {
 663     int ich;
 664     int state;
 665 
 666     /* Copy it to output, while running a state-machine to look for
 667     ** SSI directives.
 668     */
 669     state = ST_GROUND;
 670     while ( ( ich = getc( fp ) ) != EOF )
 671         {
 672         switch ( state )
 673             {
 674             case ST_GROUND:
 675             if ( ich == '<' )
 676                 { state = ST_LESSTHAN; continue; }
 677             break;
 678             case ST_LESSTHAN:
 679             if ( ich == '!' )
 680                 { state = ST_BANG; continue; }
 681             else
 682                 { state = ST_GROUND; putchar( '<' ); }
 683             break;
 684             case ST_BANG:
 685             if ( ich == '-' )
 686                 { state = ST_MINUS1; continue; }
 687             else
 688                 { state = ST_GROUND; (void) fputs ( "<!", stdout ); }
 689             break;
 690             case ST_MINUS1:
 691             if ( ich == '-' )
 692                 { state = ST_MINUS2; continue; }
 693             else
 694                 { state = ST_GROUND; (void) fputs ( "<!-", stdout ); }
 695             break;
 696             case ST_MINUS2:
 697             if ( ich == '#' )
 698                 {
 699                 slurp( vfilename, filename, fp );
 700                 state = ST_GROUND;
 701                 continue;
 702                 }
 703             else
 704                 { state = ST_GROUND; (void) fputs ( "<!--", stdout ); }
 705             break;
 706             }
 707         putchar( (char) ich );
 708         }
 709     }
 710 
 711 
 712 int
 713 main( int argc, char** argv )
 714     {
 715     char* script_name;
 716     char* path_info;
 717     char* path_translated;
 718     FILE* fp;
 719 
 720     (void) argc; /* XXX: gcc */
 721 
 722     argv0 = argv[0];
 723 
 724     /* Default formats. */
 725     (void) strcpy( timefmt, "%a %b %e %T %Z %Y" );
 726     sizefmt = SF_BYTES;
 727 
 728     /* The MIME type has to be text/html. */
 729     (void) fputs( "Content-type: text/html\n\n", stdout );
 730 
 731     /* Get the name that we were run as. */
 732     script_name = getenv( "SCRIPT_NAME" );
 733     if ( script_name == (char*) 0 )
 734         {
 735         internal_error( "Couldn't get SCRIPT_NAME environment variable." );
 736         exit( 1 );
 737         }
 738 
 739     /* Append the PATH_INFO, if any, to get the full URL. */
 740     path_info = getenv( "PATH_INFO" );
 741     if ( path_info == (char*) 0 )
 742         path_info = "";
 743     url = (char*) malloc( strlen( script_name ) + strlen( path_info ) + 1 );
 744     if ( url == (char*) 0 )
 745         {
 746         internal_error( "Out of memory." );
 747         exit( 1 );
 748         }
 749     (void) sprintf( url, "%s%s", script_name, path_info );
 750 
 751     /* Get the name of the file to parse. */
 752     path_translated = getenv( "PATH_TRANSLATED" );
 753     if ( path_translated == (char*) 0 )
 754         {
 755         internal_error( "Couldn't get PATH_TRANSLATED environment variable." );
 756         exit( 1 );
 757         }
 758 
 759     if ( ! check_filename( path_translated ) )
 760         {
 761         not_permitted( "initial", "PATH_TRANSLATED", path_translated );
 762         exit( 1 );
 763         }
 764 
 765     /* Open it. */
 766     fp = fopen( path_translated, "r" );
 767     if ( fp == (FILE*) 0 )
 768         {
 769         not_found( path_translated );
 770         exit( 1 );
 771         }
 772 
 773     /* Read and handle the file. */
 774     read_file( path_info, path_translated, fp );
 775 
 776     (void) fclose( fp );
 777     exit( 0 );
 778     }

/* [previous][next][first][last][top][bottom][index][help] */