185686eee12878de494bd96ab0e3e8be4c8d03ed hiram Fri Mar 15 17:16:37 2019 -0700 adding user documentation refs #18869 diff --git src/hg/hubApi/hubApi.c src/hg/hubApi/hubApi.c index 4cbfffb..09e9dac 100644 --- src/hg/hubApi/hubApi.c +++ src/hg/hubApi/hubApi.c @@ -4,31 +4,31 @@ /* +------------------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +------------------+------------------+------+-----+---------+-------+ | hubUrl | longblob | NO | PRI | NULL | | | shortLabel | varchar(255) | NO | | NULL | | | longLabel | varchar(255) | NO | | NULL | | | registrationTime | varchar(255) | NO | | NULL | | | dbCount | int(10) unsigned | NO | | NULL | | | dbList | blob | YES | | NULL | | | descriptionUrl | longblob | YES | | NULL | | +------------------+------------------+------+-----+---------+-------+ */ /* Global Variables */ -static boolean debug = TRUE; +static boolean debug = FALSE; static struct cart *cart; /* CGI and other variables */ static struct hash *oldVars = NULL; static struct hash *trackCounter = NULL; static long totalTracks = 0; static boolean measureTiming = FALSE; /* set by CGI parameters */ static boolean allTrackSettings = FALSE; /* checkbox setting */ static char **shortLabels = NULL; /* public hub short labels in array */ // struct hubPublic *publicHubList = NULL; static int publicHubCount = 0; static char *defaultHub = "Plants"; static char *defaultDb = "ce11"; static long enteredMainTime = 0; /* will become = clock1000() on entry */ /* to allow calculation of when to bail out, taking too long */ static long timeOutSeconds = 100; static boolean timedOut = FALSE; @@ -597,68 +597,113 @@ if (countTracks->elCount) { hPrintf(" <ol>\n"); struct hashEl *hel, *helList = hashElListHash(countTracks); slSort(&helList, hashElCmpIntValDesc); for (hel = helList; hel; hel = hel->next) { hPrintf(" <li>%d - %s</li>\n", ptToInt(hel->val), hel->name); } hPrintf(" </ol>\n"); } hPrintf("</ul>\n"); hPrintf("</p>\n"); } // static void tracksForUcscDb(char * db) +static void introductionText() +/* output explanation text */ +{ +char *scriptUri = getenv("SCRIPT_URI"); + +hPrintf("<h1>JSON data API interface to U.C. Santa Cruz genome browser data</h1>\n"); +hPrintf("<h2>Data access URL: <em>%s</em></h2>\n", scriptUri); +hPrintf("<h3>Endpoint functions:</h3>\n"); +hPrintf("<ul>\n"); +hPrintf("<li>/list/...</li>\n"); +hPrintf("<li><ol>\n"); +hPrintf("<li>/list/publicHubs - list public hubs</li>\n"); +hPrintf("<li>/list/ucscGenomes - list UCSC database genomes</li>\n"); +hPrintf("<li>/list/hubGenomes - list genomes from specified hub</li>\n"); +hPrintf("<li>/list/tracks - list data tracks available in specified hub or database genome</li>\n"); +hPrintf("<li>/list/chromosomes - list chromosomes from specified data track in specified hub or database genome</li>\n"); +hPrintf("</ol></li>\n"); +hPrintf("<li>/getData/...</li>\n"); +hPrintf("<li><ol>\n"); +hPrintf("<li>/getData/sequence - return sequence from specified hub or database genome</li>\n"); +hPrintf("<li>/getData/track - return data from specified track in hub or database genome</li>\n"); +hPrintf("</ol></li>\n"); +hPrintf("</ul>\n"); +hPrintf("<h3>Parameters to endpoint functions:</h3>\n"); +hPrintf("<ul>\n"); +hPrintf("<li>hubUrl=<url> - specify track hub or assembly hub URL</li>\n"); +hPrintf("<li>genome=<name> - specify genome assemby in track or assembly hub</li>\n"); +hPrintf("<li>db=<ucscDb> - specify database (aka genome assembly) in UCSC genome browser</li>\n"); +hPrintf("<li>track=<trackName> - specify data track in hub or UCSC database genome assembly</li>\n"); +hPrintf("<li>chrom=<chrN> - specify chromosome name for sequence or track data</li>\n"); +hPrintf("<li>start=<123> - specify start coordinate (0 relative) for data from track or sequence retrieval</li>\n"); +hPrintf("<li>end=<456> - specify end coordinate (1 relative) for data from track or sequence retrieval</li>\n"); +hPrintf("<li>(see also: <a href='http://genome.ucsc.edu/blog/the-ucsc-genome-browser-coordinate-counting-systems/' target=_blank>UCSC browser coordinate counting systems)</a></li>"); +hPrintf("</ul>\n"); +} + static void showExamples(char *url, struct trackHubGenome *hubGenome, char *ucscDb) { +char *urlPrefix = ""; +char *httpHost = getenv("HTTP_HOST"); + +if (! startsWith("hgwdev-api", httpHost)) { + if (startsWith("hgwdev",httpHost) || startsWith("genome-test", httpHost)) + { + urlPrefix = "../cgi-bin/hubApi"; + } +} hPrintf("<h2>Example URLs to return json data structures:</h2>\n"); hPrintf("<h3>listing functions</h3>\n"); hPrintf("<ol>\n"); -hPrintf("<li><a href='/list/publicHubs' target=_blank>list public hubs</a> <em>/list/publicHubs</em></li>\n"); -hPrintf("<li><a href='/list/ucscGenomes' target=_blank>list database genomes</a> <em>/list/ucscGenomes</em></li>\n"); -hPrintf("<li><a href='/list/hubGenomes?hubUrl=%s' target=_blank>list genomes from specified hub</a> <em>/list/hubGenomes?hubUrl=%s</em></li>\n", url, url); -hPrintf("<li><a href='/list/tracks?hubUrl=%s&hubUrl=%s&genome=%s' target=_blank>list tracks from specified hub and genome</a> <em>/list/tracks?hubUrl=%s&genome=%s</em></li>\n", url, url, hubGenome->name, url, hubGenome->name); -hPrintf("<li><a href='/list/tracks?db=%s' target=_blank>list tracks from specified UCSC database</a> <em>/list/tracks?db=%s</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/list/chromosomes?db=%s' target=_blank>list chromosomes from specified UCSC database</a> <em>/list/chromosomes?db=%s</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/list/chromosomes?db=%s&track=gap' target=_blank>list chromosomes from specified track from UCSC databaset</a> <em>/list/chromosomes?db=%s&track=gap</em></li>\n", ucscDb, ucscDb); +hPrintf("<li><a href='%s/list/publicHubs' target=_blank>list public hubs</a> <em>%s/list/publicHubs</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/list/ucscGenomes' target=_blank>list database genomes</a> <em>%s/list/ucscGenomes</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/list/hubGenomes?hubUrl=%s' target=_blank>list genomes from specified hub</a> <em>%s/list/hubGenomes?hubUrl=%s</em></li>\n", urlPrefix, url, urlPrefix, url); +hPrintf("<li><a href='%s/list/tracks?hubUrl=%s&genome=%s' target=_blank>list tracks from specified hub and genome</a> <em>%s/list/tracks?hubUrl=%s&genome=%s</em></li>\n", urlPrefix, url, hubGenome->name, urlPrefix, url, hubGenome->name); +hPrintf("<li><a href='%s/list/tracks?db=%s' target=_blank>list tracks from specified UCSC database</a> <em>%s/list/tracks?db=%s</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/list/chromosomes?db=%s' target=_blank>list chromosomes from specified UCSC database</a> <em>%s/list/chromosomes?db=%s</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/list/chromosomes?db=%s&track=gap' target=_blank>list chromosomes from specified track from UCSC databaset</a> <em>%s/list/chromosomes?db=%s&track=gap</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); hPrintf("</ol>\n"); hPrintf("<h3>getData functions</h3>\n"); hPrintf("<ol>\n"); -hPrintf("<li><a href='/getData/sequence?db=%s&chrom=chrM' target=_blank>get sequence from specified database and chromosome</a> <em>/getData/sequence?db=%s&chrom=chrM</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/getData/sequence?db=%s&chrom=chrM&start=0&end=128' target=_blank>get sequence from specified database, chromosome with start,end coordinates</a> <em>/getData/sequence?db=%s&chrom=chrM&start=0&end=128</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/getData/track?db=%s&track=gold' target=_blank>get entire track data from specified database and track name (gold == Assembly)</a> <em>/getData/track?db=%s&track=gold</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chrM&track=gold' target=_blank>get track data from specified database, chromosome and track name (gold == Assembly)</a> <em>/getData/track?db=%s&chrom=chrM&track=gold</em></li>\n", ucscDb, ucscDb); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chrI&track=gold&start=107680&end=186148' target=_blank>get track data from specified database, chromosome, track name, start and end coordinates</a> <em>/getData/track?db=%s&chrom=chrI&track=gold&start=107680&end=186148</em></li>\n", defaultDb, defaultDb); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/GillBejerano/hub.txt&genome=hg19&track=ultraConserved' target=_blank>get entire track data from specified hub and track name</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/GillBejerano/hub.txt&genome=hg19&track=ultraConserved</em></li>\n"); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrCp&track=assembly_' target=_blank>get track data from specified hub, chromosome and track name (full chromosome)</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrCp&track=assembly_</em></li>\n"); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chr1&track=assembly_&start=0&end=14309681' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chr1&track=assembly_&start=0&end=14309681</em></li>\n"); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&track=gc5Base_' target=_blank>get all track data from specified hub and track name</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&track=gc5Base</em></li>\n"); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrMt&track=gc5Base_&start=143600&end=143685' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrMt&track=gc5Base&start=143600&end=143685</em></li>\n"); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chrI&track=gc5BaseBw&start=107680&end=186148' target=_blank>get bigWig track data from specified database, chromosome, track name, start and end coordinates</a> <em>/getData/track?db=%s&chrom=chrI&track=gc5BaseBw&start=107680&end=186148</em></li>\n", defaultDb, defaultDb); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chrII&track=ncbiRefSeqOther&start=14334626&end=14979625' target=_blank>get bigBed track data from specified database, chromosome, track name, start and end coordinates</a> <em>/getData/track?db=%s&chrom=chrII&track=ncbiRefSeqOther&start=14334626&end=14979625</em></li>\n", defaultDb, defaultDb); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chr1&track=wgEncodeAwgDnaseDuke8988tUniPk&start=14334626&end=14979625' target=_blank>get narrowPeak track data from specified database, chromosome, track name, start and end coordinates</a> <em>/getData/track?db=%s&chrom=chr1&track=wgEncodeAwgDnaseDuke8988tUniPk&start=14334626&end=14979625</em></li>\n", "hg19", "hg19"); -hPrintf("<li><a href='/getData/track?db=%s&chrom=chr1&track=wgEncodeBroadHistoneOsteoP300kat3bPk&start=14334626&end=14979625' target=_blank>get broadPeak track data from specified database, chromosome, track name, start and end coordinates</a> <em>/getData/track?db=%s&chrom=chr1&track=wgEncodeBroadHistoneOsteoP300kat3bPk&start=14334626&end=14979625</em></li>\n", "hg19", "hg19"); +hPrintf("<li><a href='%s/getData/sequence?db=%s&chrom=chrM' target=_blank>get sequence from specified database and chromosome</a> <em>%s/getData/sequence?db=%s&chrom=chrM</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/getData/sequence?db=%s&chrom=chrM&start=0&end=128' target=_blank>get sequence from specified database, chromosome with start,end coordinates</a> <em>%s/getData/sequence?db=%s&chrom=chrM&start=0&end=128</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/getData/track?db=%s&track=gold' target=_blank>get entire track data from specified database and track name (gold == Assembly)</a> <em>%s/getData/track?db=%s&track=gold</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chrM&track=gold' target=_blank>get track data from specified database, chromosome and track name (gold == Assembly)</a> <em>%s/getData/track?db=%s&chrom=chrM&track=gold</em></li>\n", urlPrefix, ucscDb, urlPrefix, ucscDb); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chrI&track=gold&start=107680&end=186148' target=_blank>get track data from specified database, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?db=%s&chrom=chrI&track=gold&start=107680&end=186148</em></li>\n", urlPrefix, defaultDb, urlPrefix, defaultDb); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/GillBejerano/hub.txt&genome=hg19&track=ultraConserved' target=_blank>get entire track data from specified hub and track name</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/GillBejerano/hub.txt&genome=hg19&track=ultraConserved</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrCp&track=assembly_' target=_blank>get track data from specified hub, chromosome and track name (full chromosome)</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrCp&track=assembly_</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chr1&track=assembly_&start=0&end=14309681' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chr1&track=assembly_&start=0&end=14309681</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&track=gc5Base_' target=_blank>get all track data from specified hub and track name</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&track=gc5Base</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrMt&track=gc5Base_&start=143600&end=143685' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrMt&track=gc5Base&start=143600&end=143685</em></li>\n", urlPrefix, urlPrefix); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chrI&track=gc5BaseBw&start=107680&end=186148' target=_blank>get bigWig track data from specified database, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?db=%s&chrom=chrI&track=gc5BaseBw&start=107680&end=186148</em></li>\n", urlPrefix, defaultDb, urlPrefix, defaultDb); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chrII&track=ncbiRefSeqOther&start=14334626&end=14979625' target=_blank>get bigBed track data from specified database, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?db=%s&chrom=chrII&track=ncbiRefSeqOther&start=14334626&end=14979625</em></li>\n", urlPrefix, defaultDb, urlPrefix, defaultDb); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chr1&track=wgEncodeAwgDnaseDuke8988tUniPk&start=14334626&end=14979625' target=_blank>get narrowPeak track data from specified database, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?db=%s&chrom=chr1&track=wgEncodeAwgDnaseDuke8988tUniPk&start=14334626&end=14979625</em></li>\n", urlPrefix, "hg19", urlPrefix, "hg19"); +hPrintf("<li><a href='%s/getData/track?db=%s&chrom=chr1&track=wgEncodeBroadHistoneOsteoP300kat3bPk&start=14334626&end=14979625' target=_blank>get broadPeak track data from specified database, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?db=%s&chrom=chr1&track=wgEncodeBroadHistoneOsteoP300kat3bPk&start=14334626&end=14979625</em></li>\n", urlPrefix, "hg19", urlPrefix, "hg19"); hPrintf("</ol>\n"); hPrintf("<h2>Example URLs to generate errors:</h2>\n"); hPrintf("<ol>\n"); -hPrintf("<li><a href='/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrI&track=assembly_&start=0&end=14309681' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrI&track=assembly_&start=0&end=14309681</em></li>\n"); +hPrintf("<li><a href='%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrI&track=assembly_&start=0&end=14309681' target=_blank>get track data from specified hub, chromosome, track name, start and end coordinates</a> <em>%s/getData/track?hubUrl=http://genome-test.gi.ucsc.edu/~hiram/hubs/Plants/hub.txt&genome=_araTha1&chrom=chrI&track=assembly_&start=0&end=14309681</em></li>\n", urlPrefix, urlPrefix); hPrintf("</ol>\n"); } /* static void showExamples() */ static void showCartDump() /* for information purposes only during development, will become obsolete */ { hPrintf("<h4>cart dump</h4>"); hPrintf("<pre>\n"); cartDump(cart); hPrintf("</pre>\n"); } static void doMiddle(struct cart *theCart) /* Set up globals and make web page */ { @@ -741,42 +786,47 @@ char *ucscDb = cartUsualString(cart, "ucscGenomes", defaultDb); char *urlInput = urlDropDown; /* assume public hub */ if (sameWord("go", goOtherHub)) /* requested other hub URL */ urlInput = otherHubUrl; if (commandError) { hPrintf("<h3>ERROR: no such command: '%s/%s' for endpoint '%s'</h3>", words[0], words[1], pathInfo); } long lastTime = clock1000(); struct trackHub *hub = errCatchTrackHubOpen(urlInput); if (measureTiming) { long thisTime = clock1000(); + if (debug) hPrintf("<em>hub open time: %ld millis</em><br>\n", thisTime - lastTime); } // hPrintf("<h3>ucscDb: '%s'</h2>\n", ucscDb); struct trackHubGenome *hubGenome = hub->genomeList; +introductionText(); + showExamples(urlInput, hubGenome, ucscDb); if (debug) showCartDump(); +hPrintf("<h2>Explore hub or database assemblies and tracks</h2>\n"); + hPrintf("<form action='%s' name='hubApiUrl' id='hubApiUrl' method='GET'>\n\n", "../cgi-bin/hubApi"); hPrintf("<b>Select public hub: </b>"); #define JBUFSIZE 2048 #define SMALLBUF 256 char javascript[JBUFSIZE]; struct slPair *events = NULL; safef(javascript, sizeof(javascript), "this.lastIndex=this.selectedIndex;"); slPairAdd(&events, "focus", cloneString(javascript)); cgiMakeDropListClassWithIdStyleAndJavascript("publicHubs", "publicHubs", shortLabels, publicHubCount, hubDropDown, NULL, "width: 400px", events); hWrites(" "); hButton("goPublicHub", "go"); @@ -800,42 +850,44 @@ hCheckBox("depthSearch", cartUsualBoolean(cart, "depthSearch", FALSE)); hPrintf(" perform full bbi file measurement : %s (will time out if taking longer than %ld seconds)<br>\n", depthSearch ? "TRUE" : "FALSE", timeOutSeconds); hPrintf("\n "); allTrackSettings = cartUsualBoolean(cart, "allTrackSettings", FALSE); hCheckBox("allTrackSettings", allTrackSettings); hPrintf(" display all track settings for each track : %s<br>\n", allTrackSettings ? "TRUE" : "FALSE"); hPrintf("<br>\n</form>\n"); if (sameWord("go", goUcscDb)) /* requested UCSC db track list */ { tracksForUcscDb(ucscDb); } else { + if (debug) + { hPrintf("<p>URL: %s - %s<br>\n", urlInput, sameWord("go",goPublicHub) ? "public hub" : "other hub"); hPrintf("name: %s<br>\n", hub->shortLabel); hPrintf("description: %s<br>\n", hub->longLabel); hPrintf("default db: '%s'<br>\n", isEmpty(hub->defaultDb) ? "(none available)" : hub->defaultDb); printf("docRoot:'%s'<br>\n", docRoot); + } if (hub->genomeList) (void) genomeList(hub, NULL, NULL); /* ignore returned list */ hPrintf("</p>\n"); } - if (timedOut) hPrintf("<h1>Reached time out %ld seconds</h1>", timeOutSeconds); if (measureTiming) hPrintf("<em>Overall total time: %ld millis</em><br>\n", clock1000() - enteredMainTime); cartWebEnd(); } /* void doMiddle(struct cart *theCart) */ /* Null terminated list of CGI Variables we don't want to save * permanently. */ static char *excludeVars[] = {"Submit", "submit", NULL,}; int main(int argc, char *argv[]) /* Process command line. */ {