home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / yapp / part04 / sep.c < prev   
C/C++ Source or Header  |  1994-05-29  |  22KB  |  607 lines

  1. /* SEP.C */
  2. static    char sccsid[] = "@(#)sep.c 1.19 93/06/06 Copyright (c)1993 thalerd";
  3. /* This module takes care of most of the fancy output, and allows
  4.  * users and administrators to completely customize the output
  5.  * of many functions.  A "separator" string is passed to confsep
  6.  * or itemsep, which break it up and generate output based on the
  7.  * codes therein.  For more information, do "help separators"
  8.  * from within the program.
  9.  */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <ctype.h>
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include "config.h"
  16. time_t time PROTO((time_t *tloc));
  17. #include "struct.h"
  18. #include "item.h"
  19. #include "range.h"
  20. #include "globals.h"
  21. #include "sep.h"
  22. #include "change.h" /* to get CF_PUBLIC */
  23. #include "lib.h"
  24. #include "sum.h"    /* to get SF_FAST */
  25. #include "macro.h"
  26. #include "xalloc.h"
  27. #include "main.h"
  28. #include "news.h"
  29. #include "stats.h"
  30.  
  31. static char *lchars="ntvbrface";
  32. static char *rchars="\n\t\v\b\r\f\007\377\033";
  33. static int lastnum=0,show[100],depth = 0,num=0,tabs=1;
  34. static int newline,qfail,once,zero;
  35. static char buff[MAX_LINE_LENGTH];
  36. extern char *cfiles[];
  37.  
  38. /******************************************************************************/
  39. /* OUTPUT A STRING TO THE DESIRED FORMAT                                      */
  40. /******************************************************************************/
  41. static void                    /* RETURNS: (nothing)           */
  42. string(b,fp)                   /* ARGUMENTS:                   */
  43. char *b;                       /*    String to output          */
  44. FILE *fp;                      /*    File pointer to output to */
  45. {                              /* LOCAL VARIABLES:             */
  46.    char fmt[MAX_LINE_LENGTH];  /*    Format string             */
  47.    char buff[MAX_LINE_LENGTH]; /*    Formatted output          */
  48.  
  49.    if (!show[depth]) return;
  50.    if (num)
  51.       sprintf(fmt,"%%%ds",num);
  52.    else
  53.       strcpy(fmt,"%s");
  54.    sprintf(buff,fmt,b);
  55.    wfputs(buff,fp);
  56. }
  57.  
  58. /******************************************************************************/
  59. /* OUTPUT A NUMBER TO THE DESIRED FORMAT                                      */
  60. /******************************************************************************/
  61. static void  /* RETURNS: (nothing)   */
  62. number(b,fp) /* ARGUMENTS:           */
  63. short b;     /*    Number to output  */
  64. FILE *fp;    /*    Stream to send to */
  65. {
  66.    char fmt[MAX_LINE_LENGTH];
  67.  
  68.    if (!show[depth]) return;
  69.    if (num)
  70.       sprintf(fmt,"%%%dd",num);
  71.    else
  72.       strcpy(fmt,"%d");
  73.    if (!b && zero)
  74.       sprintf(buff,"%co",("nN")[zero-1]);
  75.    else
  76.       sprintf(buff,fmt,b);
  77.    wfputs(buff,fp);
  78.    lastnum=b;
  79. }
  80.  
  81. /******************************************************************************/
  82. /* PROCESS CONDITIONS FOR BOTH ITEM/CONF SEPS                                 */
  83. /******************************************************************************/
  84. static char   /* RETURNS: 1 on true, 0 on false */
  85. misccond(spp) /* ARGUMENTS: */
  86. char **spp;   /*    Separator string */
  87. {
  88.    char *sp,ret=0;
  89.    sp = *spp;
  90.    
  91.    switch(*(sp++)) {
  92.    case 'P': ret=(lastnum!=1); break;
  93.    default: ret=0; break; /* don't show */
  94.    }
  95.  
  96.    *spp = sp;
  97.    return ret;
  98. }
  99.  
  100. /******************************************************************************/
  101. /* PROCESS SEPS FOR BOTH ITEM/CONF SEPS                                       */
  102. /******************************************************************************/
  103. void            /* RETURNS: (nothing) */
  104. miscsep(spp,fp) /* ARGUMENTS: */
  105. char **spp;     /*    Separator string */
  106. FILE *fp;       /*    Stream to send to */
  107. {
  108.    char *sp;
  109.    short i;
  110.    sp = *spp;
  111.  
  112.    switch(*(sp++)) {
  113.  
  114.    /* Customization separators */
  115.    case '%': string("%",fp); break;
  116.    case 'E': if (!depth || show[depth-1]) show[depth]= !show[depth]; break;
  117.    case 'c': newline=0; break;
  118.    case 'S': if (lastnum!=1) string("s",fp); break;
  119.    case 'T': tabs=num; break;
  120.    case 'X': for (i=0; i<tabs; i++) 
  121.                 if (show[depth]) wfputc(' ',fp); 
  122.              break;
  123.    case ')': 
  124. /*
  125. for (i=0; i<depth; i++) printf("   ");
  126. printf("---\n");
  127. */
  128.              depth--; break;
  129.    case 'D': if (show[depth]) wfputs(get_date(time((time_t*)0),num),fp); break;
  130.  
  131.    default:  break; /* do nothing */
  132.    }
  133.  
  134.    *spp = sp;
  135. }
  136.  
  137. /******************************************************************************/
  138. /* PROCESS CONDITIONS FOR ITEM SEPS ONLY                                      */
  139. /******************************************************************************/
  140. char             /* RETURNS: 1 true, 0 false */
  141. itemcond(spp,fl) /* ARGUMENTS:               */
  142. char **spp;      /*    Separator string      */
  143. long  fl;        /*    Sep flags             */
  144. {
  145.    char *sp,ret=0,not=0;
  146.    response_t *cre;
  147.  
  148.    sp = *spp;
  149.    cre = &(re[st_glob.r_current]);
  150.  
  151.    if (*sp=='!' || *sp=='~') { not = !not; sp++; }
  152.    for (num=0; isdigit(*sp); sp++) num= num*10+(*sp-'0'); 
  153.    
  154.    switch(*(sp++)) {
  155.    case 'T': ret=((fl & OF_FORMFEED)>0); break;
  156.    case 'E': ret=(( cre->flags & RF_EXPIRED)>0); break;
  157.    case 'V': ret=(( cre->flags & RF_CENSORED)>0); break;
  158.    case 'W': ret=(( cre->flags & RF_SCRIBBLED)>0); break;
  159.    case 'X': ret=((sum[st_glob.i_current-1].flags & IF_RETIRED)>0); 
  160.              once &= ~IS_RETIRED;
  161.              break;
  162.    case 'Y': ret=((sum[st_glob.i_current-1].flags & IF_FORGOTTEN)>0); 
  163.              once &= ~IS_FORGOTTEN;
  164.              break;
  165.    case 'Z': ret=((sum[st_glob.i_current-1].flags & IF_FROZEN)>0); 
  166.              once &= ~IS_FROZEN;
  167.              break;
  168.    case 'R': ret=((once & (IS_ITEM|IS_RESP))>0);  
  169.              once&= ~(IS_ITEM|IS_RESP);  
  170. /*
  171.              ret= ((!part[st_glob.i_current-1].nr && sum[st_glob.i_current-1].nr) 
  172.                  || (part[st_glob.i_current-1].nr  < sum[st_glob.i_current-1].nr));
  173. */
  174.              break;
  175.    case 'F': ret=((fl & OF_NUMBERED) || (flags & O_NUMBERED)); break;
  176.    case 'D': ret=((once & IS_DATE)>0); break;
  177.    case 'U': ret=((once & IS_UID)>0); break;
  178.    case 'L': ret=(st_glob.l_current>=0 && cre->text 
  179.               &&  st_glob.l_current<xsizeof(cre->text)
  180.               &&  cre->text[st_glob.l_current]); break;
  181.    case 'I': /* ret= (!part[st_glob.i_current-1].nr && sum[st_glob.i_current-1].nr); 
  182.              break; fall through into O */
  183.    case 'O': ret=((once & IS_ITEM)>0);  once&= ~IS_ITEM;  break;
  184.    case 'B': ret=((once & IS_START)>0); once&= ~IS_START; break;
  185.    case 'N': ret=(st_glob.r_current>0); 
  186. /*           ret= (!(!part[st_glob.i_current-1].nr && sum[st_glob.i_current-1].nr) 
  187.                   && (part[st_glob.i_current-1].nr  < sum[st_glob.i_current-1].nr));
  188. */
  189.              break;
  190.    case 'p': once &= ~IS_PARENT;
  191.              ret=(cre->parent>0); break;
  192.    case 'x': ret= (once & num); /* once &= ~num; */ break;
  193.    default: return misccond(spp);
  194.    }
  195.  
  196.    *spp = sp;
  197.    if (!show[depth]) return 0;
  198.    return ret^not;
  199. }
  200.  
  201. /******************************************************************************/
  202. /* PROCESS SEPS FOR ITEM SEPS ONLY                                            */
  203. /* This works only for the current conference                                 */
  204. /******************************************************************************/
  205. void                /* RETURNS: (nothing) */
  206. itemsep2(spp,fl,fp) /* ARGUMENTS: */
  207. char **spp;         /*    Separator string */
  208. long *fl;           /*    Flags (see sep.h) */
  209. FILE *fp;           /*    Stream to output to */
  210. {
  211.    char *sp;
  212.    char *sub,neg=0;
  213.    response_t *cre;
  214.    char subbuf[MAX_LINE_LENGTH];
  215.  
  216.    cre = &(re[st_glob.r_current]);
  217.    sp = *spp;
  218.    buff[0]=0;
  219.    num=0;
  220.  
  221.    /* Get number */
  222.    zero=0;
  223.    if (*sp == 'z') { zero=1; sp++; }
  224.    else if (*sp == 'Z') { zero=2; sp++; }
  225.    if (*sp == '-') { neg=1; sp++; }
  226.    while (isdigit(*sp)) { num= num*10+(*sp-'0'); sp++; }
  227.    if (neg) num = -num;
  228.  
  229.    switch(*(sp++)) {
  230.  
  231.    /* Item Function Codes */
  232.    case 'a': string(cre->fullname,fp);    break;
  233.    case 'C': if (confidx>=0) string(compress(conflist[confidx].name),fp); break;
  234.    case 'h': string(get_subj(confidx,st_glob.i_current-1,sum),fp);       break;
  235.    case 'i': number(st_glob.i_current,fp); break;
  236.    case 'l': string(cre->login,fp);       break;
  237.    case 'L': string(cre->text[st_glob.l_current],fp); break;
  238. #ifdef NEWS
  239.    case 'm': string(message_id(compress(conflist[confidx].name),
  240.            st_glob.i_current,st_glob.r_current,re),fp); break;
  241. #endif
  242.    case 'n': number(sum[st_glob.i_current-1].nr - 1,fp);     break;
  243.    case 'N': number(st_glob.l_current+1,fp); break;
  244.    case 'r': number(st_glob.r_current,fp); break;
  245.    case 's': number((cre->flags & (RF_SCRIBBLED|RF_EXPIRED))? 0 : xsizeof(cre->text),fp); 
  246.              break;
  247.    case 'k': number((cre->numchars+1023)/1024,fp); break;
  248.    case 'q': number(cre->numchars,fp); break;
  249.    case 'K': /* KKK */ break;
  250.    case 'Q': /* KKK */ break;
  251.    case 'u': number((short)cre->uid,fp); 
  252.              /* *fl &= ~OF_UID; */
  253.              once &= ~IS_UID; break;
  254.    case 'd': if (show[depth]) wfputs(get_date(cre->date,num?num:1),fp); 
  255.              /* *fl &= ~OF_DATE; */
  256.              once &= ~IS_DATE; break;
  257.    case 't': if (show[depth]) wfputs(get_date(cre->date,num),fp); 
  258.              /* *fl &= ~OF_DATE; */
  259.              once &= ~IS_DATE; break;
  260.    case 'p': number((short)cre->parent,fp); once&=~IS_PARENT; break;
  261.    case '<': for (sub=subbuf; *sp && *sp!='>'; sp++,sub++) *sub = *sp;
  262.              sp++;
  263.              (*sub)='\0';
  264.              itemsep(subbuf,1);
  265.              break;
  266.    case '{': for (sub=subbuf; *sp && *sp!='}'; sp++,sub++) *sub = *sp;
  267.              sp++;
  268.              (*sub)='\0';
  269.              itemsep(subbuf,1);
  270.              break;
  271.    case '(': show[depth+1]=itemcond(&sp,*fl); 
  272.              depth++;
  273.              break; /* ) */
  274.    
  275.    default:  *spp=sp-1; miscsep(spp,fp);
  276.    }
  277.  
  278.    *spp = sp;
  279. }
  280.  
  281. /******************************************************************************/
  282. /* PROCESS CONDITIONS FOR CONF SEPS ONLY                                      */
  283. /******************************************************************************/
  284. char              /* RETURNS: 1 true, 0 false */
  285. confcond(spp,idx,st) /* ARGUMENTS:          */
  286. char **spp;       /*    Separator string */
  287. short idx;        /*    Conference index */
  288. status_t *st;
  289. {
  290.    char buff[MAX_LINE_LENGTH];
  291.    struct stat stt;
  292.    char *sp,ret=0,not=0;
  293.  
  294.    sp = *spp;
  295.  
  296.    if (*sp=='!' || *sp=='~') { not = !not; sp++; }
  297.    for (num=0; isdigit(*sp); sp++) num= num*10+(*sp-'0'); 
  298. /*
  299. int i;
  300. for (i=0; i<depth; i++) printf("   ");
  301. printf("%1d: %c ",i,*sp);
  302. */
  303.    switch(*(sp++)) {
  304.    case 'y': lastnum=st->i_unseen; ret=lastnum; break;
  305.    case 'n': lastnum=st->i_brandnew+st->i_newresp; ret= lastnum; break;
  306.    case 'b': lastnum=st->i_brandnew; ret= lastnum; break;
  307.    case 'r': lastnum=st->i_newresp; ret= lastnum; break;
  308.    case 'm': ret= (status & S_MAIL);  break;
  309.    case 'x': ret= (once & num); /* once &= ~num; */ break;
  310.    case 'N': if (num>=0 && num<CF_PUBLIC && idx>=0) {
  311.                 sprintf(buff,"%s/%s",conflist[idx].location,compress(cfiles[num]));
  312.                 if (stat(buff,&stt) || stt.st_size<=0) ret=0;
  313.                 else if (st->c_status & CS_JUSTJOINED) ret=1;
  314.                 else ret=(stt.st_mtime > st->parttime);
  315.              }
  316.              break;
  317.    case 'F': if (num>=0 && num<CF_PUBLIC && idx>=0) {
  318.                 sprintf(buff,"%s/%s",conflist[idx].location,compress(cfiles[num]));
  319.                 ret=!stat(buff,&stt);
  320.              }
  321.              break;
  322.    case 'O': ret= (st->c_status & CS_OTHERCONF)?1:0; break;
  323.    case 'C': ret= (idx>=0); break;
  324.    case 'i': ret= (st->i_first<=st->i_last); break;
  325.    case 's': ret= (st->c_status & CS_FW); break;
  326.    case 'f': if (num>=0 && idx>=0) {
  327.                 sprintf(buff,"%s/sum",conflist[idx].location);
  328.                 ret = !stat(buff,&stt);
  329.              }
  330.              break;
  331.    case 'j': ret= (st->c_status & CS_JUSTJOINED)?1:0; break;
  332.    case 'l': ret= (st->c_status & CS_NORESPONSE); break;
  333.    case 'B': ret= (idx == confidx); break;
  334.    case 'k': ret= (once & IS_CFIDX); /* once &= ~IS_CFIDX; */ break;
  335.    default: return misccond(spp);
  336.    }
  337. /*
  338. printf("%d\n",ret);
  339. */
  340.    *spp = sp;
  341.    if (!show[depth]) return 0;
  342.    return ret^not;
  343. }
  344.  
  345. /******************************************************************************/
  346. /* PROCESS SEPS FOR CONF SEPS ONLY                                            */
  347. /******************************************************************************/
  348. void
  349. confsep2(spp,idx,st,part,fp) /* ARGUMENTS: */
  350. char **spp;               /*    Separator string */
  351. partentry_t *part;        /*    User participation info */
  352. short idx;                /*    Conference index */
  353. status_t *st;
  354. FILE *fp;                 /*    Stream to output to */
  355. {
  356.    char  *sp,*sub,*sh,*sh2,neg=0;
  357.    char   subbuf[MAX_LINE_LENGTH];
  358.    time_t t;
  359.     char **config;
  360.  
  361.    sp = *spp;
  362.    num=0;
  363.  
  364.    /* Get number */
  365.    zero=0;
  366.    if (*sp == 'z') { zero=1; sp++; }
  367.    else if (*sp == 'Z') { zero=2; sp++; }
  368.    if (*sp == '-') { neg=1; sp++; }
  369.    while (isdigit(*sp)) { num= num*10+(*sp-'0'); sp++; }
  370.    if (neg) num = -num;
  371.  
  372.    switch(*(sp++)) {
  373.  
  374.    /* Conference separators */
  375. #ifdef NEWS
  376.    case 'A': number(st->c_article, fp); break;
  377. #endif
  378.    case 'y': number(st->i_unseen,fp); break;
  379.    case 'n': number(st->i_brandnew+st->i_newresp,fp); break;
  380.    case 'b': number(st->i_brandnew,fp); break;
  381.    case 'r': number(st->i_newresp,fp); break;
  382.    case 'k': number(st->count,fp); break;
  383.    case 'u': string(st->fullname,fp); break;
  384.    case 'v': string(login,fp); break;
  385.    case 'w': string(work,fp); break;
  386.    case 'f': number(st->i_first,fp); break;
  387.    case 'l': number(st->i_last,fp); break;
  388.    case 'Q': if (idx<0) { string("Not in a conference!",fp); qfail=1; } break;
  389.    case 'i': number(st->i_numitems,fp); break;
  390.    case 't': number(st->c_security,fp); break;
  391.    case 's': if (idx>=0) string(compress(conflist[idx].name),fp); break;
  392.    case 'p': if (config = get_config(idx))
  393.                     string(config[CF_PARTFILE],fp); 
  394.                  break;
  395.    case 'd': if (idx>=0) string(conflist[idx].location,fp); break;
  396.    case 'q': if (idx>=0) {
  397.                 sh=conflist[idx].location;
  398.                 for (sh2=sh+strlen(sh)-1; sh2>=sh && *sh2!='/'; sh2--);
  399.                 string(sh2+1,fp);
  400.              }
  401.              break;
  402.    case 'o': if (show[depth]) wfputs(get_date(st->parttime,num),fp); break;
  403.    case 'm': /* NEW: lastmod of sum file, if any */
  404. /*
  405.              if (idx<0) t=0;
  406.              else {
  407.                 sprintf(buff,"%s/sum",conflist[idx].location);
  408.                 t= (stat(buff,&stt))? 0 : stt.st_mtime;
  409.              }
  410. */
  411.              t = st->sumtime;
  412.              if (show[depth]) wfputs(get_date(t,num),fp); 
  413.              break;
  414.    case 'g': if (num>=0 && num<CF_PUBLIC && show[depth] && idx>=0) 
  415.                 cat(conflist[idx].location,compress(cfiles[num]));
  416.              break; /* KKK later, redirect cat to fp? */
  417.    case '<': for (sub=subbuf; *sp && *sp!='>'; sp++,sub++) *sub = *sp;
  418.              sp++;
  419.              (*sub)='\0';
  420.              confsep(subbuf,idx,st,part,1);
  421.              break;
  422.    case '{': for (sub=subbuf; *sp && *sp!='}'; sp++,sub++) *sub = *sp;
  423.              sp++;
  424.              (*sub)='\0';
  425.              confsep(subbuf,idx,st,part,1);
  426.              break;
  427.    case '(': /* Get number */
  428.              /* for (num=0; isdigit(*sp); sp++) num= num*10+(*sp-'0'); */
  429.              show[depth+1]=confcond(&sp,idx,st); /* for ultrix */
  430.              depth++;
  431.              break; /* ) */
  432.  
  433.    default:  *spp=sp-1; miscsep(spp,fp);
  434.    }
  435.  
  436.    *spp = sp;
  437. }
  438.  
  439. /******************************************************************************/
  440. /* SET "ONCE-ONLY" FLAGS VALUE                                                */
  441. /******************************************************************************/
  442. void       /* RETURNS: (nothing) */
  443. sepinit(x) /* ARGUMENTS:         */
  444. short x;   /*    Flags to set    */
  445. {
  446.    once |= x;
  447. }
  448.  
  449. /******************************************************************************/
  450. /* PROCESS ITEMSEP STRING                                                     */
  451. /* Output to pipe, if one is open, else to stdout                             */
  452. /******************************************************************************/
  453. void         /* RETURNS: (nothing) */
  454. itemsep(sep,fl) /* ARGUMENTS: */
  455. char *sep;   /*    Separator variable */
  456. int          fl;         /*    Force %c? */
  457. {
  458.    char       *sp,*tp;
  459.    response_t *cre;
  460.    FILE       *fp;
  461.    char       *str;
  462.    char        buff[MAX_LINE_LENGTH];
  463.    
  464.    str = expand(sep,DM_VAR);
  465.    if (!str) str = sep;
  466.  
  467.    /* Force %c */
  468.    if (fl) {
  469.       sprintf(buff,"%s%%c",str);
  470.       str = buff;
  471.    }
  472.  
  473.    if (status & S_EXECUTE)        fp = 0;
  474.    else if (status & S_REDIRECT) fp = st_glob.outp;
  475.    else                           fp = stdout;
  476.  
  477.    /* get status without trashing subj's in memory */
  478.    cre = &(re[st_glob.r_current]);
  479.  
  480.    show[depth=0]=1;
  481.    newline=1;
  482.    sp=str;
  483.  
  484.    for(;;) {
  485.       switch (*sp) {
  486.       case '%':   sp++; 
  487.                   itemsep2(&sp,&st_glob.opt_flags,fp);
  488.                   break;
  489.       case '\0':  if ((once & IS_UID)  && ((st_glob.opt_flags & OF_UID ) || (flags & O_UID )))
  490.                      fprintf(fp," uid %d",cre->uid);
  491.                   if ((once & IS_DATE) && ((st_glob.opt_flags & OF_DATE) || (flags & O_DATE))) 
  492.                      fprintf(fp," on %.24s",get_date(cre->date,0));
  493.                   if ((once & IS_RETIRED) 
  494.                   && (sum[st_glob.i_current-1].flags & IF_RETIRED))
  495.                      wfputs("\n   <item is retired>",fp);
  496.                   if ((once & IS_FORGOTTEN) 
  497.                   && (sum[st_glob.i_current-1].flags & IF_FORGOTTEN))
  498.                      wfputs("\n   <item is forgotten>",fp);
  499.                   if ((once & IS_FROZEN) 
  500.                   && (sum[st_glob.i_current-1].flags & IF_FROZEN))
  501.                      wfputs("\n   <item is frozen>",fp);
  502.                   if ((once & IS_LINKED) 
  503.                   && (sum[st_glob.i_current-1].flags & IF_PARTY))
  504.                      wfputs("\n   <synchronous (party) item>",fp);
  505.                   if ((once & IS_LINKED) 
  506.                   && (sum[st_glob.i_current-1].flags & IF_LINKED))
  507.                      wfputs("\n   <linked item>",fp);
  508.                   if ((once & IS_PARENT) 
  509.                   && (cre->parent>0))
  510.                      fprintf(fp,"   <response to #%d>",cre->parent-1);
  511.  
  512.                   if (once & IS_CENSORED) {
  513.                      if (cre->flags & RF_EXPIRED)
  514.                         wfputs("   <expired>",fp);
  515.                      else if (cre->flags & RF_SCRIBBLED) {
  516.                         if (cre->numchars>8 && cre->text 
  517.              && (flags & O_SCRIBBLER)) {
  518.                            char buff[MAX_LINE_LENGTH];
  519.                            short i;
  520.  
  521.                            for (i=0; i<8 && ((char*)cre->text)[i]!=' '; i++)
  522.                               buff[i] = ((char*)cre->text)[i];
  523.                            buff[i] = '\0';
  524.                         
  525.                            fprintf(fp,"   <censored & scribbled by %s>",buff);
  526.                         } else
  527.                            wfputs("   <censored & scribbled>",fp);
  528.                      } else if (cre->flags & RF_CENSORED)
  529.                         wfputs("   <censored>",fp);
  530.           }
  531.  
  532.                   if (newline) wfputc('\n',fp);
  533.                   once=0;
  534.                   fflush(fp);
  535.                   return;
  536.       case '\\':  /* Translate lchar into rchar */
  537.                   sp++; 
  538.                   tp=strchr(lchars,*sp); 
  539.                   if (tp) {    /* if *sp is 0 byte, will insert a 0 byte */
  540.                      if (show[depth]) wfputc(rchars[tp-lchars],fp);
  541.                      sp++;
  542.                      break;
  543.                   } /* else fall through into default */
  544.       default:    if (show[depth]) wfputc(*sp++,fp);
  545.                   else             sp++;
  546.       }
  547.    }
  548. }
  549.  
  550. /******************************************************************************/
  551. /* PROCESS CONFSEP STRING                                                     */
  552. /******************************************************************************/
  553. void                     /* RETURNS: (nothing)                    */
  554. confsep(sep,idx,st,part,fl) /* ARGUMENTS:                            */
  555. char        *sep;        /*    Sep string to process              */
  556. partentry_t *part;       /*    User participation info            */
  557. short        idx;        /*    Index of which cf we're processing */
  558. status_t *st;
  559. int          fl;         /*    Force %c? */
  560. {
  561.    char *sp,*tp,*str;
  562.    FILE *fp;
  563.    char buff[MAX_LINE_LENGTH];
  564.  
  565.    str = expand(sep,DM_VAR);
  566.    if (!str) str=sep;
  567.    
  568.    /* Compatibility: force "...prompt" to end in \c */
  569.    if (fl) {
  570.       sprintf(buff,"%s%%c",str);
  571.       str = buff;
  572.    }
  573.  
  574.    if (status & S_EXECUTE)        fp = 0;
  575.    else if (status & S_REDIRECT) fp = st_glob.outp;
  576.    else                           fp = stdout;
  577.  
  578.    show[depth=0]=1;
  579.    newline=1; qfail=0;
  580.    sp=str;
  581.  
  582.    while (!qfail) {
  583.       switch (*sp) {
  584.       case '%':   sp++; 
  585.                   confsep2(&sp,idx,st,part,fp);
  586.                   break;
  587.       case '\0':  if (newline) wfputc('\n',fp);
  588.                   once=0;
  589.                   fflush(fp);
  590.                   return;
  591.       case '\\':  /* Translate lchar into rchar */
  592.                   sp++; 
  593.                   tp=strchr(lchars,*sp); 
  594.                   if (tp) {    /* if *sp is 0 byte, will insert a 0 byte */
  595.                      if (show[depth]) wfputc(rchars[tp-lchars],fp);
  596.                      sp++;
  597.                      break;
  598.                   } /* else fall through into default */
  599.       default:    if (show[depth]) wfputc(*sp++,fp);
  600.                   else             sp++;
  601.                   break;
  602.       }
  603.    }
  604.    if (newline) wfputc('\n',fp);
  605.    fflush(fp);
  606. }
  607.