
#---------------------------------- cut here ----------------------------------
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
#
# Wrapped by Alexander Carlton <aca@hpisp749> on Tue May  9 13:09:31 2000
#
# This archive contains:
#	spec99cadscan.c	spec99cgi.c	spec99fcgi.c	spec99gp.c	
#
# Error checking via wc(1) will be performed.
# Error checking via sum(1) will be performed.

LANG=""; export LANG
PATH=/bin:/usr/bin:/usr/sbin:/usr/ccs/bin:$PATH; export PATH
EXIT_STATUS=0

if sum -r </dev/null >/dev/null 2>&1
then
	sumopt='-r'
else
	sumopt=''
fi

echo x - spec99cadscan.c
cat >spec99cadscan.c <<'@EOF'
/*
** Copyright (c) 1999 by HEWLETT-PACKARD COMPANY. All Rights Reserved.
** 
** The information contained in this document is subject to change without 
** notice. 
** 
** HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE MATERIAL, 
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARANTIES OF MERCHANTABILITY 
** AND FITNESS FOR A PARTICULAR PURPOSE.
** 
** Hewlett-Packard shall not be liable for errors contained herein or for 
** incidental or consequential damages in connection with furnishing, 
** performance, or use of this material. Hewlett-Packard assumes no 
** responsibility for the use or reliability of its software on equipment 
** that is not furnished by Hewlett-Packard. This document contains proprietary 
** information that is protected by copyright. All rights are reserved. No 
** part of this document may be photocopied, reproduced, or translated to 
** another language without the prior written consent of Hewlett-Packard 
** Company.  
*/

/*
** spec99cadscan.c
**         Web server application for SPECweb99 dynamic requests. 
**         This module uses ISAPI to interface with the Web server.
**
** usage 1: GET with Cookie
**    GET /spec/isapi/cadscan.sl?/spec/file_set/dir<n>/class<x>_<y>
**    Cookie: my_cookie=user_id=<MyUser>&last_id=<Last_ad>
**
** Revision History:
**     07/23/99 (Yea-Cheng Wang)   
**                  For SPECweb99 blind submission.
*/


#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <syslog.h>
#include <sys/stat.h>

/* DOCUMENT ROOT */
#define TOPDIR "/spec/web99"

#define BUF_SIZE            256    
#define HTTP_BUF_SIZE       256    
#define COOKIE_BUF_SIZE     256    
#define HTML_BUF_SIZE       1024    

#define TITLE "<html>\n<head><title>SPECweb99 Dynamic GET & POST Test\
</title></head>\n<body>\n<p>SERVER_SOFTWARE = "
#define SCRIPT "\n<p>SCRIPT_NAME = "
#define REMOTE "\n<p>REMOTE_ADDR = "
#define QUERY  "\n<p>QUERY_STRING = "
#define BODY   "\n<pre>\n"
#define SUFFIX "\n</pre>\n</body></html>\n"
#define SPACE 64;

/* for sendRespMsg() */
#define HTTP_HEADER "Content-Type: text/html\n"


/**************************
**    Global Variables   **
**************************/

char prefix[HTML_BUF_SIZE];
int prefixLen=0;

char   *html;
char   fullName[MAXPATHLEN] = TOPDIR;
char*  urlName = fullName + sizeof(TOPDIR) -1;

/* Used by HttpExtensionProc(), and customAdRotation() */
char     *cookiePtr, *adPtr;

static char     httpCookie[] = "200 OK\nContent-Type: text/html\nSet-Cookie: found_cookie=Ad_id=360&Ad_weight=0000&Expired=0\nContent-Length:12345\n";
char*    httpContentCookiePtr  = httpCookie + 7;
char*    httpSetCookiePtr  = httpCookie + 31;
char*    httpCookieIdPtr   = httpCookie + 62;
char     httpWtCookie[]    = "&Ad_weight=00000";
char*    httpWtPtr         = httpWtCookie + 11;
char     httpExp0Cookie[]  = "&Expired=0";
char     httpExp1Cookie[]  = "&Expired=1";

char* customAdRotation (int * index);
char* readCAD ();

#define CAD_TEMPLATE "<!WEB99CAD><IMG SRC=\"/file_set/dir"
#define CAD_TEMPLATE_LEN  sizeof(CAD_TEMPLATE)-1
#define urlFileBufLen 100*1024


int cadScan (char  *fileName,  int  adID,   char  *urlFileBuf);


/********************************************
***   ISAPI  Extension Include Files     ****
********************************************/
#include "httpext.h"
#include "wintypes.h"

#define QUERY_STR ecb->lpszQueryString

int sendRespMsg (LPEXTENSION_CONTROL_BLOCK  ecb,
char *httpHeaderPtr,
char *htmlHeader, int htmlLen, 
char *msg);


/****************************
***   ISAPI  Extension   ****
****************************/

BOOL WINAPI
GetExtensionVersion( HSE_VERSION_INFO *pVer )
{
	/* ISAPI initialization routine */

	/*pVer->dwExtensionVersion = HSE_VERSION_MAJOR;*/
	pVer->dwExtensionVersion = 1;

	strncpy(pVer->lpszExtensionDesc, "Specweb99", 
	    HSE_MAX_EXT_DLL_NAME_LEN);

	/* default with everything being zero. */

	html = malloc(urlFileBufLen+HTML_BUF_SIZE+sizeof(SUFFIX));

	return TRUE;
}


#define CONTENT_COOKIE_ERR_OFFS 7

int WINAPI
HttpExtensionProc( LPEXTENSION_CONTROL_BLOCK ecb )
{
	/* This ISAPI HTTP Extension function is called when there is a */
        /* HTTP request on this application module. */

	int	hseStatus;
	char	cookieStr[COOKIE_BUF_SIZE];
	char	*this;
	char	*htmlPtr;
	int	htmlLen, length;
	int	tLen;
	HSE_TF_INFO	tf1;


	/* Set up the HTML Page */
	if (0 == prefixLen) {
		/* the first time */
		strcpy (html, TITLE);
		htmlPtr = html + sizeof(TITLE)-1;
		length = SPACE;

		ecb->GetServerVariable(ecb->ConnID, "SERVER_SOFTWARE",
		    htmlPtr, &length);
		htmlPtr += --length;

		strcpy (htmlPtr, SCRIPT);
		htmlPtr = htmlPtr + sizeof(SCRIPT)-1;
		length  = SPACE;

		ecb->GetServerVariable(ecb->ConnID, "SCRIPT_NAME", htmlPtr,
		    &length);
		htmlPtr += --length;

		strcpy (htmlPtr, REMOTE);
		htmlPtr = htmlPtr + sizeof(REMOTE)-1;

		prefixLen = htmlPtr - html;
		strcpy (prefix, html);
	}

	htmlPtr = html + prefixLen;

	length  = SPACE;
	ecb->GetServerVariable(ecb->ConnID, "REMOTE_ADDR", htmlPtr,
	    &length);
	htmlPtr += --length;

	sprintf(htmlPtr, "%s%s%s", QUERY, QUERY_STR, BODY);
	htmlLen = strlen (html);


	length = COOKIE_BUF_SIZE;
	ecb->GetServerVariable(ecb->ConnID, "ALL_HTTP", cookieStr, &length);

	/* Cookie: my_cookie=user_id=10012&last_ad=120 */
	cookiePtr = adPtr = NULL;
	if (NULL != (this = strchr(cookieStr, '='))) {
		if (NULL != (this = strchr(++this, '='))) {
			cookiePtr = ++this;
			this = cookiePtr + 5;
			*this = '\0';
			adPtr = this = this + 8;
			if (NULL != (this = strchr(this, '\n')))
				*this = '\0';
		}
	}

	/* Process the HTTP Request */

	if (0 == strcmp(ecb->lpszMethod, "GET")) {
		/*********************/
		/***  GET REQUEST  ***/
		/*********************/

		if ( strlen(QUERY_STR) > 0) {

			int adID;
			char *classPtr;
			char *cookieMsgPtr;
			int  urlFileLen;

			/* return the file in query string */
			strcpy(urlName, QUERY_STR);

			/* Need to process WEB99CAD if it is class1/class2 */
			if ( ((classPtr = strstr (urlName, "class")) != NULL) && 
			    (49 == *(classPtr+5) || 50 == *(classPtr+5)) ){

				cookieMsgPtr = (char *) customAdRotation(&adID);

				if ( -1 == adID ) {
					hseStatus = sendRespMsg(ecb, 
					    cookieMsgPtr+CONTENT_COOKIE_ERR_OFFS,
					    html, htmlLen,
					    "Bad Cookie ID!\n");
				} else {
					if (-1 == (urlFileLen = cadScan(fullName, adID,
					    &html[htmlLen]))){

						hseStatus = sendRespMsg(ecb, 
						    httpContentCookiePtr,
						    html, htmlLen,
						    NULL);
					} else {
						int length;
						length = strlen (httpContentCookiePtr);
						sprintf (&httpContentCookiePtr[length], 
						    "\nContent-Length: %d\n",
						    htmlLen+urlFileLen+sizeof(SUFFIX)-1);
						hseStatus = sendRespMsg(ecb, 
						    httpContentCookiePtr,
						    html, htmlLen+urlFileLen,
						    NULL);
					}

				}

			} else {  /* class0 or class2 */
				memset( &tf1, 0, sizeof( HSE_TF_INFO ) );

				/* customAdRotation returns either valid */
				/* cookie string, or error information about */
				/* cookie string */
				ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_ALLOC_MEM,
				    &tf1.pHead,&htmlLen,0);
				tf1.pHead=(PVOID)html;
				tf1.TailLength=tLen=sizeof(SUFFIX)-1;
				ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_ALLOC_MEM,
				    &tf1.pTail,&tLen,0);
				tf1.pTail=(PVOID)SUFFIX;
				tf1.dwFlags = HSE_IO_SEND_HEADERS|HSE_IO_DISCONNECT_AFTER_SEND|
				    HSE_IO_HANDLE_IS_FILENAME;
				tf1.pszStatusCode = (const char *) customAdRotation(&adID);

				tf1.HeadLength = htmlLen;
				tf1.hFile    = (HANDLE)fullName;

				if( ecb->ServerSupportFunction(ecb->ConnID, 
				    HSE_REQ_TRANSMIT_FILE, &tf1, 0, 0 ) == TRUE )
					return HSE_STATUS_SUCCESS_AND_KEEP_CONN;

				return HSE_STATUS_ERROR;

			} /* WEB99CAD: non class1/class2 */

		} else {
			/* respond now with the message */
			hseStatus = sendRespMsg(ecb, 
			    (char *)NULL,
			    html, htmlLen,
			    "QUERY_STRING not set!\n");
		}
	} /* GET request */

	return hseStatus;
}

#define newURLLen 14

int cadScan (char  *fileName,  int  adID, char  *urlFileBuf)
{
	int   fd;
	int   readLen;
	char  *template;
	char  newURL[newURLLen+1];
	int   len;

	if ((fd = open (fileName, O_RDONLY, NULL)) == -1) {
		sprintf (urlFileBuf, "Cannot open file '%s' (%s)\n",
		    fileName, strerror(errno) );
		return -1;
	}

	readLen = (int) read (fd, urlFileBuf, urlFileBufLen);

	close (fd);

	urlFileBuf[readLen] = '\0';

	template = urlFileBuf;

	sprintf (newURL, "%05d/class%d_%d", adID/36, (adID%36)/9, adID%9);

	while (NULL != (template = strstr(template, CAD_TEMPLATE))) {
		template += CAD_TEMPLATE_LEN;
		strncpy(template, newURL, newURLLen);
		template += newURLLen;
	}

	return readLen;

}


/*******************************************************************
***                    Customized Ad Rotation                    ***
********************************************************************/

#define GENDER_MASK    0x30000000
#define AGE_GROUP_MASK 0x0f000000
#define REGION_MASK    0x00f00000
#define INTEREST1_MASK 0x000ffc00
#define INTEREST2_MASK 0x000003ff

#define CADFILE TOPDIR"/Custom.Ads"
#define UPFILE  TOPDIR"/User.Personality"

#define USER_REC_LEN   15
#define USER_DEMO_OFFS 6
#define USER_DEMO_LEN  USER_REC_LEN - USER_DEMO_OFFS

#define CADFILE_ENTRIES 360
#define CAD_REC_LEN     39
#define CAD_DEMO_OFFS   6
#define CAD_WEIGHT_OFFS 15
#define CAD_MIN_OFFS    24
#define CAD_EXPIRE_OFFS 28

/* Status and Set-Cookie error string */
#define LAST_AD_ERR      "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-10&Ad_weight=00&Expired=1"
#define UPF_OPEN_ERR     "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-9&Ad_weight=00&Expired=0"
#define CAD_OPEN_ERR     "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-9&Ad_weight=00&Expired=1"
#define UPF_SEEK_ERR     "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-8&Ad_weight=00&Expired=0"
#define UPF_READ_ERR     "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-7&Ad_weight=00&Expired=0"
#define CAD_READ_ERR     "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-7&Ad_weight=00&Expired=1"
#define UPF_RECORD_ERR   "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-6&Ad_weight=00&Expired=0"
#define CAD_RECORD_ERR   "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-6&Ad_weight=00&Expired=1"
#define RECORD_NOT_FOUND "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-1&Ad_weight=00&Expired=0"
#define CAD_NOT_MATCHED  "200 OK\nContent-Type: text/html\n\
                          Set-Cookie: Ad_id=-1&Ad_weight=00&Expired=1"

FILE    *upfPtr=NULL;
time_t  lastTime;

/* The following are defined in readCAD(), referred to in customAdRotation() */
unsigned int     adDemograf[CADFILE_ENTRIES];
int              adMinMatch[CADFILE_ENTRIES];
int              adExpiration[CADFILE_ENTRIES];
int              adWtGender[CADFILE_ENTRIES];
int              adWtAge[CADFILE_ENTRIES];
int              adWtRegion[CADFILE_ENTRIES];
int              adWtInterest1[CADFILE_ENTRIES];
int              adWtInterest2[CADFILE_ENTRIES];

/***************************************************************************
   If customAdRotation() can retrieve the adIndex successfully, it will 
   return the constructed cookie string in httpCookie[].The cookieIndex will
   then be the adIndex, httpCookie[] is the returned pointer.
   If it cannot retrieve the adIndex successfully, it will set cookieIndex to
   -1, and return one of the predefined Set-Cookie error HTML status strings.
***************************************************************************/
char* customAdRotation (int *cookieIndex)
{
	int          myUser, adIndex, ad;
	long int     offset;
	char         demographics[USER_REC_LEN];
	unsigned int userDemograf, combined;
	struct stat  cadStat;
	int          weight;

	char         *cookieStatus;



	*cookieIndex = -1;    /* in case it failed to get the proper adIndex */

	/* Get the User Profile from the UPFILE */

	myUser = atoi(cookiePtr) - 10000;
	offset = myUser * USER_REC_LEN + USER_DEMO_OFFS;

	if (NULL == upfPtr)
		if (NULL == (upfPtr = fopen (UPFILE, "r"))) {
			syslog (LOG_ERR, "SPECweb99 Cookie: UPF file: '%s' open error (%s)",
			    UPFILE, strerror(errno));
			return UPF_OPEN_ERR;
		}

	if (0 != fseek(upfPtr, (long int) offset, SEEK_SET)) {
		syslog (LOG_ERR, "SPECweb99 Cookie: UPF file: '%s' seek error (%s)", 
		    UPFILE, strerror(errno));
		return UPF_SEEK_ERR;
	}

	if ( USER_DEMO_LEN != fread(demographics, (size_t)sizeof(char),
	    (size_t)USER_DEMO_LEN, upfPtr)) {
		syslog (LOG_ERR, "SPECweb99 Cookie: UPF Demographics read error (%s)", 
		    strerror(errno));
		return UPF_READ_ERR;
	}

	if ( 0 == (userDemograf = (int) strtoul(demographics,(char **)NULL, 16))){
		syslog (LOG_ERR, "SPECweb99 Cookie: Demographics strtoul() error (%s)", 
		    strerror(errno));
		return UPF_RECORD_ERR;
	}

	adIndex = atoi(adPtr);
	if (( adIndex >= CADFILE_ENTRIES) || (adIndex < 0 )) {
		syslog (LOG_ERR, "SPECweb99 Cookie: Invalid Ad Index (%d)", 
		    adIndex);
		return LAST_AD_ERR;
	}
	adIndex++;
	if ( CADFILE_ENTRIES == adIndex )
		adIndex = 0;

	/* Has the file been modified? */
	if (stat(CADFILE, &cadStat) <0) {
		syslog (LOG_ERR, "SPECweb99 Cookie: stat failed on %s (%s)\n", 
		    CADFILE, strerror(errno));
	}
	if (cadStat.st_mtime > lastTime) {

		lastTime = cadStat.st_mtime;

		/* read in the latest CADFILE */
		if (NULL != (cookieStatus =readCAD()))
			return cookieStatus;
	}

	/* CADFILE has been successfully read in */
	/* Now loop for the matched CAD record starting at adIndex */

	for (ad = 0; ad<CADFILE_ENTRIES; ad++ ) {
		combined = adDemograf[adIndex] & userDemograf;

		weight = 0;
		if (0 != (combined & GENDER_MASK ))
			weight += adWtGender[adIndex];
		if (0 != (combined & AGE_GROUP_MASK ))
			weight += adWtAge[adIndex];
		if (0 != (combined & REGION_MASK ))
			weight += adWtRegion[adIndex];
		if (0 != (combined & INTEREST1_MASK ))
			weight += adWtInterest1[adIndex];
		if (0 != (combined & INTEREST2_MASK ))
			weight += adWtInterest2[adIndex];

		if (weight >= adMinMatch[adIndex]) {

			/* customAdRotation is successful */
			*cookieIndex = adIndex;

			strcpy (httpCookieIdPtr, ltoa(adIndex));
			strcpy (httpWtPtr, ltoa(weight));
			strcat (httpCookie, httpWtCookie);

			/* Check for expiry */
			if (time(NULL) > adExpiration[adIndex])
				strcat (httpCookie,httpExp1Cookie);
			else
				strcat (httpCookie,httpExp0Cookie);

			/* return the new cookie string */
			return httpCookie;

		}

		adIndex++;
		if ( CADFILE_ENTRIES == adIndex )
			adIndex = 0;

	} /* Loop for the next CAD record */

	return CAD_NOT_MATCHED;

}

/* The following are used only in readCAD() */
char    cadRec[CAD_REC_LEN];
char*   cadDemoPtr   = cadRec + CAD_DEMO_OFFS;
char*   cadWeightPtr = cadRec + CAD_WEIGHT_OFFS;
char*   cadMinPtr    = cadRec + CAD_MIN_OFFS;
char*   cadExpirePtr = cadRec + +CAD_EXPIRE_OFFS;

char* readCAD () {
	int          index;
	unsigned int adWeight;
	FILE         *cadfPtr;

	if (NULL == (cadfPtr = fopen (CADFILE, "r"))) {
		syslog (LOG_ERR, "SPECweb99 Cookie: CAD file open error (%s)", 
		    strerror(errno));
		return CAD_OPEN_ERR;
	}

	for (index = 0; index<CADFILE_ENTRIES; index++ ) {

		if ( CAD_REC_LEN != fread(cadRec, (size_t)sizeof(char),
		    (size_t)CAD_REC_LEN, cadfPtr)) {
			syslog (LOG_ERR, "SPECweb99 Cookie: CAD record read error (%s)", 
			    strerror(errno));
			return CAD_READ_ERR;
		}

		if (0 == (adDemograf[index]  = 
		    (int) strtoul(cadDemoPtr, (char **)NULL, 16)))
			return CAD_RECORD_ERR;
		if (0 == (adWeight = 
		    (int) strtoul(cadWeightPtr, (char **)NULL, 16)))
			return CAD_RECORD_ERR;
		if (0 == (adMinMatch[index]  = atoi(cadMinPtr)))
			return CAD_RECORD_ERR;
		if (0 == (adExpiration[index]= atoi(cadExpirePtr)))
			return CAD_RECORD_ERR;

		adWtInterest2[index] = adWeight & 0x0000000f;
		adWtInterest1[index] = (adWeight >>  4) & 0x0000000f;
		adWtRegion[index]    = (adWeight >>  8) & 0x0000000f;
		adWtAge[index]       = (adWeight >> 12) & 0x0000000f;
		adWtGender[index]    = (adWeight >> 16) & 0x0000000f;
	} /* for index loop */

	return NULL;
}

/*
** Send the HTTP response back to the client.
** 
*/
int sendRespMsg (LPEXTENSION_CONTROL_BLOCK ecb,
char* httpHeaderPtr,
char *htmlHeader, int htmlLen, 
char *msg)
{
	int       status;
	int       length;
	int 	buffer[256];

	/* Set the response header using ISAPI HSE Support function. */
	/*   - if httpHeaderPtr is NULL, use the predefined HTTP_HEADER, */
	/*     otherwise use the given string. */

	/* Send the HTTP response back using ISAPI WriteClient funciton. */
	/*   - If msg is not NULL, then send this message in addition to the */
	/*     HTML close tag to the client.  */

	/* Set the http header for the response message */
	if (NULL == httpHeaderPtr) {
		length = sizeof (HTTP_HEADER) -1;
		strcpy((char *)buffer,HTTP_HEADER);
		if (!ecb->ServerSupportFunction(ecb->ConnID,
		    HSE_REQ_SEND_RESPONSE_HEADER, 0, &length, 
		    (int*)buffer))
			return HSE_STATUS_ERROR;
	} else {
		length = strlen (httpHeaderPtr) - 1;
		strcpy((char *)buffer,httpHeaderPtr);
		if (!ecb->ServerSupportFunction(ecb->ConnID,
		    HSE_REQ_SEND_RESPONSE_HEADER, 0, &length, 
		    (int*)buffer))
			return HSE_STATUS_ERROR;
	}

	/* Send the html OPEN tags, msg if any, and close tag */
        /* using WriteCleint() support function */

	if (NULL != msg) {
		/* send both the msg and the HTTP CLOSE to the client using */
		/* WriteClient() support function.  */
		if (ecb->WriteClient(ecb->ConnID, htmlHeader, &htmlLen, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
		length =strlen(msg);
		if (ecb->WriteClient(ecb->ConnID, msg, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
		length =strlen(SUFFIX);
		if (ecb->WriteClient(ecb->ConnID, SUFFIX, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
	} else {
		/* send just the HTML CLOSE tag */
		length =strlen(SUFFIX);
		ecb->WriteClient(ecb->ConnID, htmlHeader, &htmlLen, 0);
		if (ecb->WriteClient(ecb->ConnID, SUFFIX, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
	}
}
@EOF
set `sum $sumopt <spec99cadscan.c`; if test $1 -ne 63310
then
	echo ERROR: spec99cadscan.c checksum is $1 should be 63310
EXIT_STATUS=1
fi
set `wc -lwc <spec99cadscan.c`
if test $1$2$3 != 637202418584
then
	echo ERROR: wc results of spec99cadscan.c are $* should be 637 2024 18584
EXIT_STATUS=1
fi

chmod 666 spec99cadscan.c

echo x - spec99cgi.c
cat >spec99cgi.c <<'@EOF'
/*
** Copyright (c) 1999 by HEWLETT-PACKARD COMPANY. All Rights Reserved.
** 
** The information contained in this document is subject to change without 
** notice. 
** 
** HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE MATERIAL, 
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARANTIES OF MERCHANTABILITY 
** AND FITNESS FOR A PARTICULAR PURPOSE.
** 
** Hewlett-Packard shall not be liable for errors contained herein or for 
** incidental or consequential damages in connection with furnishing, 
** performance, or use of this material. Hewlett-Packard assumes no 
** responsibility for the use or reliability of its software on equipment 
** that is not furnished by Hewlett-Packard. This document contains proprietary 
** information that is protected by copyright. All rights are reserved. No 
** part of this document may be photocopied, reproduced, or translated to 
** another language without the prior written consent of Hewlett-Packard 
** Company.  
*/

/*
** spec99cgi.c
**
**    CGI module for SPECweb99.
**
** usage 1: cgi GET
**    GET /spec/cgi-bin/spec99.cgi?/spec/file_set/dir<n>/class<x>_<y>
**/

#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/types.h>
#include <syslog.h>


#define TITLE "<html>\n<head><title>SPECweb99 Dynamic GET & POST Test\
</title></head>\n<body>\n<p>SERVER_SOFTWARE = "

#define BUF_LEN 1024*1025

#define TOPDIR "/spec/web99"
#define TOPDIR_LEN sizeof(TOPDIR)-1


size_t printFile(char *where, size_t length, char *fileName);

void
main(int argc, char **argv) {

	char     *query;
	char     *method;

	char    urlFileBuf[BUF_LEN];
	size_t  len=0;
	ssize_t  tmp;
	int fid;
	char    fullname[MAXPATHLEN]=TOPDIR;


	len+=sprintf(urlFileBuf, "%s%s\n", TITLE, getenv("SERVER_SOFTWARE"));

	len+=sprintf(urlFileBuf+len, 
	    "<p>REMOTE_ADDR = %s\n", getenv("REMOTE_ADDR"));

	len+=sprintf(urlFileBuf+len,
	    "<p>SCRIPT_NAME = %s\n", getenv("SCRIPT_NAME"));

	query = getenv("QUERY_STRING");
	len+=sprintf(urlFileBuf+len,
	    "<p>QUERY_STRING = %s\n<pre>\n", query);

	if ( (method = getenv("REQUEST_METHOD")) &&
	    (strcmp(method, "GET") == 0) )
	{
		/*********************/
		/***  GET REQUEST  ***/
		/*********************/

		if (query && (sizeof(query) < MAXPATHLEN))
		{
			/* return the file in query string */
			sprintf(fullname+TOPDIR_LEN, "%s", query);
			len+=printFile(urlFileBuf+len, (size_t) (BUF_LEN-len), fullname);
		} else if (!query)
			len+=sprintf(urlFileBuf+len,"QUERY STRING not set!\n");
		else len+=sprintf(urlFileBuf+len,
		    "QUERY STRING is longer than %d bytes\n", MAXPATHLEN);

	} /* GET request */

	len+=sprintf(urlFileBuf+len, "\n</pre>\n</body></html>\n");

	fid=atoi(argv[2]);
	tmp = write(fid, urlFileBuf, (size_t)len);
}


size_t printFile(char *where, size_t length, char *fileName)
{
	int      fd;
	ssize_t  byteRead;
	size_t      new_len=0;

	if ((fd = open(fileName, O_RDONLY)) < 0) {
		new_len+=sprintf(where, "Could not open file for reading - \"%s\" (%s)",
		    fileName, strerror(errno));
	} else {
		byteRead = read(fd, where, (ssize_t)length);

		if (byteRead < 0)
			new_len+=sprintf(where, "Error reading file '%s': error is %s\n", 
			    fileName, strerror(errno));
		else
			new_len+=byteRead;

		if (close(fd) < 0)
			new_len+=sprintf(where+new_len, 
			    "Could not close file - \"%s\" (%s)", fileName,
			    strerror(errno));
	}
	return new_len;
}
@EOF
set `sum $sumopt <spec99cgi.c`; if test $1 -ne 58838
then
	echo ERROR: spec99cgi.c checksum is $1 should be 58838
EXIT_STATUS=1
fi
set `wc -lwc <spec99cgi.c`
if test $1$2$3 != 1294063500
then
	echo ERROR: wc results of spec99cgi.c are $* should be 129 406 3500
EXIT_STATUS=1
fi

chmod 666 spec99cgi.c

echo x - spec99fcgi.c
cat >spec99fcgi.c <<'@EOF'
/*
** Copyright (c) 1999 by HEWLETT-PACKARD COMPANY. All Rights Reserved.
** 
** The information contained in this document is subject to change without 
** notice. 
** 
** HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE MATERIAL, 
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARANTIES OF MERCHANTABILITY 
** AND FITNESS FOR A PARTICULAR PURPOSE.
** 
** Hewlett-Packard shall not be liable for errors contained herein or for 
** incidental or consequential damages in connection with furnishing, 
** performance, or use of this material. Hewlett-Packard assumes no 
** responsibility for the use or reliability of its software on equipment 
** that is not furnished by Hewlett-Packard. This document contains proprietary 
** information that is protected by copyright. All rights are reserved. No 
** part of this document may be photocopied, reproduced, or translated to 
** another language without the prior written consent of Hewlett-Packard 
** Company.  
*/

/*
** spec99cgi.c
**
**    CGI module for SPECweb99.
**
** usage 1: cgi GET
**    GET /spec/cgi-bin/spec99.cgi?/spec/file_set/dir<n>/class<x>_<y>
**/

#include <fcgi_stdio.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <limits.h>
#include <sys/param.h>
#include <sys/types.h>
#include <signal.h>
#include <syslog.h>
#include <errno.h>

#define BUFFLEN 1049600

extern	char **	environ;


cgimain() {
	char     *query;
	char     *method;

	int      len,i=0;
	int n,pid;
	static char *childargs[4]= {"spec.cgi","1","2",0};
	char inbuff[1024];
	int in[2],out[2];
	char buff[BUFFLEN];
	int count;
	int	rc;


	rc = pipe(in);
	if( rc < 0 ) {
		syslog(LOG_ERR, "Cannot pipe in (%d)\n", errno);
		exit(1);
	}

	rc = pipe(out);
	if( rc < 0 ) {
		syslog(LOG_ERR, "Cannot pipe out (%d)\n", errno);
		exit(1);
	}

	sprintf(childargs[1], "%d", out[0]);
	sprintf(childargs[2], "%d", in[1]);

	pid = vfork();
	if( pid == 0 ) {
		close(out[1]);
		close(in[0]);
		execve("/SPEC/web99/cgi-bin/spec.cgi", childargs, environ);
		syslog(LOG_ERR, "Failed exec (%d)\n", errno);
		_exit(1);
	}

	/* parent  */
	close(out[0]);
	close(in[1]);

	while ( (n= read(in[0],&buff[len], 8192)) >0)
	    len+=n;

	    buff[len]='\0'; 
	    printf("%s",buff);

	    waitpid(pid,NULL,0);
	    close(out[1]);
	    close(in[0]);

}

void
main() {
	int count, fd;

	/* Disconnect everything from parent */
	count = 0;
	for( fd=1 ; fd<MAXFUPLIM ; fd++ ) {
	    if( close(fd) >= 0 ) {
		count++;
	    }
	}

	syslog(LOG_ERR, "FastCGI: In parent we closed %d files\n",count);

	while ( FCGI_Accept() >= 0 ) {
		cgimain();
	}
}
@EOF
set `sum $sumopt <spec99fcgi.c`; if test $1 -ne 63056
then
	echo ERROR: spec99fcgi.c checksum is $1 should be 63056
EXIT_STATUS=1
fi
set `wc -lwc <spec99fcgi.c`
if test $1$2$3 != 1213552649
then
	echo ERROR: wc results of spec99fcgi.c are $* should be 121 355 2649
EXIT_STATUS=1
fi

chmod 666 spec99fcgi.c

echo x - spec99gp.c
cat >spec99gp.c <<'@EOF'
/*
** Copyright (c) 1999 by HEWLETT-PACKARD COMPANY. All Rights Reserved.
** 
** The information contained in this document is subject to change without 
** notice. 
** 
** HEWLETT-PACKARD MAKES NO WARRANTY OF ANY KIND WITH REGARD TO THE MATERIAL, 
** INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARANTIES OF MERCHANTABILITY 
** AND FITNESS FOR A PARTICULAR PURPOSE.
** 
** Hewlett-Packard shall not be liable for errors contained herein or for 
** incidental or consequential damages in connection with furnishing, 
** performance, or use of this material. Hewlett-Packard assumes no 
** responsibility for the use or reliability of its software on equipment 
** that is not furnished by Hewlett-Packard. This document contains proprietary 
** information that is protected by copyright. All rights are reserved. No 
** part of this document may be photocopied, reproduced, or translated to 
** another language without the prior written consent of Hewlett-Packard 
** Company.  
*/


/*
** spec99gp.c
**
**         Web server application for SPECweb99 dynamic requests. 
**         This module uses ISAPI to interface with the Web server.
**
** usage 1: GET
**    GET /spec/isapi/spec99gp.sl?/spec/file_set/dir<n>/class<x>_<y>
**
** usage 2: commands
**    GET /spec/isapi/spec99gp.sl?command/Reset&ml=n&pt=t&th=t&exp=l
**    GET /spec/isapi/spec99gp.sl?command/Fetch
**
** usage 3: POST
**   POST /spec/isapi/spec99gp.sl
**   Content-length: <length>
**
**   urlroot=/spec/file_set/&dir=<n>&class=<x>&num=<y>&client=<client_id>
**
**   ("key=val" are separated by a "&")
**
** Change History:
**     07/23/99 (Yea-Cheng Wang)   
**                  For SPECweb99 blind submission.
*/

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <sys/param.h>
#include <sys/types.h>
#include <syslog.h>
#include <sys/sem.h>

/* DOCUMENT ROOT */
#define TOPDIR "/spec/web99"
#define CADGEN_CMD "/spec/web99/cadgen99"
#define UPFGEN_CMD "/spec/web99/upfgen99"

#define BUF_SIZE            256    
#define HTTP_BUF_SIZE       256    
#define HTML_BUF_SIZE       1024    
#define READ_BUF_SIZE       4096
#define COOKIE_BUF_SIZE     256
#define POST_BUF_SIZE       512
#define COUNT_LEN           10
#define POST_LOG            "/logs/post.log"

#define TITLE "<html>\n<head><title>SPECweb99 Dynamic GET & POST Test\
</title></head>\n<body>\n<p>SERVER_SOFTWARE = "
#define SCRIPT "\n<p>SCRIPT_NAME = "
#define REMOTE "\n<p>REMOTE_ADDR = "
#define QUERY  "\n<p>QUERY_STRING = "
#define QUERYnBODY  "\n<p>QUERY_STRING = \n<pre>\n"
#define BODY   "\n<pre>\n"
#define SUFFIX "\n</pre>\n</body></html>\n"
#define SPACE 64;

#define HTTP_HEADER "Content-Type: text/html\n"
#define HTTP_STATUS "Content-Type: text/html\r\n"

/**************************
**    Global Variables   **
**************************/

char prefix[HTML_BUF_SIZE];
int prefixLen=0;

char   html[HTML_BUF_SIZE];
char   fullName[MAXPATHLEN] = TOPDIR;
char*  urlName = fullName + sizeof(TOPDIR) -1;

char   logFile[MAXPATHLEN]  = POST_LOG;

static char   httpCookie[] = "200 OK\r\nSet-Cookie: my_cookie=360----\r\n";
char*  cookieIdPtr = httpCookie + 30;
char        *cookiePtr;

pid_t    mypid;
int      logfd=0;

char     tmpBuf[BUF_SIZE];

int sem_id;
extern int errno;

/******************************
***   ISAPI  Extension     ****
******************************/
#include "httpext.h"
#include "wintypes.h"


#define QUERY_STR ecb->lpszQueryString

int sendRespMsg (LPEXTENSION_CONTROL_BLOCK  ecb,
	char *htmlHeader, int htmlLen, char *msg);

int createLogSendResp (LPEXTENSION_CONTROL_BLOCK  ecb,
	char *htmlHeader, int htmlLen, char *fileName);

int sendRespLogFile   (LPEXTENSION_CONTROL_BLOCK  ecb,
	char *htmlHeader, int htmlLen, char *fileName);

int sem_init();
int get_sema();
int release_sema();
void remove_sema();

static unsigned int gct=0;


BOOL WINAPI
GetExtensionVersion( HSE_VERSION_INFO *pVer )
{

	/* ISAPI initialization routine */

	pVer->dwExtensionVersion = 1;

	strncpy(pVer->lpszExtensionDesc, "SPECweb99 v1.0", 
	    HSE_MAX_EXT_DLL_NAME_LEN);

	/* default with everything being zero. */

	mypid = getpid();
	sem_init();
	atexit(remove_sema); /* cleanup semaphore before exit */
	return TRUE;
}


int WINAPI
HttpExtensionProc( LPEXTENSION_CONTROL_BLOCK ecb )
{
	/* This ISAPI HTTP Extension function is called when there is a */
	/* HTTP request on this application module.  */

	int   hseStatus;
	char  *maxldPtr, *pttPtr, *thPtr, *expPtr, *this;
	char  cmdCAD[BUF_SIZE] = CADGEN_CMD;
	char  cmdUPF[BUF_SIZE] = UPFGEN_CMD;
	HSE_TF_INFO tf;

	/* html[]: applicaton's HTML Page */
	char *htmlPtr;
	int  htmlLen, length;
	int tLen;

	memset( &tf, 0, sizeof( HSE_TF_INFO ) );

	tf.HeadLength=htmlLen=strlen(html);
	ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_ALLOC_MEM,
	    &tf.pHead,&htmlLen,0);
	tf.pHead=(PVOID)html;
	tf.TailLength=tLen=sizeof(SUFFIX)-1;
	ecb->ServerSupportFunction(ecb->ConnID, HSE_REQ_ALLOC_MEM,
	    &tf.pTail,&tLen,0);
	tf.pTail=(PVOID)SUFFIX;
	tf.dwFlags = HSE_IO_SEND_HEADERS|HSE_IO_DISCONNECT_AFTER_SEND|
	    HSE_IO_HANDLE_IS_FILENAME;


	gct++;
	/* Set up the HTML Page */
	if (0 == prefixLen) {
		strcpy (html, TITLE);
		htmlPtr = html + sizeof(TITLE) - 1;
		length = SPACE;

		ecb->GetServerVariable(ecb->ConnID, "SERVER_SOFTWARE",
		    htmlPtr, &length);
		htmlPtr += --length;

		strcpy (htmlPtr, SCRIPT);
		htmlPtr = htmlPtr + sizeof(SCRIPT) - 1;
		length  = SPACE;

		ecb->GetServerVariable(ecb->ConnID, "SCRIPT_NAME", htmlPtr,
		    &length);
		htmlPtr += --length;

		strcpy (htmlPtr, REMOTE);
		htmlPtr = htmlPtr + sizeof(REMOTE) - 1;

		prefixLen = htmlPtr - html;
		strcpy (prefix, html);
	}

	htmlPtr = html + prefixLen;

	length  = SPACE;
	ecb->GetServerVariable(ecb->ConnID, "REMOTE_ADDR", htmlPtr,
	    &length);
	htmlPtr += --length;


	/* Process the HTTP Request */

	if (0 == strcmp(ecb->lpszMethod, "GET")) {
		/*********************/
		/***  GET REQUEST  ***/
		/*********************/

		sprintf(htmlPtr, "%s%s%s", QUERY, QUERY_STR, BODY);
		if ( NULL != strchr(QUERY_STR,'-'))
			syslog(LOG_ERR,"INCORRECT STR PASSED =%s\n",QUERY_STR);

		htmlLen = strlen (html);

		if ( strlen(QUERY_STR) > 0) {

			if (strncmp(QUERY_STR, "command/Reset", 13) == 0) {

				/* command/Reset&maxload=n&pttime=time&maxthread=th&exp=list */
				if (NULL != (this = strchr(QUERY_STR, '='))) {
					maxldPtr = ++this;
					if (NULL != (this = strchr(this, '&'))) {
						*this = '\0';
						if (NULL != (this = strchr(++this, '='))) {
							pttPtr = ++this;
							if (NULL != (this = strchr(this, '&'))) {
								*this = '\0';
								if (NULL != (this = strchr(++this, '='))) {
/* code folded from here */
	thPtr = ++this;
	if (NULL != (this = strchr(this, '&'))) {
		*this = '\0';
		if (NULL != (this = strchr(++this, '='))) {
			expPtr = ++this;
			if (NULL != (this = strchr(this, ','))) {
				*this = ' ';
			}
		}
	}
/* unfolding */
								}
							}
						}
					}
				}

				sprintf(cmdUPF+strlen(cmdUPF), " -C %s -n %s -t %s", 
				    TOPDIR, maxldPtr, thPtr);
				sprintf(cmdCAD+strlen(cmdCAD), " -C %s -e %s -t %s %s", 
				    TOPDIR, pttPtr, thPtr, expPtr);

				system (cmdUPF);
				system (cmdCAD);

				syslog (LOG_ERR, "cmdUPF: %s\n", cmdUPF);
				syslog (LOG_ERR, "cmdCAD: %s\n", cmdCAD);


				/* create the log file */
				hseStatus = createLogSendResp(ecb, 
				    html, htmlLen,
				    logFile);
			}
			else if (strcmp(QUERY_STR, "command/Fetch") == 0) {
				/* return the log file */
				hseStatus = sendRespLogFile(ecb, 
				    html, htmlLen,
				    logFile);
			}
			else {

				/* return the file in query string */
				strcpy(urlName, QUERY_STR);

				tf.pHead = (PVOID)html;
				tf.pTail = (PVOID)SUFFIX;
				tf.TailLength = sizeof(SUFFIX) - 1;
				tf.dwFlags = HSE_IO_SEND_HEADERS|HSE_IO_DISCONNECT_AFTER_SEND| HSE_IO_HANDLE_IS_FILENAME;
				tf.pszStatusCode = (const char *) HTTP_STATUS;
				tf.hFile    = (HANDLE)fullName;
				tf.HeadLength = htmlLen;
				if ( NULL != strchr(tf.hFile,'-'))
					syslog(LOG_ERR,"hFile INCORRECT STR PASSED =%s\n",QUERY_STR);

				if( ecb->ServerSupportFunction(ecb->ConnID, 
				    HSE_REQ_TRANSMIT_FILE, &tf, 0, 0 ) == TRUE )
					return HSE_STATUS_SUCCESS_AND_KEEP_CONN;

				return HSE_STATUS_ERROR;

			}
		} else {
			/* respond now with the message */
			hseStatus = sendRespMsg(ecb, html, htmlLen,
			    "QUERY_STRING not set!\n");
		}
	} else if (0 == strcmp(ecb->lpszMethod, "POST")) {
		/**********************/
		/***  POST REQUEST  ***/
		/**********************/

		char   cookieStr[COOKIE_BUF_SIZE];
		char     contentBuf[POST_BUF_SIZE];
		char     *bufPtr;
		int      bufLength;
		/* parsing the POST content */
		char    *urlrootptr=NULL, *dirptr=NULL, *classptr=NULL,
		*numptr=NULL, *clientptr=NULL;
		char    *this;
		int     found;
		/* post.log file processing */
		char    countBuf[2*COUNT_LEN+1];
		time_t  timeinsec;
		int     postRemain, readLength;


		strcpy(htmlPtr, QUERYnBODY);
		htmlLen = strlen (html);

		/* Get the cookie string */
		length = COOKIE_BUF_SIZE;
		ecb->GetServerVariable(ecb->ConnID, "ALL_HTTP", cookieStr, &length);

		/* HTTP_COOKIE: my_cookie=user_id=10012&last_ad=120 */
		cookiePtr = NULL;
		if (NULL != (this = strchr(cookieStr, '='))) {
			if (NULL != (this = strchr(++this, '='))) {
				cookiePtr = ++this;
				this = cookiePtr + 5;
				*this = '\0';
				strcpy (cookieIdPtr, cookiePtr);
			}
		}

		/**********************/
		/***  POST REQUEST  ***/
		/**********************/

		/* Get the POST content */
		postRemain = ecb->cbTotalBytes;
		if (postRemain == ecb->cbAvailable) {
			strncpy(contentBuf, (char *)ecb->lpbData, postRemain);
			bufPtr = contentBuf + postRemain;
			/* for debugging purpose */
			syslog (LOG_ERR, "strncpy POST CONTENT\n");
		} else {
			bufPtr = contentBuf;
			while (postRemain > 0 ) {
				readLength = postRemain;
				ecb->ReadClient(ecb->ConnID, bufPtr, &readLength);
				postRemain -= readLength;
				bufPtr += readLength;
			}
		}
		/* contentBuf must be '\0' terminated. */
		*bufPtr ='\0';      /* bufPtr always point to the end */

		urlrootptr=dirptr=classptr=numptr=clientptr=NULL;
		this = contentBuf;

		/* Parse the POST content */
		found = 0;
		while (*this != '\0') {

			/******  parseKeyValue() ********/

			if (strncmp(this, "urlroot=", 8) == 0) {
				urlrootptr = this += 8; 
				found++;
				if (NULL == (this = strchr(this, '&')))
					this = bufPtr;  /* *bufPtr == '\0' */
				else {
					*this = '\0'; 
					this++;
				}
			}
			if (strncmp(this, "dir=", 4) == 0) {
				dirptr = this += 4; 
				found++;
				if (NULL == (this = strchr(this, '&')))
					this = bufPtr;  /* *bufPtr == '\0' */
				else {
					*this = '\0'; 
					this++;
				}
			}
			if (strncmp(this, "class=", 6) == 0) {
				classptr = this += 6; 
				found++;
				if (NULL == (this = strchr(this, '&')))
					this = bufPtr;  /* *bufPtr == '\0' */
				else {
					*this = '\0'; 
					this++;
				}
			}
			if (strncmp(this, "num=", 4) == 0) {
				numptr = this += 4; 
				found++;
				if (NULL == (this = strchr(this, '&')))
					this = bufPtr;  /* *bufPtr == '\0' */
				else {
					*this = '\0'; 
					this++;
				}
			}
			if (strncmp(this, "client=", 7) == 0) {
				clientptr = this += 7; 
				found++;
				if (NULL == (this = strchr(this, '&')))
					this = bufPtr;  /* *bufPtr == '\0' */
				else {
					*this = '\0'; 
					this++;
				}
			}
			if (found == 0)
				this++;
			else
				found = 0;
		}
		sprintf(urlName, "%sdir%5s/class%1s_%1s",
		    urlrootptr,dirptr,classptr,numptr);

		if (!urlrootptr || !dirptr || !classptr || !numptr || !clientptr) {
			sprintf(tmpBuf,
			    "Incorrect POST Input: '%s'\nPOST Content-length: %d\nPOST does"
			    "not contain complete pathname and client information.\n",
			    fullName, bufPtr-contentBuf);

			/* respond now with the message */
			hseStatus = sendRespMsg(ecb, html, htmlLen, tmpBuf);

		} else {
			/* Update the log file */
			timeinsec = time((time_t *) NULL);

			if (-1 == (logfd = open(logFile, O_RDWR))) {
				sprintf(tmpBuf, "Cannot open %s(%s)\n",logFile,strerror(errno));
				hseStatus = sendRespMsg(ecb, html, htmlLen, tmpBuf);
				return hseStatus;
			}

			get_sema();

			/* read, increment and then write the counter from/to log file */
			(void) read (logfd, countBuf, (size_t)COUNT_LEN);
			countBuf[COUNT_LEN] = '\0';
			sprintf (countBuf, "%10d", atoi(countBuf)+1);
			(void) lseek (logfd, 0, SEEK_SET);
			write (logfd, countBuf, (size_t)COUNT_LEN);

			/* append to the log file information on the requested URL */
			(void) lseek (logfd, 0, SEEK_END);
			bufLength = sprintf(tmpBuf,
			    "%s %10d %10d %5s %2s %2s %10s %-60.60s %10d\n",
			    countBuf, timeinsec, mypid,dirptr, classptr, numptr, clientptr,
			    urlName, mypid);
			(void) write (logfd, tmpBuf, bufLength);
			release_sema();
			close(logfd);

			/* return the requested URL */

			tf.pHead = (PVOID)html;
			tf.pTail = (PVOID)SUFFIX;
			tf.TailLength = sizeof(SUFFIX) - 1;
			tf.dwFlags = HSE_IO_SEND_HEADERS|HSE_IO_DISCONNECT_AFTER_SEND| 
			    HSE_IO_HANDLE_IS_FILENAME;
			tf.pHead = (PVOID)html;
			tf.pszStatusCode = (const char *) httpCookie;
			tf.HeadLength = htmlLen;
			tf.hFile    = (HANDLE)fullName;

			if( ecb->ServerSupportFunction(ecb->ConnID,
			    HSE_REQ_TRANSMIT_FILE, &tf, 0, 0 ) == TRUE )
			{
				return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
			}

			return HSE_STATUS_ERROR;
		}
	} /* POST */
	return hseStatus;
}



/*
** Send the HTTP response back to the client.
** 
*/
int sendRespMsg (LPEXTENSION_CONTROL_BLOCK ecb,
char *htmlHeader, int htmlLen, 
char *msg)
{
	int       status;
	int       length;
	int	http_hdr[256];

        /* Set the response header using ISAPI HSE Support function. */
        /*   - The header and its lenght are defined prior to this call. */

        /* Send the HTTP response back using ISAPI WriteClient funciton. */
        /*   - If msg is not NULL, then send this message in addition to the */
        /*     HTML close tag to the client. */

	length = sizeof (HTTP_HEADER) -1;
	strcpy((char *) http_hdr,HTTP_HEADER);

	if (!ecb->ServerSupportFunction(ecb->ConnID,
	    HSE_REQ_SEND_RESPONSE_HEADER, 0, &length, (int*)http_hdr))
		return HSE_STATUS_ERROR;


	length = htmlLen;
	if (!ecb->WriteClient(ecb->ConnID, htmlHeader, &length, 0))
		return HSE_STATUS_ERROR;

	if (msg) {
		/* send both the msg and the HTTP CLOSE to the client using */
		/* WriteClient() support function.  */
		length = snprintf(tmpBuf, (size_t)BUF_SIZE, "%s%s\n", msg, 
		    SUFFIX);
		if (ecb->WriteClient(ecb->ConnID, tmpBuf, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
	} else {
		/* excluding '\0' */
		length = sizeof(SUFFIX) -1;
		if (ecb->WriteClient(ecb->ConnID, SUFFIX, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;
	}
}

int createLogSendResp (LPEXTENSION_CONTROL_BLOCK  ecb,
char *htmlHeader, int htmlLen, 
char *fileName)
{
	FILE     *fptr;
	int    status;


	unlink (fileName);
	fptr = fopen(fileName, "w");
	if (NULL == fptr) {
		sprintf(tmpBuf, "Could not create file - \"%s\" (%s)",fileName,
		    strerror(errno));
		status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
	} else {

		/* Write 0 to the first line */
		if ( fprintf (fptr, "%10d\n", 0) <=0 ) {
			sprintf(tmpBuf, "Could not initialize Log  file - \"%s\" (%s)",
			    fileName, strerror(errno));
			status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
		} else if (EOF == fclose(fptr)) {
			sprintf(tmpBuf, "Could not close file - \"%s\" (%s)", fileName,
			    strerror(errno));
			status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
		} else
			status = sendRespMsg(ecb, htmlHeader, htmlLen, 0);
	}

	return status;
}



int sendRespLogFile   (LPEXTENSION_CONTROL_BLOCK  ecb,
char *htmlHeader, int htmlLen, 
char *fileName)
{
	int      fd;
	char     buffer[READ_BUF_SIZE];
	ssize_t  byteRead;
	ssize_t  tmp;
	int    status;
	int    length;

	if ((fd = open(fileName, O_RDONLY)) < 0) {
		sprintf(tmpBuf, "Could not open file for reading - \"%s\" (%s)",
		    fileName, strerror(errno));
		status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
	} else {

		length = htmlLen;
		if (!ecb->WriteClient(ecb->ConnID, htmlHeader, &length, 0))
			return HSE_STATUS_ERROR;

		do {
			byteRead = read(fd, buffer, (size_t)READ_BUF_SIZE);

			if (byteRead < 0) {
				sprintf(tmpBuf, "Error reading file '%s': error is %s\n", 
				    fileName, strerror(errno));
				status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
				break;
			}

			length = byteRead;
			if (!(ecb->WriteClient(ecb->ConnID, buffer, &length, 0)))
				return HSE_STATUS_ERROR;

		} while (READ_BUF_SIZE == byteRead);

		/* excluding '\0' */
		length = sizeof(SUFFIX) -1;
		if (ecb->WriteClient(ecb->ConnID, SUFFIX, &length, 0))
			return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
		else
			return HSE_STATUS_ERROR;

		if (close(fd) < 0) {
			sprintf(tmpBuf, "Could not close file - \"%s\" (%s)", fileName,
			    strerror(errno));
			status = sendRespMsg(ecb, htmlHeader, htmlLen, tmpBuf);
		}
	}

	return status;
}


/*
 *  sem_init()
 *
 *    create a semaphore for file control - lock POST_LOG
 */

int sem_init ()
{
	if ((sem_id = semget((key_t)8989, 1, 0666 | IPC_CREAT )) == -1) {
		if (errno == EEXIST) {
			syslog (LOG_ERR,
			    "ISAPI Error: semaphore already in use! key=8989\n");
			return (-1);
		}
		else {
			syslog(LOG_ERR,
			    "Error: ISAPI semaphore creation failed ! key=8989, errno=%d\n",errno);
			return (-1);
		}
	}
	else {
		/* initialize a semaphore to the value of 1 */
		if (semctl(sem_id, 0, SETVAL, 1) == -1) {
			syslog(LOG_ERR,"Error: ISAPI semctl(id, 0, SETVAL, 1)failed\n");
			return (-1);
		}
		else
			return (sem_id);
	}
}

/*
* get semaphore
*/

int get_sema()
{
	struct sembuf p_buf;
	int NOT_GET = TRUE;
	int retry_number = 0;
	int semop_ret;

	p_buf.sem_num = 0;
	p_buf.sem_op  = -1;
	p_buf.sem_flg = SEM_UNDO ;

	while (NOT_GET) {
		errno=0;
		semop_ret = semop(sem_id, &p_buf, 1);
		if (semop_ret == -1) {
			if (errno == EAGAIN || errno == ENOSPC || errno == ERANGE || errno == 0 ) {
				syslog(LOG_ERR,
				    "getsema(): semop(sem_id=%d) failed! errno=%d\n",
				    sem_id, errno);
			}
			else {
				if (errno == EINTR) {
					syslog(LOG_ERR,"get_sema(): get sema gets EINTR\n");
					return (-1);
				}
				else {
					syslog(LOG_ERR,
					    "Error: getsema(): semop(sem_id=%d) failed! errno=%d\n",
					    sem_id, errno);
					return (-1);
				}
			}
		}
		else {
			return (semop_ret);
		}
	}
}




/*
 *   release_sema()
 *
 */
int release_sema()
{
	struct sembuf p_buf;
	int NOT_RELEASE = TRUE;
	int retry_number = 0;
	int semop_ret;

	p_buf.sem_num = 0;
	p_buf.sem_op  = 1;
	p_buf.sem_flg = SEM_UNDO;

	while (NOT_RELEASE) {
		if ((semop_ret = semop(sem_id, &p_buf, 1)) == -1)
		{
			if (errno == EAGAIN || errno == ENOSPC || errno == ERANGE) {

				syslog(LOG_ERR,
				    "Warning:  release_sema(%d): semop retry time out ! \n",
				    sem_id);
				return (-1);
			}
			else {
				if (errno == EINTR) {
					syslog(LOG_ERR,"Release_sema(): release sema gets EINTR\n");
					return (-1);
				}
				else {
					syslog(LOG_ERR,
					    "Error: release_sema(): semop(sem_id=%d) failed !\n",
					    sem_id, errno);
					return (-1);
				}
			}
		}
		else {
			return (semop_ret);
		}
	}
}

/*
*  remove_sema
*/

void
remove_sema()
{

	if (semctl(sem_id, 0, IPC_RMID, 0) == -1)
		syslog(LOG_ERR,
		    "Error: ISAPI semctl(id, 0, IPC_RMID, 1)failed, errno=%d\n",errno);
}
@EOF
set `sum $sumopt <spec99gp.c`; if test $1 -ne 12257
then
	echo ERROR: spec99gp.c checksum is $1 should be 12257
EXIT_STATUS=1
fi
set `wc -lwc <spec99gp.c`
if test $1$2$3 != 782235419541
then
	echo ERROR: wc results of spec99gp.c are $* should be 782 2354 19541
EXIT_STATUS=1
fi

chmod 666 spec99gp.c


if [ $EXIT_STATUS -eq 1 ];then
	exit 1
fi
exit 0
