Improved Server Push in C

What follows is the complete source code for the improved version of doit.c, entitled animate.c. At the bottom you will also find the Makefile which will allow you to install the program on your machine.

Here is a list of improvements found in the animate.c program which were not included in the original doit.c source code.

C Source Code



/*
******************************************************************
* animate.c: A derived work from Rob McCool's doit.c             *
* Code changes made by Andrew Cowan [GlobalMedia Design Inc.].   *
*                                                                *
* Description: Performs browser detection on the remote end and  *
* sends off a single image if non-netscape (or netscape version  *
* earlier than 1.0), or the animation otherwise.                 *
*                                                                *
* This code is released into the public domain.  Do whatever     *
* you want with it.                                              *
******************************************************************
*/

#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdio.h>

/* 
***************************************************************
*                    Configuration Section                    * 
* The next 6 lines require your attention in order for this   *
* program to work. Here is a run down on what is needed for   *
* the configuration:                                          *
*                                                             *
* Your image files must be setup as a standard filename       *
* indexed by a letter character. For instance the following   *
* would work: imagea.gif, imageb.gif, imagec.gif, imaged.gif  *
* Or you could have something like: image_a.jpg, image_b.jpg, *
* image_c.jpg, and image_d.jpg.                               *
*                                                             *
* LASTCHAR  - The last character index of your image files.   *
*             For the above examples you would use 'd'.       *
* DIR       - The full directory name where your images live. *
* LASTIMAGE - The last image in the animation sequence. For   *
*             the above examples it would be either imaged.gif*
*             or image_d.jpg. This definition is used for     *
*             non-Netscape browsers.                          *
* GIF/JPEG  - This defines the type of image file you want to *
*             display. If your images are gif-type then leave *
*             Those lines as is, otherwise for jpgs you will  *
*             need to comment out the GIF definition and      *
*             uncomment the JPEG definition.                  *
* CYCLE     - Uncomment this line if you want your images to  *
*             cycle continuously. The default is for one loop *
*             and it is not recommended that you change this  *
*             but you may if desired.                         * 
*                                                             *
* There is one more thing needed before you can compile and   *
* run the animate program. There are two sprintf() lines      *
* below, the second one (line 132) will require editing to    *
* suit your image files. It should look like this now:        *
* sprintf(fn, "%s/cells_%c.gif", DIR, (char) x);              *
* You must rename cells_%c.gif to whatever filename structure *
* you are using. For instance if the image files are named:   *
* image_a.gif, image_b.gif, ..., image_e.gif then your line   *
* should be modified to look like this:                       *
* sprintf(fn, "%s/image_%c.gif", DIR, (char) x);              *
*                                                             *
* Thats all there is to it! When you compile the program you  *
* should get a warning message about making a pointer from an *
* integer without a cast, don't worry about it, its doing     *
* what it should! If you run into any problems feel free to   *
* send me email at cowana@magicnet.net.      Good Luck!       *
***************************************************************
*/

#define LASTCHAR 'e'
#define DIR "/usr/users/cowana/tutorials"
#define LASTIMAGE "cells_e.gif"
#define GIF 1 
/* #define JPEG	1 */
/* #define CYCLE 1 */

/*
***************************************************************
*                 End of Configuration Section                *
***************************************************************
*/

#define HEADER \
"Content-type: multipart/x-mixed-replace;boundary=ThisRandomString\n" 
#define RANDOMSTRING "\n--ThisRandomString\n"
#define ENDSTRING "\n--ThisRandomString--\n"

#if defined(GIF)
   #define CTSTRING "Content-type: image/gif\n\n"
   #define SHEADER "Content-type: image/gif\n\n"
#else
   #define CTSTRING "Content-type: image/jpeg\n\n"
   #define SHEADER "Content-type: image/jpeg\n\n"
#endif

int main(int argc, char *argv[])
{
    struct stat fi;
    char fn[32];
    caddr_t fp[20];
    unsigned char x;
    int fd[20];
    int index;
    char *agent;

    agent = getenv("HTTP_USER_AGENT");

    if ((!(strstr(agent, "Mozilla/1.")) && !(strstr(agent, "Mozilla/2."))) || 
       (strstr(agent, "Mozilla/1.0"))){
       if(write(STDOUT_FILENO, SHEADER, strlen(SHEADER)) == -1)
        exit(0);      
       sprintf(fn, "%s/%s", DIR, LASTIMAGE); 
       if( (fd[1] = open(fn, O_RDONLY)) == -1)
           exit(0);  
       fstat(fd[1], &fi);
       fp[1] = mmap(NULL, fi.st_size, PROT_READ, MAP_PRIVATE, fd[1], 0);
       if(fp[1] == (caddr_t) -1) exit(0);
       write(STDOUT_FILENO, (void *) fp[1], fi.st_size);
       munmap(fp[1], fi.st_size);  
       exit(0);
    } 

    if(write(STDOUT_FILENO, HEADER, strlen(HEADER)) == -1)
        exit(0);
    if(write(STDOUT_FILENO, RANDOMSTRING, strlen(RANDOMSTRING)) == -1)
        exit(0);

    x = 'a';
    index = 1;

    while(1) {
      sprintf(fn, "%s/cells_%c.gif", DIR, (char) x); 
      if( (fd[index] = open(fn, O_RDONLY)) == -1)
          exit(1);
      if (x == LASTCHAR) goto display;
      x++;
      index++;
    }

display:

    x = 'a';
    index = 1;
 
    while(1) {
       fstat(fd[index], &fi);
       fp[index] = mmap(NULL, fi.st_size, PROT_READ, MAP_PRIVATE, fd[index], 0);
       if(fp[index] == (caddr_t) -1) exit(0); 
       write(STDOUT_FILENO, CTSTRING, strlen(CTSTRING));
       write(STDOUT_FILENO, (void *) fp[index], fi.st_size); 
       munmap(fp[index], fi.st_size);
       write(STDOUT_FILENO, RANDOMSTRING, strlen(RANDOMSTRING));
       if (x == LASTCHAR){
          #if defined(CYCLE)
             sleep(1);
             goto display;
          #else
             goto endit;
          #endif 
       }
       x++;
       index++;
    }

endit:
    exit (0);
}

The Makefile

#
# @(#)Makefile  1.2 8/21/94
#
# Makefile for "animate.c"
#
# Original code created by Rob McCool (doit.c). Modifications
# made by Andrew Cowan. This program is public domain.
#
# Modify the CGI_BIN definition to represent your directory
# Modify the CC definition to cc if gcc is unavailable to you.
# Type: make install to install the animate program in the
# defined directory.
#

CGI_BIN = /usr/local/etc/httpd/cgi-bin
CC = gcc

DESTDIR = $(CGI_BIN)

animate: animate.c
        $(CC) $(OPTS) -DCGI_BIN='"$(CGI_BIN)"' -o $@ animate.c

install: animate 
	cp animate $(DESTDIR)
	chmod 755 $(DESTDIR)/animate

# End of Makefile

Back to the Tutorial on Server Push Animation


The Radiation Zone is copyright © 1995 by its creators. All rights are reserved.