/*
** This software is Copyright (c) 1989, 1990, 1991 by Kent Landfield.
**
** Permission is hereby granted to copy, distribute or otherwise 
** use any part of this package as long as you do not try to make 
** money from it or pretend that you wrote it.  This copyright 
** notice must be maintained in any copy made.
**
*/
#if !defined(lint) && !defined(SABER)
static char SID[] = "@(#)format.c	2.3 5/9/91";
#endif

#include <stdio.h>
#include <sys/types.h>
#include "article.h"
#include "rkive.h"

int strlen();

extern FILE *errfp;
extern struct group_archive *newsgrp;

#ifdef RKIVE
  extern char *config_file;
  extern char problems_dir[];
  extern char spooldir[];
  extern char compress[];
  extern char log[];
  extern char log_format[];
  extern char mindex[];
  extern char index_format[];
  extern char mail[];
  extern char checkhash[];
  extern char arch_command[];
  extern int default_type;
  extern int default_patch_type;
  extern int default_owner;
  extern int default_group;
  extern int default_modes;
# ifdef NNTP
    extern char nntp[];
    extern char nntp_tmp_path[];
# endif /*NNTP*/
#endif /* RKIVE */


/*
** substr:
**
** substr(str, substr) returns a pointer to the first place in
** str where the substring substr occurs, or NULL if substr does
** not occur in str.
**
** char *substr(str, substr) char *str, *substr; { return (str); }
*/

char *substr(from, find)
    char *from, *find;
{
    int strncmp();
    char *strchr();

    register char *sp, *np;
    register int len;

    np = from;
    len = strlen(find);

    while ((sp = strchr(np,*find)) != NULL) {
        if (strlen(sp) < len)
            break;
        if (strncmp(sp,find,len) == 0) 
            return(sp);
        np = sp + 1;
    }
    return(NULL);
}

char *itoa(n)
int n;
{
    static char str[20];

    int i, c, j, sign;
	
    if ((sign = n) < 0) 
	n = -n;

    i = 0;
    do {
        str[i++] = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (sign < 0)
        str[i++] = '-';
    str[i] = '\0';

    for (i = 0, j = strlen(str)-1; i < j; i++,j--) {
        c = str[i];
        str[i] = str[j];
        str[j] = c;
    }
    return(str);
}

char *add_string(ptr, member_str)
char *ptr, *member_str;
{
    while(*member_str)
        *ptr++ = *member_str++;
    return(ptr);
}


char *basename(name)
    char *name;
{
    char *p;
    char *strrchr();
    
    if ((p = strrchr(name,'/')) == NULL)
        return(name);
    return(++p);
}


char *format_output(frmptr, filename, called_from)
char *frmptr;          /* Selection Format pointer              */
char *filename;        /* File name the info came from          */
int called_from;       /* Where called from, Rkive or Article   */
{
    char *basename();

    static char format[4*BUFSIZ];
    register char *aptr;
    register char *cp;
    char c;
 
    /* Did the user specify a format to use   */
    /* or should the default format be used ? */

    if (frmptr == NULL) {
       if (called_from == ARCHIVE) 
           (void) sprintf(format,"%-s\t%-s\t%s",
                 article.newsarticle, header.archive_name,
                 article.description);
       else
           (void) sprintf(format,"%-s\t%-s", filename, header.subject);
       return(format);
    }

    for (cp = format; cp < format + sizeof(format); cp++)
         *cp = '\0';
 
    aptr = frmptr;
    cp = format;

    while ((c = *aptr++)) {
        if (c == '%') {
           switch (*aptr++) {
               case '%':
                   *cp++ = '%';
                   continue;
               case 'A':     /* Approved  */
                   cp = add_string(cp, header.approved);
                   continue;
               case 'B':     /* Base name of the file path  */
                   cp = add_string(cp, basename(filename));
                   continue;
               case 'C':     /* Control  */
                   cp = add_string(cp, header.ctlmsg);
                   continue;
               case 'D':     /* Date */
                   cp = add_string(cp, header.subdate);
                   continue;
               case 'E':     /* Reposted-by */
                   cp = add_string(cp, header.reposter);
                   continue;
               case 'F':     /* From */
                   cp = add_string(cp, header.from);
                   continue;
               case 'G':     /* newGroups disk location */
                   /*
                   ** The newsgroup selected and displayed is the first
                   ** newsgroup encountered unless the calling routine 
                   ** is rkive. This is necessary to support rkive's
                   ** needs when the newsgroup is known ahead of time
                   ** and article's need to display just what the news article
                   ** contains. If this is not done then the index information
                   ** mailed to the specified users may display a crossposted
                   ** newsgroup as an information line. KLUDGE ALERT!!!
                   */
                   if (called_from == ARCHIVE) 
                       cp = add_string(cp, newsgrp->ng_name);
                   else
                       cp = add_string(cp, article.newsgroup);
                   continue;
               case 'H':     /* Original-posting-by */
                   cp = add_string(cp, header.orig_poster);
                   continue;
               case 'I':     /* Original-subject */
                   cp = add_string(cp, header.orig_subject);
                   continue;
               case 'J':     /* Archive-directory */
                   cp = add_string(cp, header.archive_dir);
                   continue;
               case 'K':     /* Keywords  */
                   cp = add_string(cp, header.keywords);
                   continue;
               case 'L':     /* Lines */
                   cp = add_string(cp, header.numlines);
                   continue;
               case 'M':     /* Message-ID */
                   cp = add_string(cp, header.ident);
                   continue;
               case 'N':     /* Newsgroups */
                   cp = add_string(cp, header.nbuf);
                   continue;
               case 'O':     /* Actual Archived filename */
                   cp = add_string(cp, filename);
                   continue;
               case 'P':     /* Path */
                   cp = add_string(cp, header.path);
                   continue;
               case 'Q':     /* Expires  */
                   cp = add_string(cp, header.expdate);
                   continue;
               case 'R':     /* References */
                   cp = add_string(cp, header.references);
                   continue;
               case 'S':     /* Subject */
                   cp = add_string(cp, header.subject);
                   continue;
               case 'T':     /* Subject Topic */
                   cp = add_string(cp, article.description);
                   continue;
               case 'V':     /* Volume-Issue article filename  */
                   cp = add_string(cp, article.filename);
                   continue;
               case 'W':     /* Architecture */
                   cp = add_string(cp, header.architecture);
                   continue;
               case 'X':     /* Version-number */
                   cp = add_string(cp, header.version_number);
                   continue;
#ifdef RKIVE
               case 'Z':   /*  Relative pathname of archived file */
                   cp = add_string(cp,substr(filename,newsgrp->location)?filename+strlen(newsgrp->location)+1:filename);
                   continue;
#endif
               case 'a':     /* Archive-name */
                   cp = add_string(cp, header.archive_name);
                   continue;
               case 'b':     /* Submitted-by */
                   cp = add_string(cp, header.submitted_by);
                   continue;
               case 'c':     /* Supersedes  */
                   cp = add_string(cp, header.supersedes);
                   continue;
               case 'd':     /* Distribution  */
                   cp = add_string(cp, header.distribution);
                   continue;
               case 'e':     /* Environment  */
                   cp = add_string(cp, header.environment);
                   continue;
               case 'f':     /* Followup-to  */
                   cp = add_string(cp, header.followup_to);
                   continue;
               case 'h':     /* X-Checksum-Snefru or X-Md4-Signature */
                   cp = add_string(cp, header.x_checksum);
                   continue;
               case 'i':     /* issue (if archive) */
                   cp = add_string(cp,itoa(article.issue));
                   continue;
               case 'l':     /* Author's logon address */
                   cp = add_string(cp, article.author_signon);
                   continue;
               case 'n':     /* Author's name */
                   cp = add_string(cp, article.author_name);
                   continue;
               case 'o':     /* Organization */
                   cp = add_string(cp, header.organization);
                   continue;
               case 'p':     /* Posting-number */
                   cp = add_string(cp, header.posting_num);
                   continue;
               case 'r':     /* Reply-to */
                   cp = add_string(cp, header.replyto);
                   continue;
               case 's':     /* Sender  */
                   cp = add_string(cp, header.sender);
                   continue;
               case 't':     /* Patch-To  */
                   cp = add_string(cp, header.patch_to);
                   continue;
               case 'u':     /* Summary */
                   cp = add_string(cp, header.summary);
                   continue;
               case 'v':     /* volume (if archive) */
                   cp = add_string(cp,itoa(article.volume));
                   continue;
               case 'w':     /* Archive-site */
                   cp = add_string(cp,header.archive_site);
                   continue;
               case 'x':     /* Xref */
                   cp = add_string(cp, header.xref);
                   continue;
	       case 'y':     /* Archive */
		   cp = add_string(cp, header.archive);
		   continue;
               default:
                  (void) fprintf(errfp, "invalid format - %c\n", *--aptr);
                  exit(2);
           }    /* end switch */
        }
        else if (c == '\134') {
           switch (*aptr++) {
               case 'n':
                   *cp++ = '\n';
                   continue;
               case 't':
                   *cp++ = '\t';
                   continue;
           }
        }

#ifdef RKIVE
        else if (c == '$') {
           switch (*aptr++) {
               /*
               **  The GLOBAL information 
               */
               case 'B':     /* BASEDIR */
                   cp = add_string(cp,newsgrp->location);
                   continue;
               case 'E':     /* PROBLEMS - errors */
                   cp = add_string(cp,problems_dir);
                   continue;
               case 'I':     /* INDEX */
                   cp = add_string(cp, mindex);
                   continue;
               case 'J':     /* INDEX_FORMAT */
                   cp = add_string(cp, index_format);
                   continue;
               case 'K':     /* LOG_FORMAT */
                   cp = add_string(cp, log_format);
                   continue;
               case 'L':     /* LOG */
                   cp = add_string(cp, log);
                   continue;
               case 'P':     /* actual disk path to file to archive */
                   cp = add_string(cp,spooldir);
                   cp = add_string(cp,"/");
                   cp = add_string(cp,newsgrp->ng_path);
                   cp = add_string(cp,"/");
                   cp = add_string(cp, basename(filename));
                   continue;
               case 'S':     /* SPOOLDIR */
                   cp = add_string(cp,spooldir);
                   continue;
		case 'U':     /* MAIL - users */
                   cp = add_string(cp,mail);
                   continue;
               /*
               **  Now the newgroup specific information 
               */
               case 'a':     /* newsgroup's .archived file path */
                   cp = add_string(cp, newsgrp->arc_done);
                   continue;
               case 'b':     /* newsgroup's spool directory */
                   cp = add_string(cp, newsgrp->ng_path);
                   continue;
               case 'c':     /* COMPRESS: */
                   if (*newsgrp->compress)
                       cp = add_string(cp, newsgrp->compress);
                   else
                       cp = add_string(cp, compress);
                   continue;
               case 'g':     /* GROUP: */
                   cp = add_string(cp,itoa(newsgrp->group));
                   continue;
               case 'h':     /* CHECKHASH: */
                   if (*newsgrp->checkhash)
                       cp = add_string(cp, newsgrp->checkhash);
                   else
                       cp = add_string(cp, checkhash);
                   continue;
               case 'i':     /* INDEX: */
                   cp = add_string(cp, newsgrp->index);
                   continue;
               case 'j':     /* INDEX_FORMAT: */
                   cp = add_string(cp, "'");
                   cp = add_string(cp, newsgrp->indformat);
                   cp = add_string(cp, "'");
                   continue;
               case 'k':     /* LOG_FORMAT: */
                   cp = add_string(cp, "'");
                   cp = add_string(cp, newsgrp->logformat);
                   cp = add_string(cp, "'");
                   continue;
               case 'l':     /* LOG: */
                   cp = add_string(cp, newsgrp->logfile);
                   continue;
               case 'm':     /* MODE: */
                   {
                     char octal_str[20];
                     (void) sprintf(octal_str,"%o",newsgrp->modes);
                     cp = add_string(cp,octal_str);
                     continue;
                   }
               case 'n':     /* $$newsgroup name */
                   cp = add_string(cp,newsgrp->ng_name);
                   continue;
               case 'o':     /* OWNER: */
                   cp = add_string(cp,itoa(newsgrp->owner));
                   continue;
               case 'p':     /* PATCHES: */
                   if (newsgrp->patch_type == PACKAGE)
                       cp = add_string(cp, "Package");
                   else
                       cp = add_string(cp, "Historical");
                   continue;
                case 'u':     /* MAIL: - users */
                   cp = add_string(cp,newsgrp->mail_list);
                   continue;
#ifdef NNTP
               case 'F':     /* NNTP Temporary transfer file */
                   cp = add_string(cp,nntp_tmp_path);
                   continue;
               case 'N':     /* NNTP */
                   /* print out according to precedence. */
                   if (*newsgrp->nntp)
                       cp = add_string(cp,newsgrp->nntp);
                   else if (*nntp)
                       cp = add_string(cp,nntp);
                   continue;
#endif /* NNTP */
               default:
                  (void) fprintf(errfp, "invalid format - %c\n", *--aptr);
                  exit(2);
           }
        }
#endif /* RKIVE */

        *cp++ = c;
     }  /* end while */
     return(format);
}
