The Unofficial Web Page


This site should appear as the creator intended if viewed in Explorer 3.0 or higher.  Netscape should be OK too.  Users of other browsers are up a creek and must paddle as best they can.


Back in the 1950s, when white teenagers were just beginning to discover that Pat Boone's version of "Ain't That A Shame" was not the original, a radio station in Nashville, Tennessee, was beaming rhythm and blues and gospel music to millions of young listeners, each discretely tuning his dial to 1510 on the AM dial late into the evening hours.

It was 10:00 pm in the East, bed time for many a schoolboy. But, if the weather was cooperative and the tuner sensitive enough, wonderful sounds soon began to issue forth.  Not Perry Como, not the Chordettes, certainly not Pat Boone.  No, here streaming directly into our bedrooms were the strange, new, and wonderful tones of Chuck Berry, Jimmy Reed, Lowell Fulson, Lightning Hopkins, Muddy Waters, Little Junior Parker, The Spaniels, Sonny Boy Williamson, Howling Wolf, and Etta James.

Here was something special, something to be shared only with your very best friends, not with those jerks at school who didn't know about it and couldn't understand it if they did.  Here was something that made you wish you could soundproof the door to your room or, perhaps, buy a pair of headphones, all to insure that listening bliss might continue into the wee hours when your mother assumed that you had long been asleep.

Nothing characterized the WLAC listening experience more than the nightly program sponsored by "The World's Largest Mail Order Phonograph Record Shop" -- Randy's Record Shop in Gallatin, Tennessee.  They must have done a heck of a business.  No street address, no post office box ... just "Gallatin, Tennessee."

During the mid-'50s, Randy's sponsored what may have been the most listened to disc jockey show in the country.  Introduced by the nostalgic tones of "Swannee River Boogie" by Albert Ammons, "Randy's Record Hi-Lights" was broadcast on clear-channel WLAC at 10:15 pm Central Time, six nights a week--and at 11:00 pm on Sunday.  And 50,000 watts of power insured that it could be heard all over the East, South, and Mid-West, probably in Canada and Mexico as well.

Your genial master of ceremonies was Gene Nobles, seen here holding a soon to be displaced 78 rpm disc.  He was ably assisted by engineer George Karsch in the control booth, whom Nobles referred to as "Cohort."  Listeners sometimes called him the "ape man," as he occasionally punctuated records and commentary with Johnny Weissmuller's Tarzan ape call, as found on the Dale Hawkins recording of "See You Soon Baboon."  I listened to Gene and his show as often as possible.  For whatever reason, he was my favorite and I always had the impression that he was the star of the WLAC lineup.

I'll never forget, however, the night when my hero's feet of clay were exposed.  Nobles' exuberant comments notwithstanding, he didn't always pay attention to the records being played.  Evidently, he and the ape man worked from a list prepared in advance of the show.  But this night they got out of synch somehow.  So just as a record by Chuck Berry had finished playing, poor Gene could be heard saying: "How about that great number by Nervous Norvus, one of my favorites."  I've since learned that this slip may have been attributable to the fact that Nobles was known to have consumed a bottle of Seagrams V.O. in the studio each night.

Gene Nobles has as much claim as anyone to being the first to play rhythm and blues records for a racially mixed audience and developing a distinctive deejay "patter."  Gene called it "Slanguage" and it included such phrases as "from the heart of my bottom."  Mr. Nobles passed away in 1989.

"Randy" was Randy Wood, a successful entrepreneur whose catalog boasted that his shop was "The Home of the World's Largest Stock of Recorded Music."  Randy was patriotic too, offering a "10% discount to all men and women now serving in the Armed Forces."  Lest we forget, these records were "also available in 45 r.p.m."

Randy Wood was also President of "Dot" Records.  Ironically, it was in this capacity, in 1955, that he met with Hugh Cherry of WMAK (Nashville) and was introduced to an aspiring 20-year old singer named Charles Eugene Boone.  Wood was impressed and signed the young man to a contract.  In November of that same year "Pat" Boone had his first hit on Dot: "Ain't That A Shame."

In addition to Boone, Wood's label featured other white artists such as Sanford Clark and, yes, Nervous Norvus.

Giving Randy's show a run for its money was the program sponsored by the venerable Ernie's Record Mart, at 179 3rd Avenue North, Nashville, Tennessee.  "Ernie's Record Parade" could also be heard every night.  It was a one-hour show broadcast Monday through Friday at 9:00 pm Central Time and on Saturday from 8:00 until 9:45 pm.  On Sunday night the "all spiritual" show began at 8:30.

The host on Ernie's show was the steadfast "John R."  His full name was John Richbourg and he began working at WLAC in 1942.  His distinct, deep, and sometimes gravelly voice, together with his "hep-cat" patter combined to confuse many listeners into believing that he was a black man.  Actually, he was a white man who had come to WLAC following stints at other stations and a youthful attempt to pursue a career on the musical stage.  John R. signed off for the last time on June 28, 1973.  As late as the 1980s, Mr. Richbourg was answering letters from his fans, sending out autographed photos, and selling tapes of his programs.

John Richbourg died February 15, 1986 at age 75.  At his funeral, gospel singer Ella Washington sang "Amazing Grace" and "Because He Lives."  One of his old friends, Motown songwriter Jackie Beavers, performed a song John R. had requested, "Eye on the Sparrow."  More details on the life of John R. may be found in an article by Dale R. Patterson at the excellent Rock Radio Retrospective web site.

"Ernie" was Ernie Young, details about whom are found in an article about the Radio Four gospel group written in 1995 by Opal Nations.  Here is the pertinent portion:

Between 1952 and 1955, The Radio Four were captained by the Reverend Dr. Morgan Babb. ... [who] was also taken on as gospel A&R man by Ernie L. Young, founder and president of Nashboro Records out of Nashville in 1951, a post he held for nine years.  The kindly, resourceful Young became a part of the Nashville music scene at an early age and was soon supplying records for the juke boxes he operated around the city.  When records were taken off the juke boxes, they were sold at his record store, Ernie's Record Mart at 177 Third Avenue.

Young found that his customers, for the most part African American, were devoted collectors of gospel music, and that the local market for gospel was such that supply undercut demand.  To counteract the situation, Young, out of his store location, founded Nashboro Records and Record Distributing in 1951.  The Excello label, a secular sister of Nashboro, was set up shortly thereafter to handle the demands of a burgeoning rhythm and blues market.  Young, without prior training, undertook all the recording and mixing on primitive, two-track, mono equipment in the dingy attic above the rudimentary mail order department.

The Nashboro/Excello Record and Distributing Company operated on a shoestring budget with just three employees, Dorothy Keaton, Young's devoted and indispensable secretary, Willie D. Hendrix who worked in the packing room and oft-times doubled as a packer and learn-as-you-go sound engineer, and a short, deaf bookkeeper, James Clifton who cussed every time radio dispatched taxi drivers out on the street jammed his hearing aid.  The store financed the record company at first, until the success of Arthur Gunter's ... enormous hit "Baby Let's Play House" stormed the charts in January 1955.

Youthful insomniacs and dedicated listener's could stay up past midnight in the East and listen to the third in the nightly series of record-shop-sponsored shows, this one brought to us courtesy of Buckley's Record Shop.

Buckley's show, entitled "After Hours," was introduced by the theme song "After Hours" by Erskine Hawkins.  The host disc jockey was a gentleman who seemed to be older than Gene Nobles or John R.  That gentleman was Herman Grizzard, pictured here, who had been with the station since the '30s.  I would be pleased for someone of you to send me more information regarding Buckley's record shop and the late night show.

Each of these record shops offered "special" packages of records available by mail order at a group price.  As I recall, each 5-record special from Ernie's was offered for a period of a couple months and was called something like Ernie's "Bullseye" Special or some similar name that would distinguish it from, say, Ernie's "Blue Ribbon" Special.  Five records for three dollars or so was a great deal too, as long as you didn't mind having a ringer or two in the group--some title that you probably wouldn't have otherwise purchased.  I mean ... did I really want a copy of "Gumbo Mombo" by Guitar Gable?

I can remember sitting in bed making notations in a diary detailing the play lists of these shows and the contents of each special record deal.  I used to think that the illustrations I drew as borders around these "specials" were quite clever and attractive.  Regrettably, that diary has fallen by the way somewhere over the years.  Of all the mementos of my youth, it would certainly be in the top 5 that I would wish to retrieve.

I always thought it was odd that Ernie's seemed to be pushing artists such as Larry Birdsong, Lonesome Sundown, and Lillian Offitt.  All became clear when I noticed that the address of Excello Records was 177 3rd Avenue North.  It was right next door!  That great distinctive Excello sound made me imagine that all of their recordings were being made in the back room at Ernie's.  Many years later I learned that I wasn't far wrong, although most of the later Excello artists' sessions were recorded at a studio in Crowley, Louisiana.

Yes, Ernie owned the Excello label.  So it is no surprise that he chose to pump up sales and promote his artists by including Excello discs in his "special" packages.  In truth, this was a relatively benign avenue of promotion by comparison to what was going on elsewhere in the music industry.

The best of the Ernie's specials was the "45" Special, described on a special sheet that came in the mail with your records.  Here you could select any five records from a list of over 200 "Blues" and "Spiritual" titles for the very agreeable price of $3.05.  Gee, looking it over after all these years, I realize that this must be where I got that copy of "Hoo Doo Blues" by Lightnin' Slim.


Bill "Hoss" Allen was yet another popular dee-jay at WLAC.  After graduating from Vanderbilt in 1948, Allen began his radio career at WHIN in his hometown of Gallatin, Tennessee, hosting "Harlem Hop."  Allen soon moved to WLAC, initially filling in where needed, ultimately taking over the 10:15 to midnight spot, when Gene Nobles retired.

The "Hossman" also hosted many gospel programs.  Indeed, in 1981, Savoy Records released an LP (SL 14627) entitled: Bill "Hoss" Allen Presents "Let's Go To The Program."  Subtitled "Twelve of America's Greatest Gospel Groups," the record includes recordings by such groups as The Swan Silvertones, The Soul Stirrers, and The Original Blind Boys of Alabama, introduced by Allen and altered to include applause, as though the performances were actually live, in concert.

Allen helped promote the careers of many musicians, but always down played his own significance:

I have heard many, many DJs who were a lot more personable, professional, and maybe even knowledgeable.  I was just myself.  I was just the Hossman.

Randy Wood saw it differently:

He was completely unique, you might say.  He didn't copy anyone, he was an original.

A humble man, Allen, enjoyed telling stories at his own expense.  One such involved the time in 1950 that Randy Wood offered him the opportunity to become a partner in the upstart "Dot" record label.  Allen turned Wood down and by 1956 "Dot" had become so successful that Wood moved his base of operations to Hollywood.

Bill Allen died February 25, 1997, at the age of 74.  The report of his death by Associated Press, together with a picture of Hoss, Sam Phillips, and others may be found on a separate page.


"The 50,000 Watt Quartet"

This photograph, probably taken around 1970, shows the legendary WLAC deejays(from left to right) John Richbourg, Gene Nobles, Hoss Allen, and Herman Grizzard.  Standing behind them is WLAC news announcer Don Whitehead, the only one of the five who clearly sounded like a white man on the air.

To learn far more about the personal lives and exploits of Gene Nobles, Hoss Allen, and all the gang at WLAC in the 1940s and '50s, I highly recommend to you the book "The Pied Pipers of Rock 'n' Roll" by Wes Smith (Longstreet Press, 1989).  Subtitled "Radio Deejays of the 50s and 60s," the book contains a chapter devoted to WLAC which recounts many amusing tales of the on and off-air shenanigans of the deejays and their staff.  Trust me, this book is a must.  Drinking, gambling, "auditioning" female staff members, monitoring an adjacent office building with binoculars, ... I mean, these guys got into more mischief than the Katzenjammer Kids.


During the hours not sponsored by record shops, WLAC featured a whole slew of wonderful commercials for such things as "live baby chicks," "Royal Crown Hair Dressing" and "White Rose Petroleum Jelly."  The disc jockeys used to have a lot of fun mentioning creative uses for that versatile substance, many with double entendre meanings.  Indeed, if one could believe the announcer, certain, more active, members of the listening audience were ordering the stuff in the 50-gallon drum size.  And, yes, you can still buy it today.

In retrospect, it appears that I got as much meaningful education attending those nightly sessions at 1510 on the dial as I did in many a classroom.  My horizons were broadened and I like to think that this process continues.  Listening to these magical broadcasts led directly to many another trail, not the least of which was attendance at a number of those wonderful traveling rhythm and blues revues.  And not everyone was happy with what young whites were learning either.  It wasn't just the musical tastes of teenagers that was changing.  Social change on a large scale was also in the wind.  Whenever a fresh breeze begins to blow, you can be sure that an old odor will perceive the threat.

The next thing we knew some young guy named Elvis was on the scene.  So was a young senator in Massachusetts, a young preacher in Alabama.  Youth itself, with its own spending money, its own fashion, its own culture, was on the move.  It is with great pleasure that we recall that vast regional subculture epitomized by WLAC.  Nothing quite like it is likely to happen again.  When today's young adults enter the age of nostalgic remembrance, who among them will fondly reflect upon MTV with the same recollection of innocence?


HEAR IT NOW AND BELIEVE IT LATER

If you were a faithful listener to WLAC in the '50s (and assuming that your computer has sound capability), prepare yourself for a truly profound wave of nostalgic recognition.  Yes, I know.  I'm just too good to you.

  • "Hey John R!" ... "way down South in Dixie."  Some of you heard this when this page first opened.  [142K -- 12 seconds]

  • Ernie's Record Mart ...records galore.  [62K -- 5 seconds]

  • What a deal!  Live Baby Chicks delivered right to your door!   [75K -- 6 seconds]  Or, if you have time to enjoy the longer version.   [299K -- 27 seconds]

  • The Johnny Weissmuller Ape Call.  [63K -- 5 seconds]

  • Gene Nobles pitching the "School Days Special" for Randy's Record Shop.  [219K -- 28 seconds]

  • Gene Nobles for Royal Crown Hair Dressing in his own inimitable way.  [159K -- 15 seconds]

  • The Ernie's theme song: "Dig These Blues" by the Four Clefs.  [176K -- 17 seconds]

  • An incredibly rare air check, the introduction to the Buckley's Record Shop program with your host, Herman Grizzard.  [249K -- 32 seconds]

"Wait a minute," you say, "It's great to hear old Herman, but what about his theme song?"  Well, that would be the oft recalled, but seldom identified, "After Hours."  Those who venture to the Multimedia Page will find it there.


THE MULTIMEDIA PAGE
And ... since these examples are so abbreviated, it is my pleasure to also present access to two entire selections in mp3 format.  Assuming your computer supports the playing of such files, the MultiMedia Page awaits you.


I am often asked: "Is it possible to get records or tapes of the old WLAC shows?"  Possible?  Well, prior to his death, John Richbourg was selling some cassette tapes that consisted largely of recreated versions of his Ernie's Record Mart shows.  A small amount of material taped off the air has circulated among fans for several years but, so far as I know, there is no currently authorized material of the sort that would allow me to give a "yes" answer to this question.  So what is this picture? The CD shown here is Ace CDCHD 684, Ernie's Record Mart, a reissue collection of 24 recordings originally released on Excello Records.  Selections include "Miss You So" by Lillian Offitt and "Pleadin' For Love" by Larry Birdsong, but it is not a representative collection of that label's hits.  The 12-page booklet is worthwhile and the disc starts off with a John R introduction similar to the one featured on this page. The last time I looked, this CD was available from Amazon.com.


LINKS

Animated towers

For the early history of WLAC, "the broadcast service of Life And Casualty Insurance," you can visit the station's own site.  Once you arrive there, be sure to click on the red banner that looks like this.

For a more extensive audio treat than those offered above, you can hear more than 5 minutes of a John R. broadcast at the exceptional "Uncle Ricky Collection" archival site.  Scroll way down or search the page for WLAC to find it.

Yet another worthwhile site presents an extensive treatment relating to Randy Wood and the history of the Dot records label.


If you would like to support this page and save yourself some money in the process, please consider shopping for your books, CDs, and videos from Amazon.com.


Just click one of these icons and bookmark or make a favorite of the page it takes you to.  Thereafter, your purchases from Amazon will produce a small credit to yours truly.  The eBay icon takes you to a list of items that my alter ego, Otto, is offering at auction this week.

Donations Are Welcome   If you are one of those rare angels who would like to make a modest donation to support my efforts, you may do so by clicking the Pay Pal "Donate" image and filling in the pertinent information that will appear on the next screen.  It's fast and easy and your surprising generosity will be greatly appreciated.

MORE?   Many other areas of the "Popular Culture Excavation Site" await you.  Full descriptions are on the main menu or go directly to the area of your choice by clicking one of these seductive little images.

The Katzenjammer KidsWillie the KOOL penguinMistinguettCarl "Duck Man" BarksSvend AsmussenTim "Kingfish" MooreWestern SwingHazel CourtRhythm and Blues RevuesEuropean Jazz and Close Harmony Vocal GroupsThe Pie Girl DinnerSally RandWLAC Radio: Nashville

Who are these guys?  Just place your cursor on each image to get a clue.

Return to the main menu.


On May 18, 2002, the 5th anniversary of the creation of the main site, hosting of this page was transferred from Yahoo/GeoCities to an independent server.  You are the most recent of the #!/usr/local/bin/perl5 use GD; alarm(600); # cgi-bin access counter program # Version 4.0.7 # # Copyright (C) 1995 George Burgyan # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or (at # your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # A full copy of the GNU General Public License can be retrieved from # http://www.webtools.org/counter/copying.html # # gburgyan@webtools.org # # George Burgyan # 1380 Dill Road # South Euclid, OH 44121 # # For more information look at http://www.webtools.org/counter/ ######################################################################## # # CHANGE THESE TO SUIT YOUR SITE # # The default language option (english, french, swedish) $default_lang = "english"; # The name of the file to use. You should probably give this an absolute path $FileName = "$ENV{'DOCUMENT_ROOT'}/counter/access_count"; # Replace with a list of regular expression IP addresses that we # are supposed to ignore. If you don't know what this means, just use # "\." instead of periods. Comment out entirely to ignore nothing. #@IgnoreIP = ("199\.18\.203\..*", # "199\.18\.159\.1", # ); # Aliases: Set this up so that diffent pages will all yield the same # count. For instance, if you have a link like "index.html -> home.html" # set it up like ("/index.html", "/home.html"). Make sure you give a full # path to it. This will treat "/index.html" as if it were "/home.html". %Aliases = ("/fakename.html", "/realname.html", "/index.html", "/home.html", ); # AUTOMATICALLY SET BY INSTALL!! Modify only if necessary!!! # # BaseName: set to whatever you have counter installed as. This is # used to derive the arguments. No not touch the next comment. ### AUTOMAGIC ### $BaseName = "counter"; # counter or counterbanner or counterfiglet # # Outputs the number of times a specific page has been accessed. # The output depends on which page 'called' it, and what the program # is named: # # The counter can "take arguments" via its name. That is, if you tack # -arg to the end of the program name, -arg is taken to be an argument. # For example, if you call the counter 'counter-ord', '-ord' is considered # an argument, and an ordinal count (1st, 2nd, 3rd, ...) will be printed # instead of (1, 2, 3, ...). Note that counterord does the same thing as # counter-ord for backward compatibility. # # Currently recognized arguments: # # -f=font sets "font" to be the font for figlet # -lang=lang sets the language used to ordinalize to "lang" # -nc no count; don't to write the incremented count back to the file # -nl no link; don't automatically generate a link # -nd no display; don't display anything, just count # -ord make an ordinal count instead of regular # -doc=document override the DOCUMENT_URI environment variable # # Example: counterfiglet-ord-f=bigfont-nc # # This will cause the counter to call figlet as the output routine, printing # in a big font an ordinal count, without updating the access count file. # Note that the order of arguments is irrelevant so long as you spell the # file name correctly. It is generally assumed that the ability to take # different arguments/use different output routines is done with symlinks: # i.e. ln -s counter counterfiglet-ord-f=bigfont-nc # # More complete documentation can be found at # http://www.webtools.org/counter/ # ######################################################################## # # Thing that shouldn't really need changing, but are configurable anyway. # # Maximum number of times to try to lock the file. # Each try is .1 second. Try for 1 second. $MaxTries = 10; # Set this to point to something, or comment it out, and it # won't be a link at all. # $Link = "http://www.webtools.org/counter/"; # Whether or not to use locking. If perl complains that flock is not # defined, change this to 0. Not *really* necessary because we check # to make sure it works properly. $UseLocking = 0; # What version of the counter file format are we using? $FileVersion = "02.000"; # Common names of the counter to install... @CommonExtensions = ("-ord", # Ordinam "figlet", # Figlet'ed "figlet-ord",# Ordinal figlet "banner", # Bannered "banner-ord",# Ordinal banner ); # ######################################################################### # # Misc documents to refer people to in case of errors. # $CreateFile = "[Error Creating Counter File -- Click for more info]"; $AccessRights = "[Error Opening Counter File -- Click for more info]"; $TimeoutLock = "[Timeout locking counter file]"; $BadVersion = "[Version access_count newer than this program. Please upgrade.]"; ######################################################################### # # The actual program! ### Stage 1 ### ### Parse the arguments... (just ignore this part) # Get arguments from program name. Argh...what a horrible way to do it! $prog = $0; $prog =~ s/(\.cgi|\.pl)//; #strip .cgi|.pl name extension $prog =~ s!^(.*/)!!; # separate program name $prog =~ s/\\(.)/sprintf("%%%02x", ord($1))/ge; # quote \c to %xx ($printer, @args) = split(/-/, $prog); # args are separated by dashes $printer =~ s/%(..)/pack("c", hex($1))/ge; # unquote printer function name $printer =~ s/$BaseName/counter/; # Make it cannonical. # This gets path info, which is only applicable if you are using our # ssis script (see above). This makes counter/ord the same as counter-ord push(@args, split("/", $ENV{"PATH_INFO"})) if $ENV{"PATH_INFO"}; # put them in assoc array %arg foreach (@args) # means do this for each element in the array { s/%(..)/pack("c", hex($1))/ge; # unquote %xx /^([^=]*)=?(.*)$/; # extract "=" part, if any $arg{$1} = $2 ? $2 : 1; } if ($ARGV[0] eq '-install') { &CheckPerl; &SetBaseName; &MakeCommon(0); exit(0); } if ($ARGV[0] eq '-installforce') { &CheckPerl; &SetBaseName; &MakeCommon(1); exit(0); } if ($ARGV[0] eq '-unlock') { open(FILE,"$FileName"); &UnlockFile(FILE); exit(0); } undef $Link if $arg{'nl'}; # make link? ### Stage 2 ### ### Print out the header # Print out the header print "Content-type: text/html\n\n"; #print "Debug 1: $ConfName
Debug 2: $FileName"; ### Stage 3 ### ### Open the access_count file for read-write taking all the precautions # Make sure the file exists: if (!(-f $FileName)) { if (!open (COUNT,">$FileName")) { # Can't create the file print $CreateFile; exit 1; } else { # We got the file, print out the version number print COUNT "$FileVersion\n"; $version = 2; } } else { if (!((-r $FileName) && (-w $FileName))) { # Make sure that we can in fact read and write to the file in # question. If not, direct them to the FAQ. print $AccessRights; exit 1; } if (!open (COUNT,"+<$FileName")) { # Now make sure it *really* opens print $AccessRights; # ...just in case... exit 1; } # Try to read in a version number $version = ; if (!($version =~ /^\d+.\d+$/)) { # No version number, assume version 1 and reset the file. $version = 1; seek(COUNT,0,0); } } # This is for the future: the access_count file will have a version number. if ($version > 2) { print $BadVersion; exit 1; } ### Stage 4 ### ### Attempt to lock the file $lockerror = &LockFile(COUNT); # You would figure that $MaxTries would equal 0 if it didn't work. The # post-decrement takes it to -1 when the loop finally exits. if ($lockerror) { print $TimeoutLock; exit(0); } ### Stage 5 ### ### Check if we need to update the file to a newer version if ($version < 2) { &UpdateVersion1; } ### Stage 6 ### ### Convert the information the server gave us into the document ### identifier. # Make sure perl doesn't spit out warnings... if (defined $ENV{'DOCUMENT_URI'}) { $doc_uri = $ENV{'DOCUMENT_URI'}; } else { $doc_uri = ""; } # Campatibility: Version 2 files have the server name in front if and # only if it doesn't have a "~" in it. $old_uri = $doc_uri; # Add the server name in front to support multi-homed hosts if and only if # it doesn't have a "~" in it. (usernames are global in most multi-homed # settings if (defined $ENV{'SERVER_NAME'} && !($doc_uri =~ /~/)) { $doc_uri = $ENV{'SERVER_NAME'} . "/" . $doc_uri; } if (defined $arg{'doc'}) { $doc_uri = $arg{'doc'}; } $doc_uri = $Aliases{$doc_uri} if defined $Aliases{$doc_uri}; ### Stage 7 ### ### Find the relevant place in the file $location = tell COUNT; while ($line = ) { # Read the file line-by-line. if (($uri,$accesses) = ($line =~ /^'(\S*)' (\d\d\d\d\d\d\d\d\d\d)$/)) { # An old line if ($uri eq $old_uri) { &ConvertDocV1($doc_uri,$old_uri,$accesses,$location); last; } } elsif (($uri,$accesses,$flags) = ($line =~ /^'(\S*)' (\d\d\d\d\d\d\d\d\d\d) (\w\w\w\w)$/)) { # A new line if ($uri eq $doc_uri) { $flags = hex($flags); last; } } last if ($uri eq $doc_uri); $location = tell COUNT; #reset the fields $accesses = 0; $flags = 0; } ### Stage 8 ### ### Update the access count of the file $accesses += 1; # *NOT* '++' because we don't want '++'s magic ### Stage 9 ### ### Figure out what to print out # If we have to ordinalize, do it now. if (defined $arg{'ord'}) { if (defined $arg{'lang'}) { $ord = eval("&ordinalize_$arg{lang}($accesses)"); } else { $ord = &ordinalize($accesses); } } else { $ord = ""; } $to_print = $accesses . $ord; # Give it to the printer function to actually produce the output from the # ascii text that we have (to_print) ($count, $nLink) = eval("&output_$printer('$to_print')"); # If the above line gave us an error, default to just the text. if ($@) { ($count, $nLink) = &output_counter($to_print); } ### Stage 10 ### ### Now we actually tell the browser what the count is. if (! $arg{"nd"} ) { # If we print anything # Print out a link to something informative (if we were requested to) $script_name = $ENV{'SCRIPT_NAME'}; print "" if $nLink; if ($script_name =~ /cgi-bin\/count(\w+)/) { $img_dir = $1; } if ($img_dir ne "er") { &give_graphic } else { print $count; print "" if $nLink; } } sub give_graphic { @img_count = split(//,$count); foreach (@img_count) { print ""; }; } sub comment1 { # create a new image print "Content-type: image/gif\n\n"; $im = new GD::Image(100,100); # allocate some colors $white = $im->colorAllocate(255,255,255); $black = $im->colorAllocate(0,0,0); $red = $im->colorAllocate(255,0,0); $blue = $im->colorAllocate(0,0,255); # make the background transparent and interlaced $im->transparent($white); $im->interlaced('true'); # Put a black frame around the picture $im->rectangle(0,0,99,99,$black); # Draw a blue oval $im->arc(50,50,95,75,0,360,$blue); # And fill it with red $im->fill(50,50,$red); # Convert the image to GIF and print it on standard output print $im->gif; } ### Stage 11 ### ### Check if we are supposed to update the count in the file. (ie. we're ### not ignoring the host that just accessed us) # Make sure we are not ignoring the host: $ignore = 0; $ignore = grep($ENV{"REMOTE_ADDR"} =~ /$_/, @IgnoreIP) if defined ($ENV{"REMOTE_ADDR"}); $ignore = $ignore || $arg{"nc"}; ### Stage 12 ### ### Actually write the updated information back to the file if (!$ignore) # If we aren't ignoring this access { # Now update the counter file seek(COUNT, $location, 0); $longaccesses = sprintf("%010.10d", $accesses); $hexflags = sprintf("%04.4x", $flags); print COUNT "'$doc_uri' $longaccesses $hexflags\n"; } &UnlockFile(COUNT); close COUNT; ####################################################################### # # Support functions # # translate_output # # Quote any special characters with HTML quoting. sub translate_output { local($string) = @_; $_ = $string; s/è/è/g; return $_; } sub LockFile { local(*FILE) = @_; local($TrysLeft) = $MaxTries; if ($UseLocking) { # Try to get a lock on the file while ($TrysLeft--) { # Try to use locking, if it doesn't use locking, the eval would # die. Catch that, and don't use locking. # Try to grab the lock with a non-blocking (4) exclusive (2) lock. # (4 | 2 = 6) $lockresult = eval("flock(COUNT,6)"); if ($@) { $UseLocking = 0; last; } if (!$lockresult) { select(undef,undef,undef,0.1); # Wait for 1/10 sec. } else { last; # We have gotten the lock. } } } if ($TrysLeft >= 0) { # Success! return 0; } else { return -1; } } sub UnlockFile { local(*FILE) = @_; if ($UseLocking) { flock(FILE,8); # Unlock the file. } } #################################################################### # # Installation helpers # # SetBaseName # # Change the counter program itself to set the basename sub SetBaseName { local($name) = $0; $name =~ s/^.*\/([^\/]+)$/$1/; # Strip off any of the path if ($name eq $BaseName) { # The way we're set up now!!! return; # Don't need to change a thing. } if (!open(COUNTERFILE, "+<$0")) { print "Can't modify program. Set \$BaseName manually.\n"; return; } print "Configuring \$BaseName variable...\n"; local($oldsep) = $/; undef($/); local($program) = ; # The next line does all the magic. $program =~ s/\#\#\# AUTOMAGIC \#\#\#\n\$BaseName = \"[^\"]+\";\n/\#\#\# AUTOMAGIC \#\#\#\n\$BaseName = \"$name\";\n/; seek(COUNTERFILE,0,0) || return; truncate(COUNTERFILE,0); print COUNTERFILE $program; close COUNTERFILE; } # CheckPerl # # Make sure that the "#! /[path]/perl" points to something real... sub CheckPerl { if (!open(COUNTERFILE, "<$0")) { print "Can't check to make sure Perl is in the right place.\n"; return; } print "Checking to make sure Perl is found properly...\n"; $firstline = ; ($command) = ($firstline =~ /^\#! *([^\s]+) *$/); close(COUNTERFILE); if (! -x $command) { print "The location of Perl is misconfigured. Please edit the\n"; print "first line of this program to point to the locally installed\n"; print "copy of perl.\n\n"; print "Currently, it is configured to be \"$command\", however,\n"; print "that file either does not exist or is not a program.\n\n"; print "Some common locations for Perl are:\n"; print " /usr/bin/perl\n"; print " /usr/local/bin/perl\n"; print " /bin/perl\n"; print " /opt/gnu/bin/perl\n\n"; exit; } } # MakeCommon # # Make some common links to the counter sub MakeCommon { local($force) = @_; local($ext); print "Installing the counter...\n"; print " ...making counter executable\n"; chmod(0755,$0); local($path, $name, $cgi); $name = $0; if ($name =~ /^(.*\/)([^\/]+)$/) { $path = $1; $name = $2; } if ($name =~ /^(.*)(\.cgi)$/) { $name = $1, $cgi = $2; } foreach $ext (@CommonExtensions) { print " ...making link from $path$name$cgi to $path$name$ext$cgi\n"; if (!&MakeLink("$path$name$cgi","$path$name$ext$cgi",$force)) { # An error occured while making the link. :-( print " *** An error occured while making the link.\n"; } } if ($symlink_exists == 0 && $link_exists == 0) { print "* NOTE * Your system does not support symbolic or hard links,\n"; print " copies made instead. If you modify the counter, you must\n"; print " run counter -install again to recopy it to the other files.\n"; } print "...done!\n"; } # MakeLink # # Actually create the link. sub MakeLink { local($oldname,$newname,$force) = @_; # Check to see if we can make symbolic links instead of hard links if (!defined $symlink_exists) { $symlink_exists = (eval 'symlink("","");', $@ eq ''); } # Check to see if we can make a link if we can't make a symlink if (!symlink_exists) { $link_exists = (eval 'link("","");', $2 eq ''); } if ($force) { # Check to see if the file exists if (-e $newname) { if (!unlink ($newname)) { return 0; } } } if ($symlink_exists) { return symlink($oldname, $newname); } elsif ($link_exists) { return link($oldname, $newname); } else { # Copy it the old-fashioned way... *sigh* open(OLDFILE, $oldname) || die "Can't open $oldname for copy"; open(NEWFILE, ">$newname") || die "Can't open $newname for write"; while() { print NEWFILE $_; } close(NEWFILE); close(OLDFILE); } } #################################################################### # # Ordinalizing functions # # ordinalize # # Call the appropriate ordinalize function for the default language sub ordinalize { local($count) = @_; if (defined $arg{'lang'}) { return eval("&ordinalize_$arg{lang}($count)"); } else { return eval("&ordinalize_$default_lang($count)"); } } # ordinalize_english # # Figure out what suffix (st, nd, rd, th) a number would have in ordinal # form and return that extension. sub ordinalize_english { local($count) = @_; local($last, $last2); $last2 = $count % 100; $last = $count % 10; if ($last2 < 10 || $last2 > 13) { return "st" if $last == 1; return "nd" if $last == 2; return "rd" if $last == 3; } return "th"; # Catch "eleventh, twelveth, thirteenth" etc. } # ordinalize_french # # Trivial... Return the extension for french. The only exception is 1. # Thank you Chris Polewczuk sub ordinalize_french { local ($count) = @_; if ($count == 1) { return "'ière"; } else { return "ième"; } } # ordinalize_swedish # # A function to ordinalize in Swedish. Thanks go to Johan Linde # for the code! sub ordinalize_swedish { local($count) = @_; local($last, $last2); $last2 = $count % 100; $last = $count % 10; if ($last2 < 10 || $last2 > 12) { return ":a" if ($last == 1 || $last == 2); } return ":e"; } ######################################################################## # # Output functions # # The following are the routines that actually convert the number # of accesses into something that we print out. # # The name of each function is "output_" followed by the program's name. # For instance, is the program is called "counter" then "output_counter" # will be called; a program called "counterbanner" will call # "output_counterbanner" to get the output. # # If the function is not defined, then "output_counter" will be called. # # output_counter # # The simplest function: just returns the number of accesses and the link. sub output_counter { local($count) = @_; return &translate_output($count), $Link; # we return the count and the link } # output_counterord # # Return the number of accesses as an ordinal number. (ie. 1st, 2nd, 3rd, 4th) sub output_counterord { local($count) = @_; return &translate_output($count . &ordinalize($count)), $Link; } # output_counterbanner # # A somewhat silly one that uses the "banner" command to print out the # count. :) You might need to change the path to make it work. sub output_counterbanner { local($count) = @_; $banner = `banner $count`; return "

$banner
"; # return no link here (it would be annoying) } # output_counterfiglet # # An even sillier one than counterbanner. :) sub output_counterfiglet { local($count) = @_; $fig = "echo $count | /usr/games/figlet"; # setup command line $fig .= " -f $arg{'f'}" if $arg{"f"}; # use a different font? $fig = `$fig`; $fig =~ s!&!&!g; $fig =~ s!
" . $fig . "
"; # note no link here, either } ######################################################################### # # Conversion functions # # UpdateVersion # # Convert a version 1file into a version 2 file. sub UpdateVersion1 { local ($contents,$dummy); local ($oldsep) = $/; $/ = ""; seek(COUNT,0,0); # Go to the beginning of the file $contents = ; seek(COUNT,0,0); print COUNT "$FileVersion\n"; print COUNT $contents; seek(COUNT,0,0); $/ = $oldsep; $dummy = ; # Skip the new line } # ConvertDocV1 # # Convert the a version 1 line into a version 2 line sub ConvertDocV1 { local ($doc_uri,$old_uri,$accesses,$location) = @_; local ($contents,$dummy,$oldsep); $oldsep = $/; seek (COUNT,$location,0); # Skip the line in question $dummy = ; $/ = ""; # Read in the whole file $contents = ; seek (COUNT,$location,0); local ($longaccesses,$hexflags); $longaccesses = sprintf("%010.10d", $accesses); $hexflags = sprintf("%04.4x", $flags); # Print out the new stuff print COUNT "'$doc_uri' $longaccesses $hexflags\n"; print COUNT $contents; $/ = $oldsep; } cognoscenti who have ventured to this page since that date.


This page created and maintained by Jim Lowe
First appearance: September 8, 1997
Last updated: May 15, 2003

© 1997, 1998, 2001, and 2003, by James R. Lowe, who reserves all rights to the content of this page not successfully claimed by others.