gj@cbscc.UUCP (08/25/83)
The New Batch Program Owner: Gary Jolly It became necessary to write a new batch program to be used on netnews in place of the old batch program.The old batch program was unable to transfer a file, which con- tain names of news articles, that exceeds one million bytes. The new batch program differs in that it will enable the transfer of news articles up until their limit. The limit of the articles that can be transferred will be decided by how many blocks the user wishes to transfer. This limit will be the third argument in the program. Once the limit of how many articles that can be transferred is reached,the remaining articles that were not transferred will be placed in a file by the same name. The old file is then removed. If the limit is greater than the size of the articles, each article in the file is printed. The file is then removed. Using the Batch Program User types: batch list 88 The first argument, which is batch, is the name of the program. The second argument is a file, which in this example is called list. For this example list will contain the articles below. /usr/spool/news/control/112 /usr/spool/news/btl/general/82 /usr/spool/news/btl/general/186 /usr/spool/news/btl/movies/403 The third argument is the number of blocks the user wishes to transfer. For this example the number of blocks will be 88. 1 block = 512 characters How it works 1. If articles 112 and 82 are less than 88 blocks, they will be transferred. The rest of the articles will be placed in a file by the same name. The old file will be removed. list contains: /usr/spool/news/btl/general/186 /usr/spool/news/btl/movies/403 2. If all of the articles are less than 88 blocks, each one will be transferred. The file, which is called list, is then removed. ********************* batch.c ********************** #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #define ERROR -1 char IBUF[513]; char *BUFP; char *BUFE; int LEN; long n; main( argc, argv ) int argc; char **argv; { FILE *fp; char filename[80]; int getlin(); int indev; int i,x; if( argc != 3) { printf("Usage: 3 argruments needed\n"); exit(0); } if(( n = atoi(argv[2])) >= 0 ) n *= 512; else { printf("%s : not acceptable MUST BE POSITIVE\n",argv[2]); exit(0); } if( (indev = open( argv[ 1 ], 0 )) == ERROR ) { printf("batch: can't open %s\n",argv[ 1 ]); exit( 0 ); } while( (getlin( indev )) > 0 ) { x=0; for( i = 0 ; i < 80 ; i++ ) { if( BUFP[i] == ' ' ) continue; if( (filename[x++] = BUFP[i] ) == '\0' ) break; } if(cat_file(filename) == -1) { fp = fopen("batchtmp", "w"); fprintf(fp, "%s\n",&filename[0]); while( (getlin( indev )) > 0 ) { x=0; for( i = 0 ; i < 80 ; i++ ) { if( BUFP[i] == ' ' ) continue; if( (filename[x++] = BUFP[i] ) == '\0' ) break; } fprintf(fp, "%s\n",&filename[0]); } unlink(argv[1]); link("batchtmp", argv[1]); unlink("batchtmp"); fclose(fp); exit(0); } } unlink(argv[1]); exit( 0 ); } cat_file( filename ) /* cat files */ char filename[]; { FILE *fp; int filesize(); static long size = 0; int fsize; if((fp =fopen(filename,"r"))== NULL) printf("batch: cannot open %s\n",filename); else { fsize = filesize( filename); size += fsize; } if(n > size ) { printf("#! rnews %d\n",fsize); filecopy(fp); fclose(fp); return( 0 ); } else return( -1 ); } filecopy(fp) /* copy file fp into std.output */ FILE *fp; { int c; while((c =getc(fp)) != EOF ) putc(c, stdout); } filesize( name ) char *name; { int fstat(); int fildes; struct stat buf; fildes = open( name , 0 ); fstat( fildes , &buf ); close(fildes); return( (int)buf.st_size ); } ********************** getlin.c ********************** # /* FUNCTION: Get line of input data Owner: Jim McGuire This subroutine reads data from the file specified by the file descriptor given as an argument and breaks it into individual lines terminated by a new line character. CALL is made as follows: getlin(indev); where indev is the input file descriptor of an opened file. The number of characters read will be returned as the value of the function. Global variables BUFP and LEN will contain the address of the input line, and the LENgth of the line, respectively. Global variables BUFE and IBUF are used by the routine, and should not be used by the users program. */ #define IBUFSZ 512 char IBUF[513]; /* internal data buffer */ char *BUFP = IBUF; /* User's data ptr */ char *BUFE = IBUF; /* Pointer to next loc in IBUF */ int LEN; /* Count of characters read */ int getlin(indev) int indev; { int i,j; if (indev == -1) {BUFP = IBUF; BUFE = IBUF; LEN = 0; return(-1); } start: /* Check if end of file has occurred */ if (BUFE < BUFP) goto reteof; /* Test if this is the first entry */ if (BUFE == IBUF) /* Buffer is empty--reset buffer pointer*/ /* and read an entire buffer of data */ {BUFP = IBUF; LEN = read(indev,BUFP,IBUFSZ); /* Test for error or end of file */ if (LEN < 1) { reteof: LEN = 0; *BUFP = 0; /* Set BUFE ptr to indicate EOF */ BUFE = BUFP - 1; return(0); } /* Mark end of buffer with null byte */ BUFP[LEN] = 0; } /* Buffer contains data. Search for */ /* another input line */ else BUFP = BUFE; /**************************************************************** SEARCH FOR END OF LINE --- OR END OF BUFFER ****************************************************************/ LEN = -1; /* end of buffer is mark by null byte */ findnl: while(BUFP[++LEN]) if (BUFP[LEN] == '\n') /* End of line found, return if this */ /* was not a blank line */ {BUFP[LEN] = 0; BUFE = &BUFP[LEN+1]; if (LEN) return(LEN); /* Blank line--ignore it */ else goto start; } /*************************************************************** BUFFER HAS BEEN SEARCHED FOR THE END OF LINE **************************************************************/ /* Test if the entire buffer is full */ /* If so, then this input line is */ /* longer than the buffer size IBUFSZ */ if (BUFP == IBUF) {LEN = -1; BUFE = IBUF; *IBUF = 0; /* Return negative value to indicate error*/ return(-1); } /* Move current line to beginning of buffer*/ /* and read rest of buffer input */ else { i = -1; j = -1; if (BUFP >= &IBUF[IBUFSZ]) {BUFE = IBUF; BUFP = IBUF; goto start;} while(IBUF[++i] = BUFP[++j]) ; BUFP = IBUF; j = IBUFSZ - i; LEN = read(indev,&BUFP[i],j); /* Test for EOF */ if (LEN < 1) {LEN = i; BUFE = IBUF - 1; return(i); } BUFP[LEN+i] = 0; /* Mark end */ LEN = -1; goto findnl; } }