[net.sources] mail & news archiver

oscar@utcsrgv.UUCP (Oscar M. Nierstrasz) (12/13/83)

Jack Waugh has pointed out to me that "echo -n" is understood
by Berkley UN*X only.  This flag prevents a carriage return from
being emitted.  It was used to make the shell script "mkarc"
more readable.  To fix simply replace:

echo -n "sed 's/^	//' > $i << "
echo "'All work and no play makes Jack a dull boy'"

by

echo "sed 's/^	//' > $i << 'All work and no play makes Jack a dull boy'"
-- 

UUCP:	{ allegra cornell decvax decwrl floyd ihnp4 linus
	  sask ubc-vision utzoo uw-beaver watmath } !utcsrgv!oscar

brad@bradley.UUCP (12/22/83)

#R:utcsrgv:-293100:bradley:3800005:000:64
bradley!brad    Dec 17 12:14:00 1983


We run DEC V7m2.1 here and 'echo -n' works here

Bradley Smith

chip@t4test.UUCP (Chip Rosenthal) (05/20/84)

I noticed a followup article on mail and news archiving, but missed the
original.  On the oft chance that it was a request for such a program,
I am posting "archive".  Included is a manual page.  While archive is
really useful for news articles, it is of marginal use for mail.  This
is for two reasons.  First, our mail interface doesn't have anything
like the "s |" command which our readnews does.  Secondly, archive
stores the articles catagorically by looking at the newsgroup.  Mail
messages don't offer any nice hooks like groups to allow this automatic
catagorization. 

To make archive:

1) extract the "shar-format" script below.  Don't forget the signature.
2) run it through sh.
3) cc archive.c
4) nroff -man archive.l


----------------- tear here -------------------------------------------------
echo 'extracting archive.c (file 1 of 2)'
cat > archive.c << '!!FUNKY-STUFF'
#include <stdio.h>
#define FALSE 0
#define TRUE 1
#define DEFAULT_arch_dir "NEWSARCHIVE"
#define USAGE_ERROR "Usage:  %s [-g group] [-f file] [-o] [-s subject]\n"
#define SUBJECT_LENGTH 60

main(argc, argv)
int argc;
char *argv[];
{
  FILE *tempfp, *outfp;
  char *tempfile="/tmp/archXXXXXX";
  char *outfile="";
  char *archgroup="", *archdir="", *today="";
  char subject[SUBJECT_LENGTH];
  int fswitch, gswitch, sswitch, oswitch;
  long timenow;

  int i;
  char *line, *c;

  FILE *fopen();
  char *strclone();
  char *mktemp(), *getenv(), *malloc(), *fgets(), *ctime();
  char *strcpy(), *strcat();
  long time();

  line=malloc(999);

  /**********************************************************************/
  /*                                                                    */
  /*  Set the date                                                      */
  /*                                                                    */
  /**********************************************************************/
  timenow=time(0);
  today=ctime(&timenow);

#ifdef DEBUG
  fprintf(stderr,"%s:  date set to %s",argv[0],today);
#endif

  /**********************************************************************/
  /*                                                                    */
  /*  Decode invocation switches                                        */
  /*                                                                    */
  /**********************************************************************/

  fswitch=FALSE;
  gswitch=FALSE;
  oswitch=FALSE;
  sswitch=FALSE;
  i=1;

  while (i<argc) {
    if (*argv[i] != '-') {
      fprintf(stderr,USAGE_ERROR,argv[0]);
      exit(1);
      }
    switch (*(argv[i]+1)) {
    case 'f':
      if (++i>=argc) {
	fprintf(stderr,USAGE_ERROR,argv[0]);
	exit(1);
	}
      fswitch=TRUE;
      outfile=strclone(argv[i]);
      break;
    case 'g':
      if (++i>=argc) {
	fprintf(stderr,USAGE_ERROR,argv[0]);
	exit(1);
	}
      gswitch=TRUE;
      archgroup=strclone(argv[i]);
      break;
    case 'o':
      oswitch=TRUE;
      break;
    case 's':
      sswitch=TRUE;
      strcpy(subject,"");
      ++i;
      while ( i<argc && *argv[i]!='-' ) {
	strncat(subject," ",SUBJECT_LENGTH);
	strncat(subject,argv[i],SUBJECT_LENGTH);
	++i;
	}
      --i;
      break;
    default:
      fprintf(stderr,USAGE_ERROR,argv[0]);
      exit(1);
      break;
      }
    ++i;
  }

#ifdef DEBUG
  fprintf(stderr,
    "%s:  argc=%d, fswitch=%d, gswitch=%d, oswitch=%d, sswitch=%d\n",
    argv[0],argc,fswitch,gswitch,oswitch,sswitch);
  if (fswitch) fprintf(stderr,"%s:  output file is %s\n",argv[0],outfile);
  if (gswitch) fprintf(stderr,"%s:  output group is %s\n",argv[0],archgroup);
  if (sswitch) fprintf(stderr,"%s:  subject is %s\n",argv[0],subject);
#endif

if ( (fswitch && gswitch) || (fswitch && oswitch) || (gswitch && oswitch) ) {
  fprintf(stderr,USAGE_ERROR,argv[0]);
  exit(1);
  }

  /**********************************************************************/
  /*                                                                    */
  /*  Dump from std input into temp file                                */
  /*                                                                    */
  /**********************************************************************/
  mktemp(tempfile);
  if ((tempfp=fopen(tempfile,"w")) == NULL) {
    fprintf(stderr,"%s:  can't create %s\n",argv[0],tempfile);
    exit(1);
    }
  while ( (i=getc(stdin)) != EOF ) putc(i,tempfp);
  fclose(tempfp);
#ifdef DEBUG
  fprintf(stderr,"%s:  tempfile %s created\n",argv[0],tempfile);
#endif

  /**********************************************************************/
  /*                                                                    */
  /*  Determine output file name                                        */
  /*                                                                    */
  /**********************************************************************/
  if (gswitch) {
    if ( ! *(archdir=getenv(DEFAULT_arch_dir)) ) {
      fprintf(stderr,"%s:  %s undefined\n",argv[0],DEFAULT_arch_dir);
      exit(1);
      }
    sprintf((outfile=malloc(strlen(archdir)+strlen(archgroup)+2)),
      "%s/%s",archdir,archgroup);
    }

  else if (fswitch) ;

  else if (oswitch) {
    outfile="stdout";
    outfp=stdout;
    }

  else {

    if ( ! *(archdir=getenv(DEFAULT_arch_dir) )) {
      fprintf(stderr,"%s:  %s undefined\n",argv[0],DEFAULT_arch_dir);
      exit(1);
      }

    if ((tempfp = fopen(tempfile,"r")) == NULL) {
      fprintf(stderr,"%s:  can't access %s\n",argv[0],tempfile);
      exit(1);
      }
    re_comp("^Newsgroups: ");
    for ( c=fgets(line,999,tempfp) ;
      c!=NULL && re_exec(line)!=1 ;
      c=fgets(line,999,tempfp) )
      ;

    if (re_exec(line)==1) {
      c=line;
      while ( *(c++)!=' ' ) ;
      while ( *(c++)==' ' ) ;
      while ( *c!=' ' && *c!=',' ) ++c;
      *c='\0';
      c=line; 
      while ( *(c++)!=' ' ) ;
      while ( *c==' ' ) ++c;
      archgroup=strclone(c);
    }
    else {
      fprintf(stderr,"%s:  no group found\n",argv[0]);
      exit(1);
      }

    fclose(tempfp);
    sprintf((outfile=malloc(strlen(archdir)+strlen(archgroup)+2)),
      "%s/%s",archdir,archgroup);
    }

  if (! oswitch) {
    trim(outfile);
    if ( (outfp=fopen(outfile,"a")) == NULL ) {
      fprintf(stderr,"%s:  can't access %s\n",argv[0],outfile);
      exit(1);
      }
    fprintf(stderr,"archiving article in %s\n",outfile);
    }
  fprintf(outfp,"\n\n");

#ifdef DEBUG
  fprintf(stderr,"%s:  output file is %s\n",argv[0],outfile);
#endif


  /**********************************************************************/
  /*                                                                    */
  /*  Insert first line of header                                       */
  /*                                                                    */
  /**********************************************************************/
  if ((tempfp = fopen(tempfile,"r")) == NULL) {
    fprintf(stderr,"%s:  can't access %s\n",argv[0],tempfile);
    exit(1);
    }
  re_comp("^From ");
  for ( c=fgets(line,999,tempfp) ; 
    c!=NULL && re_exec(line)!=1 ;
    c=fgets(line,999,tempfp) )
    ;
  if (re_exec(line)==1) {
    c=line;
    while ( *(c)!=' ' ) ++c;
    while ( *(c)==' ' ) ++c; 
    while ( *(c)!=' ' ) ++c;
    --c;
    while ( *c!='!' && *c!=' ') --c;
    fprintf(outfp,"From %s",c+1);
  }
  else {
    fprintf(outfp,"From ???????? %s",today);
    fclose(tempfp);
    if ((tempfp = fopen(tempfile,"r")) == NULL) {
      fprintf(stderr,"%s:  can't access %s\n",argv[0],tempfile);
      exit(1);
      }
    }

  /**********************************************************************/
  /*                                                                    */
  /*  Insert second line of header                                      */
  /*                                                                    */
  /**********************************************************************/
  if (sswitch) 
    fprintf(outfp,"Subject:%s\n",subject);
  else {
    re_comp("^Subject: ");
    for ( c=fgets(line,999,tempfp) ;
      c!=NULL && re_exec(line)!=1 ;
      c=fgets(line,999,tempfp) )
      ;
    if (re_exec(line)==1) fprintf(outfp,"%s",line);
    else fprintf(outfp,"Subject: article without subject\n");
    }
  fclose(tempfp);

  /**********************************************************************/
  /*                                                                    */
  /*  Insert third line of header                                       */
  /*                                                                    */
  /**********************************************************************/
  fprintf(outfp,"Date-Archived: %s",today);

  /**********************************************************************/
  /*                                                                    */
  /*  Output article -- add mark to first paragraph                     */
  /*                                                                    */
  /**********************************************************************/
  if ((tempfp = fopen(tempfile,"r")) == NULL) {
    fprintf(stderr,"%s:  can't access %s\n",argv[0],tempfile);
    exit(1);
    }
  i=TRUE;
  while (fgets(line,999,tempfp)!=NULL) {
    if (i) {
      c=line;
      while (*c==' ') ++c;
      if (*c=='\n' || *c=='\0') i=FALSE;
    }
    if (i) putc('>',outfp);
    fprintf(outfp,"%s",line);
  }
  fclose(outfp);
  fclose(tempfp);
  unlink(tempfile);
#ifdef DEBUG
  fprintf(stderr,"%s:  completed\n\n",argv[0]);
#endif
}

/**********************************************************************/

char *strclone(point)
char *point;
{
  char *p,*malloc();
  strcpy((p=malloc(strlen(point)+1)),point);
  return(p);
  }

trim(s)
char *s;
{
  while ( *s!='\n' && *s!='\0' && *s!=EOF ) ++s;
  *s='\0';
  }

!!FUNKY-STUFF
echo 'extracting archive.l (file 2 of 2)'
cat > archive.l << '!!FUNKY-STUFF'

.TH ARCHIVE 1L 4/18/84
.UC
.SH NAME
archive \- archive USENET articles 
.SH SYNOPSIS
.B archive 
[ 
.B \-g
archgroup ] [ 
.B \-f
archfile ] [ 
.B \-o
] [
.B \-s
subject ]
.SH DESCRIPTION
.PP
.I Archive
is used to save USENET articles in an archive for future reference.
These articles may be accessed with the "mail -f" command.  
.I Archive
reads in the article from the standard input, and then stores it
directly into an archive file.  
It is generally used by responding
to the readnews "more [ynq] ?" prompt with "s\ |\ archive".
.PP
The directory in which the archived article is placed (that is, 
the default archives directory) is defined by the value of
the ARCHIVES environment parameter.  
The default file to which the article is
archived is defined by the newsgroup to which the article
was posted.  If an article has been posted to multiple newsgroups,
the archive file will be specified by the first newsgroup listed.
Options are available to overide the defaults and
specify where to archive the article.  No more than one of
these options may be specified at a time.  They include:
.TP 8
.B \-g
The posted newsgroup is ignored, and instead the article is
archived to a file called 
.I archgroup
within the default archives directory.
.br
.TP 8
.B \-f
Both the posted newsgroup and the ARCHIVES parameter are ignored,
and instead the article is archived to 
.I archfile\.
.br
.TP 8
.B \-o
The article is sent to the standard output.
.PP
The archived article is given a subject which is readable by
.I mail.
By default, the subject is the one by which the article was
posted.  The
.B \-s
option is used to change this subject title to
.I subject.
.SH FILES
/tmp/arch*
.SH SEE ALSO
mail(1)
.br
readnews(1)
.SH BUGS
.PP
If
.I archive
can't figure out the article's subject or author, it will indicate
so in the header of the archived article.  If 
.I archive
can't figure out the appropriate location for archiving (e.g. 
.I setenv
hasn't been placed in the user's
.I .cshrc
file to define the ARCHIVES parameter)
then it abort with an error message.
.PP
No method is provided to manage and manipulate articles once
archived, other than those provided through the 
.I mail 
program.
.SH AUTHOR
Chip Rosenthal 
.br
intelca!t4test!chip
.br
SC4-457
.br
x6-7651
!!FUNKY-STUFF
-- 
        Chip Rosenthal, Intel/Santa Clara
 GNUS:  {pur-ee|hplabs|ucbvax!amd70|ogcvax!omsvax}!intelca!t4test!{chip|news}
MAYUL:  {intelca|icalqa|qubix|idi}!t4test!{chip|news}