lee@kcl-cs.UUCP (Lee McLoughlin) (02/24/85)
Yes there is a rather serious bug in lotsend to do with the way uux handles the mapping of names. uux -r rnewsall!kcl-cs /f1/news/net/frobitz/11 /f1/news/net/general/11 uuxqt causes the second file to overwrite the first on moving them to the execute directory and it then runs: rnewsall 11 11 Result lost news. Thanks a bunch to everyone who pointed it out. Simple fix. Also it calls system() to run the command now to ensure that a /bin/sh is called. /* * Simple news batcher. * Rather than running compress and all that stuff simply submit a * command like: * uux -r -c remote!rnewsall !/news/net/oa/1 !/news/net/ai/276 * where rnewsall is a simple script which calls rnews on all its arguments. * Its input can be generated by a news sysfile line like: * ic-cs:uk,eunet,net,mod,fa:F:/usr/lib/news/lots.ic-cs * Lotsend itself should be called (by cron) a few minutes before news is * due to be sent. For example the following crontab entry. 0 0,1,2,3,4,5,6,7,8,23 * * * /usr/lib/news/lotsend ic-cs * * CAREFULL: lotsend will zap the existing lots list. Remember to install * it with a mode of 6755 and a user/group id suitable for news. * * Note that you do not get the transmission saving that compress style * batchers give you but you do save more blockspace since copies of the data * are never stored in the spool area. * * This is particulaly usefull if you have the uucp mod to prevent resending * successfully transmitted files. * * L.M.McLoughlin. * Feb 1984. Get around uux problem where the remote end only sees * the lastparts of names so make sure they're unique. * Allow dir, cmd and wether to ! names to be specified. * * rnewsall: for i do if test -r $i then rnews < $i rm -f $i else echo $0: failed to find $i >> $NEWS/rnewsall.log fi done */ char *Rcsid = "$Header: /f0/UKUUCP/lotsend.c,v 1.2 85/02/24 01:43:41 lee Exp $"; /* $Log: lotsend.c,v $ * Revision 1.2 85/02/24 01:43:41 lee * Add a few usefull options and fix bug to do with tails of names being * treated the same by uux! * * Revision 1.1 85/02/24 00:58:39 lee * Initial revision * */ #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #define BLK 512 /* Don't fiddle with this */ #define MAXBLKS 200 #define MAXARGS 20 int maxblks = MAXBLKS; /* Max blks of data per uux call. */ long maxsize; int maxargs = MAXARGS; /* Max no. of args per uux call. */ char *site; /* Name of site to use */ /* Where the lists the news generates are kept * This program MUST have write permission on that directory. * Preferably run this program under the news id. */ #define LOTSDIR "/usr/lib/news" char *dir = LOTSDIR; /* Directory where lots are kept. */ char *base_cmd = "uux -r -z -c %.7s!rnewsall "; /*Command to run */ int nopling = 0; /* Give filename as !file, default is to give ! */ main( argc, argv ) int argc; char **argv; { int ma, mb; FILE *lf; char *lt, lotname[ BUFSIZ ]; char filename[ BUFSIZ ]; while( argv++, --argc ){ if( argv[ 0 ][ 0 ] != '-' ) break; switch( argv[ 0 ][ 1 ] ){ case 'a': ma = 0; sscanf( &argv[ 0 ][ 2 ], "%d", &ma ); if( 0 < ma && ma <= MAXARGS ) maxargs = ma; break; case 'b': mb = 0; sscanf( &argv[ 0 ][ 2 ], "%d", &mb ); if( 0 < mb && mb <= MAXBLKS ) maxblks = mb; break; case 'c': base_cmd = &argv[ 0 ][ 2 ]; break; case 'd': dir = &argv[ 0 ][ 2 ]; break; case 'n': nopling = 1; break; } } maxsize = (long)maxblks * BLK; if( argc == 0 ){ fprintf( stderr, "Usage: lotsend [-aMAXARGS] [-bMAXBLKS] [-ccmd] [-ddir] [-n] file\n" ); exit( 1 ); } if( chdir( dir ) == -1 ){ fprintf( stderr, "lotsend: cannot chdir to %s\n", LOTSDIR ); exit( 2 ); } /* Move the given lot file into a temporary to avoid problems * with inews updates. */ site = argv[ 0 ]; sprintf( lotname, "lots.%s", site ); lt = mktemp( "LOTS.XXXXXX" ); if( link( lotname, lt ) == -1 ){ fprintf( stderr, "lotsend: cannot link %s to %s\n", lotname, lt ); exit( 3 ); } unlink( lotname ); if( (lf = fopen( lt, "r" )) == NULL ){ fprintf( stderr, "lotsend: cannot open to %s\n", lt ); exit( 4 ); } init(); /* Initialize the command generator */ while( fgets( filename, BUFSIZ, lf ) != NULL ){ filename[ strlen( filename ) - 1 ] = '\0'; addname( filename ); } outcmd(); fclose( lf ); unlink( lt ); exit( 0 ); } long size_sofar = 0; int args_sofar = 0; char cmd[ 5*1024 ]; /* Initialize the cmd. */ init() { size_sofar = 0l; args_sofar = 0; sprintf( cmd, base_cmd, site ); } /* Add the name to the list to be given to uux. * If maxargs name in the list call outcmd. * If the total size of all files > maxblks then call outcmd * Force the list out on getting two names with the same tail part. * Eg: /f1/news/general/1 /f1/news/net/sport/1 * since uux treats this badly. */ addname( name ) char *name; { struct stat sb; long tot; char *lastpart(); if( stat( name, &sb ) == -1 ) return; /* Its gone! Ignore it */ if( (tot = sb.st_size + size_sofar) > maxsize || inlist( lastpart( name ) ) ) outcmd(); /* Send what we have sofar */ size_sofar = tot; if( !nopling ) strcat( cmd, "!" ); strcat( cmd, name ); strcat( cmd, " " ); args_sofar++; if( args_sofar >= maxargs ) outcmd(); } /* See if the name given is the same as a lastpart of * an existing name in the cmd. */ inlist( name ) register char *name; { register char *s = &cmd[ strlen( base_cmd ) + 1 ]; while( *s != '\0' ){ register char *sp = index( s, ' ' ); /* Stomp on space terminator */ *sp = '\0'; /* Has it the same end? */ if( strcmp( lastpart( s ), name ) == 0 ){ *sp = ' '; return( 1 ); } *sp = ' '; s = sp + 1; } return( 0 ); } outcmd() { if( args_sofar == 0 ) return; system( cmd ); init(); } /* LMCL: This is needed since the Orion has a bug to do with decrementing * the argv[0] pointer before the start of memory. * * Bug has long since been fixed but this * is the only lastpart() I had around. */ char * lastpart( file ) register char *file; { register char *c; char *index(); if( index( file, '/' ) != ((char *)0) ){ c = file + strlen( file ); while( c >= file) { if( *(--c) == '/' ) break; } return( ++c ); } else return( file ); } -- UKUUCP SUPPORT Lee McLoughlin <UK>!ukc!lmcl kcl-cs!lee "What you once thought was only a nightmare is now a reality!"