/*
    Program:		number
    Filename:		number.c
    Programmer:		Ben Y. Yoshino
    Description:	A rudimentary counter, to be used with Server-side
			Includes on an NCSA httpd or other server.
    Dependencies:	Requires the C string libraries and Unix file i/o.
    Copyright info:	Permission to use, copy, modify and distribute this
			software and its documentation for any purpose and
			without fee is hereby granted, provided that the
			above copyright notice and this permission notice
			appear in supporting documentation. This software is
			provided "as is" without expressed or implied
			warranty. Ben Y. Yoshino will not be held liable for
			any damages whatsoever resulting from the use of this
			software.
    
    Copyright 1995, Ben Y. Yoshino.
    All rights reserved.
*/

#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define COUNTDIR	"/usr/tmp/counts"
/* This directory MUST exist */

#define writebuf(x,y)	(void) write((x), (void *) (y), (size_t) strlen((y)))

void incstr(char *string);
void revstr(char *string);

int main(int argc, char *argv[])
{
    int fd, len;
    char content[1024], docname[1024], filename[1024],
	 output[1024], *ptr1;

    (void) strcpy(docname, getenv("DOCUMENT_URI"));
    if (! *docname)
	(void) strcpy(docname, "test");
    else if (ptr1 = strrchr(docname, '/')) {
	*(ptr1 ++) = '\0';
	(void) strcpy(content, docname);
	(void) strcpy(docname, ptr1);
    }
    if (! strlen(docname)) {
	if (ptr1 = strrchr(docname, '/')) {
	    *(ptr1 ++) = '\0';
	}
	(void) strcpy(docname, ptr1);
    }
    if (! strlen(docname))
	(void) strcpy(docname, "index");
    if (ptr1 = strrchr(docname, '.'))
	*ptr1 = '\0';
    (void) sprintf(filename, "%s/%s", COUNTDIR, docname);
    if ((fd = open(filename, O_RDWR | O_CREAT, 0644)) == -1)  {
	(void) sprintf(output, "%s: could not open lock file %s\r\n", argv[0],
		       filename);
	writebuf(2, output);
	return -1;
    }
    (void) lockf(fd, F_LOCK, 0);
    if ((len = read(fd, (void *) content, 1024)) <= 1)
	content[0] = '0', content[1] = '\0';
    if (ptr1 = strchr(content, '\n'))
	*ptr1 = '\0';
    revstr(content);
    incstr(content);
    revstr(content);
    (void) lseek(fd, 0, SEEK_SET);
    writebuf(1, "Content-type: text/html\r\n\r\n");
    (void) strcpy(output, content);
    (void) strcat(output, "\r\n");
    (void) strcat(content, "\n");
    writebuf(1, output);
    writebuf(fd, content);
    ftruncate(fd, (size_t) strlen(content));
    close(fd);
    return 0;
}

void incstr(char *string)
{
    register int next;
    register char *ptr;

    for (ptr = string; *ptr; ptr ++)
	if ((*ptr) ++ >= '9') {
	    *ptr = '0', next = 1;
	    continue;
	} else {
	    next = 0;
	    break;
	}
    if (next) {
	*(ptr ++) = '1';
	*ptr = '\0';
    }
    return;
}

void revstr(char *string)
{
    register int slen;
    register char *front, *back;

    slen = strlen(string) - 1;
    if (! slen) return;
    for (front = string, back = string + slen; front <= back;
	 front ++, back --)
	 if (*front != *back)
	    *front ^= *back, *back ^= *front, *front ^= *back;
    return;
}
