[net.bugs.uucp] your uucp/gename.c

swatt (07/20/82)

	From decvax!ucbvax!knutsen@SRI-UNIX Mon Jul 19 22:53:35 1982
	Date: 19 Jul 1982 at 1514-PDT
	From: Andrew Knutsen <knutsen@SRI-UNIX>
	To: decvax!ittvax!swatt at UCB
	Subject: your uucp/gename.c
	Sender: knutsen at SRI-UNIX
	
	
	
	------- Forwarded Message
	
	Date: 19 Jul 82 11:16-PDT
	From: mclure@SRI-UNIX
	To: knutsen@SRI-UNIX
	Subject: Re: uucp mods
	
	Hmm, our compiler barfs on the line "typedef unsigned long int ts_t".
	Have you seen that construction before?
	
	
	------- End of Forwarded Message
		Is an "unsigned long int" something special for
	vaxen? Has this code ever been tried on an 11? Id just
	switch it to long (since there are no right shifts or printfs)
	but Im curious why you used that.
		Thanks for the mod... we're on the edge of dropping
	a neighbor due to uux overhead/overload.

====================================================================== 
Okay, this seems to be of general interest.  Our VAX compiler has 
it, but I guess we're in the minority.  The "unsigned"  qualifier
is  in  this  case  unnecessary,  but  I  included it for literal
correctness for all magnitudes.  

It just also occurred to me: Some 16-bit machine compilers object 
to the designation "register ts_t", which is  used  in  "totoa()"
and  "atots()", where "ts_t" is a typedef for "long int".  Simply
change that to omit the register qualifier.  
====================================================================== 

>From swatt Mon Jul 19 13:33:28 1982
To: decvax!ucbvax!menlo70!sri-unix!mclure
Subject: gename.c
Cc: cbosgd!mark


	From decvax!ucbvax!menlo70!sri-unix!mclure Sat Jul 17 08:12:52 1982
	Date: Sat Jul 17 03:09:23 1982
	To: menlo70!ucbvax!decvax!ittvax!swatt
	
	Hi. I got a copy of your gename.c mods from Mark Horton via net.sources
	and was wondering about something. When I try to compile it, I get
	'misplaced long' for lines 76 & 181 (typedef unsigned long int ts_t).
	I've never seen this construction before. We're running 2.8 BSD v7 on
	an 11/70.
	
		Stuart
	
	
"unsigned long" is only recognized by the portable C compiler, and
even then I think not all versions do so.

The "unsigned" qualifier is unnecessary for base 62 sequence numbers
of length 4 (max == 14 million something).  You can just change that
to "typedef long int ts_t" and it should all work.

There are also some complaints about "mismatched arguments" to the
ASSERT macro.  The ASSERT calls are all as I found them; I think
the mismatch only occurs in the test versions.

Here is the new source with the change; I've tested it to be sure
that "zzzz" wraps around to "0000" as it should.  This is on a VAX
of course; you should verify it all works on your pdp-11.  This is
what the "#ifdef TEST" junk is for; you can generate a local test
copy.  It expects to include the file "uucplock.c", which on most
installations is "ulockf.c" in the uucp source area.

	- Alan
======================================================================
	/*  gename 3.3  1/5/80  13:51:41  */

#ifdef TEST
# define finish(x)	exit(x)
# define DEBUG(a,b,c)	;
# define SEQLOCK	"SEQLCK"
# define SEQFILE	"SEQFILE"
# include "uucplock.c"
#else !TEST
# include "uucp.h"
# ifdef ITTVAX
#  define TSSEQ
#  define SEQHUNK 10
#  define BASE 62
# endif ITTVAX
#endif TEST


/*******
 *	gename(pre, sys, grade, file)	generate file name
 *	char grade, *sys, pre, *file;
 *
 *	return codes:  none
 */

gename(pre, sys, grade, file)
char pre, *sys, grade, *file;
{
	char sqnum[5];

	getseq(sqnum);
	sprintf(file, "%c.%.7s%c%.4s", pre, sys, grade, sqnum);
	DEBUG(4, "file - %s\n", file);
	return;
}


#define SLOCKTIME 10L
#define SLOCKTRIES 5
#define SEQLEN 4

/*******
 *	getseq(snum)	get next sequence number
 *	char *snum;
 *
 *	return codes:  none
 *
 * Fri Jan 15 15:34:02 EST 1982 ittvax!swatt:
 * if "TSSEQ" is defined, use "ts" routines to keep sequence numbers
 * in either base 36 or 62.
 * if "SEQHUNK" is defined, then sequence numbers are allocated in
 * hunks of that size.  Using SEQHUNK on very busy systems is not
 * advisable unless TSSEQ is also enabled.
 *
 * Also fix so wraparound is correct; the old code did 9999=>1000
 *
 * The hunk idea saves a lot of filesystem activity.  To get a
 * new sequence number from the sequnce file invovles:
 *
 *  1)	Lock the file (creat + link)
 *  2)	Open file
 *  3)	Read from file
 *  4)	Reopen file for writing
 *  5)	Change mode to 0666
 *  6)	Write to file
 *  7)  Unlock file (unlink)
 */

#ifndef SEQHUNK
# define SEQHUNK 1
#endif !SEQHUNK

#ifdef TSSEQ
 typedef long int ts_t;
 ts_t	atots();
 char	*tstoa();
#else !TSSEQ
 typedef int ts_t;
#endif TSSEQ


getseq(snum)
char *snum;
{
	FILE *fp;
	char tseqbuf[64];
	static ts_t n;
	static int nseq = 0;

	if (nseq <= 0) {
		for (n = 0; n < SLOCKTRIES; n++) {
			if (!ulockf( SEQLOCK, SLOCKTIME))
				break;
			sleep(5);
		}

		ASSERT(n < SLOCKTRIES, "CAN NOT GET", SEQLOCK, 0);

		/* @@@(ittvax!swatt):
		 * can save something by using "r+" on fopen
		 */
		if ((fp = fopen(SEQFILE, "r")) != NULL) {
#ifdef TSSEQ
			fgets (tseqbuf, sizeof tseqbuf, fp);
			n = atots (tseqbuf);
#else !TSSEQ
			/* read sequence number file */
			fscanf(fp, "%4d", &n);
#endif TSSEQ
			fp = freopen(SEQFILE, "w", fp);
			ASSERT(fp != NULL, "CAN NOT OPEN", SEQFILE, 0);
			chmod(SEQFILE, 0666);
		}
		else {
			/* can not read file - create a new one */
			if ((fp = fopen(SEQFILE, "w")) == NULL)
				/* can not write new seqeunce file */
				return(FAIL);
			chmod(SEQFILE, 0666);
			n = 0;
		}
#ifdef TSSEQ
		tstoa (n+SEQHUNK, tseqbuf, SEQLEN);
#else !TSSEQ
		sprintf (tseqbuf, "%04d", n+SEQHUNK);
#endif TSSEQ
		/* discard high order digits on overflow */
		while (strlen (tseqbuf) > SEQLEN)
			strcpy (tseqbuf, tseqbuf+1);
		fprintf (fp, "%s", tseqbuf);
		fclose (fp);
		rmlock (SEQLOCK);
		nseq = SEQHUNK;
	}

#ifdef TSSEQ
	/* Convert n to base 36 (or base 62) digit string */
	tstoa (n, tseqbuf, SEQLEN);
#else !TSSEQ
	sprintf (tseqbuf, "%04d", n);
#endif TSSEQ
	/* discard high-order digits on overflow */
	while (strlen (tseqbuf) > SEQLEN)
		strcpy (tseqbuf, tseqbuf+1);
	strcpy (snum, tseqbuf);
	++n;
	--nseq;
	return(0);
}

#ifdef TSSEQ
/*********************************************************************
function:	ts
description:	Convert between binary integers and base thirty-six
		strings (hence the name "ts")
programmer:	Alan S. Watt

history:
	01/14/82	original version
*********************************************************************/


/* Alphanumeric string-to-integer conversion routines */

/* BASE is either 36 or 62
 * Base 36 allows magnitudes from 0 to 1679615
 * Base 62 allows magnitudes from 0 to 14776365
 */
#ifndef BASE
# define BASE	62
#endif BASE
#define EOS	'\0'
static char tsdigits[]	=
	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

#include <ctype.h>

/* Ordinal values for characters
 * Change for non-ASCII
 */
#define DIGORD(c)	(c-'0')
#define UCORD(c)	(c-'A')
#define LCORD(c)	(c-'a')


/* Convert TS string to binary integer */
ts_t
atots (str)
register char *str;
{

	register ts_t ret;
	register digit;

	for (ret = 0; *str != EOS; str++) {
		if (isupper (*str))
			digit = UCORD(*str) + 10;
		else if (islower (*str))
			digit = LCORD(*str) + 10 + (BASE-36);
		else if (isdigit (*str))
			digit = DIGORD(*str);
		else
			break;
		ret = ret * BASE + digit;
	}
	return (ret);
}

/* Convert binary integer to TS string.
 * String is left-padded with zeros up to the
 * width given by 'prec'.  Truncation does not
 * take place here; calling routine must do it
 * if required.
 */
char *
tstoa (num, buf, prec)
register ts_t num;
register char *buf;
int prec;
{
	register ts_t quot = num / BASE;

	if (--prec > 0 || quot != 0)
		buf = tstoa (quot, buf, prec);
	*buf++ = tsdigits[num % BASE];
	*buf = EOS;
	return (buf);
}
#endif TSSEQ

#ifdef TEST
#include <stdio.h>
main (argc, argv)
int argc;
char **argv;
{
	char buf[128];
	int nseq;

	if (argc > 1)
		nseq = atoi (argv[1]);
	else
		nseq = 10;
	while (nseq-- > 0) {
		gename ('C', "ittvax", 'n', buf);
		if (argc < 3)
			printf ("%s\n", buf);
	}
}
#endif TEST