home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Tools / mu / mu.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  30.5 KB  |  1,248 lines

  1. /* mu.c         MTS user interface */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Tools/mu/RCS/mu.c,v 6.0 1991/12/18 20:31:54 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Tools/mu/RCS/mu.c,v 6.0 1991/12/18 20:31:54 jpo Rel $
  9.  *
  10.  * $Log: mu.c,v $
  11.  * Revision 6.0  1991/12/18  20:31:54  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "head.h"
  19. #include "util.h"
  20. #include "q.h"
  21. #include "prm.h"
  22. #include <isode/cmd_srch.h>
  23. #include "tb_prm.h"
  24. #include "tb_q.h"
  25. #include "tb_a.h"
  26. #include "tb_dr.h"
  27.  
  28. #include <signal.h>
  29. #include <isode/usr.dirent.h>
  30. #include <sys/stat.h>
  31.  
  32.  
  33. #include "argh.h"       /* jct only */
  34.  
  35. /* That's enough #includes - ed */
  36.  
  37. /* tailor'ed directory */
  38. extern  char    *cmddfldir;
  39.  
  40. #define DEFAULT_FILENAME        "mu.defaults"
  41. #define MAXNAME_LENGTH          200
  42. #define MAXARG_COUNT            200
  43. #define COMMENTCHAR             '#'
  44. #define TOKENCHAR               '$'
  45. #define REPEATCHAR              '*'
  46. #define FILEMARKCHAR            '*'
  47. #define DISP_INDENT             2
  48. #define YES_STRING              "Yy"
  49. #define NO_STRING               "Nn"
  50. #define THREE_BAGS_FULL_STRING  ""      /* joke */
  51. #define CONFIRM_STRING          "Confirm ( Y/N ) "
  52.  
  53. /* ------ from : ut_msg.c: library of routines to read a message directory struct */
  54.  
  55. #define NULLDIR ((DIR*)0)
  56. #define NULLDCT ((struct dirent *)0)
  57.  
  58. extern int      errno;
  59. extern int      fcmp();
  60.  
  61. static DIR      *ST_dir = NULLDIR;
  62. static char     *ST_array[BUFSIZ];
  63. static char     *ST_name = NULLCP;
  64. static int      ST_curr = NULL;
  65. static int      ST_level = NULL;
  66. static int      ST_no = NULL;
  67. static int      basedir_len;
  68.  
  69. static int UM_rfile (), UM_push (), UM_isdir (),
  70.     UM_array_free ();
  71. static struct dirent *UM_readdir(), *UM_pop();
  72. /* ------ from : ut_msg.c: library of routines to read a message directory struct */
  73.  
  74. void    advise();
  75. void    adios();
  76. SFD sig_cleanquit();
  77.  
  78. struct argdef arg[] = { /* program specific flag definitions */
  79.  
  80. /*      flag            function        type    match */
  81.  
  82.     "default",      NULL,           '1',    0,
  83.     "file",         NULL,           'm',    0,
  84.     "value",        NULL,           'm',    0,
  85.     "body",         NULL,           'm',    0,
  86.     "tree",         NULL,           '1',    0,
  87.     "confirm",      NULL,           '0',    0,
  88.     "nofix",        NULL,           '0',    0,
  89.     "prompt",       NULL,           '2',    0,
  90.     "group",        NULL,           '1',    0,
  91.     "logfile",      NULL,           '1',    0,
  92.     "help",         show_args,      '0',    0,
  93.     "-",            show_args,      '0',    0,
  94.     "!",            NULL,           '0',    0,
  95.     "0",            NULL,           '0',    0,
  96.     "1",            NULL,           '0',    0,
  97.     "2",            NULL,           '0',    0,
  98.     "3",            NULL,           '0',    0,
  99.     "4",            NULL,           '0',    0,
  100.     "5",            NULL,           '0',    0,
  101.     "",             NULL,           '?',    0
  102.     /* "" is 'others' list, also terminates structure array  */
  103. };
  104.  
  105. /* Other global variables */
  106. static  struct  prm_vars        prm;
  107. static  struct  Qstruct         q;
  108.  
  109. ADDR    *ad_originator;         /* address of sender */
  110. ADDR    *ad_recipient;          /* recipient list */
  111.  
  112. RP_Buf  r,*rp = &r;             /* reply value structure */
  113. int     debug[6]={0,0,0,0,0,0}; /* interactive debug flags */
  114. int     nest_level=0;           /* to display level of recursion */
  115. int     confirm_input = FALSE;
  116. int     fix_input = TRUE;
  117. FILE    *muout=stdout;          /* progress messages to... */
  118. char    *getcwd();              /* not used */
  119.  
  120. /* 
  121.     In addition to the LLOG_TRACE, LLOG_DEBUG calls associated
  122.     with debug[0], debug[1] shown below, there are other
  123.     LLOG_FATAL and LLOG_EXCEPTIONS calls.  Note that list_args
  124.     and show_args ( in argh.c ) do not generate LLOG events.
  125.  
  126.     debug[?]    function
  127.     0       log to muout progress messages, and PPLOG( LLOG_TRACE ...)
  128.     1       log to muout command files as they are processed, and PPLOG( LLOG_DEBUG ...)
  129.     2       list to muout body part files as they are io_tdata'ed
  130.     3       list to muout structures prior to submit io_ calls
  131.     4       abort prior to submit io_ calls
  132.     5       append to logfile rather than overwrite
  133. */
  134.  
  135. /* ----------------------------------------------------------------- */
  136. main (argc, argv)
  137. int     argc;
  138. char    **argv;
  139. {
  140.     sys_init (argv[0]);
  141.  
  142.     signal(SIGINT,sig_cleanquit);
  143.  
  144.     msg_init();     /* initialise message structures */
  145.  
  146.     in_all(argc,argv);
  147.     do_all(argc,argv);
  148.  
  149.     if (muout != stdout)
  150.         fclose(muout);
  151.     exit(0);
  152. }
  153. /* ----------------------------------------------------------------- */
  154. in_all(argc, argv)      /* input from original or constructed command line */
  155.             /* CALLED RECURSIVELY */
  156. int     argc;
  157. char    **argv;
  158. {
  159.     int     scan_counter;
  160.  
  161.     if (debug[0]) {
  162.         fprintf(muout,"in_all nest_level %d\n",nest_level);
  163.         PP_LOG (LLOG_TRACE,("mu: in_all nest_level %d",nest_level));
  164.     }
  165.     /*      printf("argc=%d argv=%h\n",argc,argv); */
  166.  
  167.     scan_counter=scan_args(argc,argv);      /* prep_args() called automatically */
  168.  
  169.     get_debug(scan_counter);
  170.  
  171.     process_args(argv,scan_counter);
  172. }
  173. /* ----------------------------------------------------------------- */
  174. do_all(argc, argv)      /* all post-input operations */
  175. int     argc;
  176. char    **argv;
  177. {
  178.     if (debug[0]){
  179.         list_args(muout,"default");
  180.         list_args(muout,"logfile");
  181.         list_args(muout,"file");
  182.         list_args(muout,"value");
  183.         list_args(muout,"body");
  184.         list_args(muout,"tree");
  185.         list_args(muout,"confirm");
  186.         list_args(muout,"nofix");
  187. /*
  188.         list_args(muout,"prompt");
  189.         list_args(muout,"group");
  190. */
  191.         list_args(muout,"");
  192.     }
  193.  
  194.     call_args(argc,argv,muout);     /* pass output file pointer */
  195.  
  196.     if (ad_originator == NULLADDR)
  197.         adios("","No originator specified");        /* ... and abort */
  198.  
  199.     if (ad_recipient == NULLADDR)
  200.         adios("","No recipient specified");        /* ... and abort */
  201.  
  202.     if( debug[3] )
  203.         print_structures();
  204.  
  205.     if( !debug[4] )
  206.         submit_message(argv);
  207.  
  208.     return;
  209. }
  210. /* ----------------------------------------------------------------- */
  211. process_args(argv,scan_counter)
  212. char    **argv;
  213. int     scan_counter;
  214. {
  215.     FILE    *fd;
  216.     static  char    default_filename[MAXNAME_LENGTH] = DEFAULT_FILENAME;
  217.     char    *argvtemp[MAXARG_COUNT];
  218.     char    buf[BUFSIZ];
  219.     char    *p, *p_end;
  220.     int     i,n,of,dummy;
  221.  
  222.     if (scan_counter == 1) {        /* can override mu.defaults from command line only */
  223.         if(p=nextc_arg("default",scan_counter,&n,&of))
  224.             strcpy(default_filename,p);
  225.         else {
  226.             if ((fd = fopen(default_filename,"r")) == NULL )
  227.                 sprintf(default_filename,"%s/%s",cmddfldir,DEFAULT_FILENAME);
  228.             else
  229.                 fclose(fd);
  230.         }
  231.         read_file(default_filename);    /* into param_, queue_structure */
  232.     }
  233.     /* read all -file arguments */
  234.     while (p=nextc_arg("file",scan_counter,&n,&of)) {
  235.         read_file(p);   /* into param_, queue_,addr_structure */
  236.     }
  237.     /* scan all -body arguments */
  238.     while (p=nextc_arg("body",scan_counter,&n,&of)) {
  239.         try_file(p);    /* open and check file length */
  240.     }
  241.     /* at least one call to next_arg/nextc_arg with different argument is
  242.     necessary before looping on "body" again; "tree" will do nicely ... */
  243.  
  244.     /* scan all -tree arguments */
  245.     while (p=nextc_arg("tree",scan_counter,&n,&of)) {
  246.         try_directory(p);       /* check that it exists */
  247.     }
  248.     /* similarly... at least one call to next_arg/nextc_arg with different argument is
  249.     necessary before looping on "tree" again; "value" will do nicely ... */
  250.  
  251.     for (n=0,of=0;(p = nextc_arg("value",scan_counter,&n,&of)) != NULL;) {
  252.         sprintf (buf, "%s", p);
  253.         i = 1;
  254.         while (of-i) {
  255.             p = nextc_arg("value",scan_counter,&dummy,&dummy);
  256.             p_end = index( buf, '\0' );
  257.             sprintf (p_end, " %s", p);      /* i.e. concatenate parameters */
  258.             i++;
  259.         }
  260.         /* this messy construction is necessary to put argvtemp in proper format */
  261.  
  262.         of = str2arg (buf, MAXARG_COUNT, argvtemp, NULLCP);
  263.  
  264.         if ( debug[0] ) {
  265.             dump_args(of,argvtemp);
  266.         }
  267.         parse_txt(of,argvtemp);
  268.     }
  269.     return(TRUE);
  270. }
  271.  
  272. /* ----------------------------------------------------------------- */
  273. get_debug(scan_counter)         /* check for action flags */
  274. {
  275.     char    deb[2];         /* very short string */
  276.     char    *p;
  277.     int     i,n,of;
  278.  
  279.     for(i=0;i<=5;i++) {
  280.         deb[0]=('0'+i);
  281.         deb[1]='\0';
  282.         if (nextc_arg(deb,scan_counter,&n,&of)) {
  283.             debug[i] = 1;
  284.             if ( debug[0] ) {
  285.                 fprintf(muout,"debug flag %s set\n", deb);
  286.                 PP_LOG (LLOG_TRACE,("mu: debug flag %s set", deb));
  287.             }
  288.         }
  289.     }
  290.     if (nextc_arg("nofix",scan_counter,&n,&of))
  291.         if ( debug[0] ) {
  292.             fprintf(muout,"nofix set\n");
  293.             PP_LOG (LLOG_TRACE,("mu: nofix set"));
  294.         }
  295.         fix_input=FALSE;
  296.  
  297.     if (nextc_arg("confirm",scan_counter,&n,&of))
  298.         if ( debug[0] ) {
  299.             fprintf(muout,"confirm set\n");
  300.             PP_LOG (LLOG_TRACE,("mu: confirm set"));
  301.         }
  302.         confirm_input=TRUE;
  303.  
  304.     if (p=nextc_arg("logfile",scan_counter,&n,&of)) {
  305.         if ( debug[0] ) {
  306.             fprintf(muout,"logfile set to %s\n", p);
  307.             PP_LOG (LLOG_TRACE,("mu: logfile set to %s", p));
  308.         }
  309.         if (muout != stdout)
  310.             fclose(muout);
  311.  
  312.         if ( debug[5] ) {
  313.             if ((muout = fopen(p,"a")) == NULL ) {
  314.                 advise("","unable to append to %s",p);
  315.                 muout = stdout;         /* and send to screen */
  316.             }
  317.         }
  318.         else {
  319.             if ((muout = fopen(p,"w")) == NULL ) {
  320.                 advise("","unable to write to %s",p);
  321.                 muout = stdout;
  322.             }
  323.         }
  324.     }
  325. }
  326. /* ----------------------------------------------------------------- */
  327. read_file(p)    /* read file *p */
  328. char    *p;
  329. {       
  330.     FILE    *fd;
  331.  
  332.     if (debug[0]) {
  333.         fprintf(muout,"start read_file : %s\n",p);
  334.         PP_LOG (LLOG_TRACE,("mu: start read_file : %s",p));
  335.     }
  336.     if ((fd = fopen(p,"r")) == NULL ) {
  337.         adios("","unable to read %s",p);        /* ... and abort */
  338.         return;
  339.     }
  340.     /* Rather than call rd_prm, rd_q, rd_adr individually, each of which
  341.     expects to receive a subset of the control parameters, each line is
  342.     read with txt2buf to command-argument form with str2arg (was sstr2arg) then 
  343.     offered to each of txt2prm, txt2q and txt2adr in turn to see if it
  344.     is valid for any - if not then an error is reported. */
  345.  
  346.     rd_all(fd);
  347.     fclose(fd);
  348.  
  349.     if (debug[0]) {
  350.         fprintf(muout,"finish read_file : %s\n",p);
  351.         PP_LOG (LLOG_TRACE,("mu: finish read_file : %s",p));
  352.     }
  353.     return;
  354. }
  355. /* ----------------------------------------------------------------- */
  356. try_file(p)     /* open, check file length */
  357. char    *p;
  358. {       
  359.     FILE    *fd;
  360.     long    f;
  361.     char    pp[MAXNAME_LENGTH],*r;
  362.  
  363.     strcpy(pp,p);
  364.     if (r=index(pp,FILEMARKCHAR)) {
  365.         *r = '\0';
  366.         strcat(pp,r+1);
  367.         if (debug[0]) {
  368.             fprintf(muout,"body part %s FILEMARKCHAR detected : %s\n",p,pp);
  369.             PP_LOG (LLOG_TRACE,("mu: body part %s FILEMARKCHAR detected : %s",p,pp));
  370.         }
  371.     }
  372.     if ((fd = fopen(pp,"r")) == NULL )
  373.         adios("","unable to read body part %s",pp);
  374.     fseek(fd,0L,2);         /* eof */
  375.     if ((f=ftell(fd)) == 0 )
  376.         adios("","body part %s is null file",pp);
  377.     fclose(fd);
  378.     return;
  379. }
  380. /* ----------------------------------------------------------------- */
  381. try_directory(p)        /* check that it exists */
  382. char    *p;
  383. {       
  384.     char    pp[MAXNAME_LENGTH],*r;
  385.  
  386.     strcpy(pp,p);
  387.     if (r=index(pp,FILEMARKCHAR)) {
  388.         *r = '\0';
  389.         strcat(pp,r+1);
  390.         if (debug[0]) {
  391.             fprintf(muout,"directory %s FILEMARKCHAR detected : %s\n",p,pp);
  392.             PP_LOG (LLOG_TRACE,("mu: directory %s FILEMARKCHAR detected : %s",p,pp));
  393.         }
  394.     }
  395.  
  396.     if (dir_rinit(pp) != RP_OK)
  397.         adios("","cannot initialise directory %s",pp);
  398.     dir_rend();
  399.     return;
  400. }
  401. /* ----------------------------------------------------------------- */
  402. rd_all  (fd)
  403. FILE    *fd;
  404. {
  405.     char    buf[BUFSIZ],copybuf[BUFSIZ];
  406.     char    *argv[MAXARG_COUNT];
  407.     int     argc,retval,repeat,repeat_offset,user_input,parse_result;
  408.     int     tokenfound;
  409.  
  410.     for (;;) {
  411.         retval = txt2buf (buf, fd);
  412.         if (rp_isbad (retval))
  413.             return (retval);
  414.  
  415.         if(debug[1])
  416.             display(buf,nest_level);
  417.  
  418.         if (*buf == REPEATCHAR) {
  419.             repeat = TRUE;
  420.             repeat_offset = 1;
  421.         }
  422.         else {
  423.             repeat = FALSE;
  424.             repeat_offset = 0;
  425.         }
  426.  
  427.         for(;;) {
  428.             /* copy buf to copybuf and check for TOKENCHAR */
  429.             user_input=prompt(copybuf,buf,repeat,&tokenfound);
  430.  
  431.             if (repeat && !tokenfound) {
  432.                 advise(NULL,"<<%s>>\nerror : no TOKENCHAR(s) in REPEAT line - REPEATCHAR ignored",buf);
  433.                 repeat = FALSE;
  434.             }
  435.             if(repeat && !user_input)       /* no more user input */
  436.                 break;
  437.             strip(copybuf);                 /* remove trailing spaces */
  438.             /* argc = str2arg (copybuf+repeat_offset, 50, argv, " \t\n"); */
  439.             argc = str2arg (copybuf+repeat_offset, MAXARG_COUNT, argv, NULLCP);
  440.             argv[argc] = NULLCP;
  441. /*
  442.             if (debug[0]) {
  443.                 dump_args(argc,argv);
  444.             }
  445. */
  446.             if (argc == 0) {        /* ignore empty lines */
  447.                 parse_result=OK;
  448.             }
  449.             else {
  450.                 parse_result=parse_txt(argc,argv);      /* parse_txt(argc,argv,ftell(fd)); */
  451.             }
  452.             if(repeat || (fix_input && user_input && (parse_result == NOTOK)) ) {
  453.                 continue;
  454.             }
  455.             else {
  456.                 break;
  457.             }
  458.         }
  459.     }
  460. }
  461. /* ----------------------------------------------------------------- */
  462. parse_txt(argc,argv)    /* returns OK || NOTOK */
  463. int     argc;
  464. char    **argv;
  465.  
  466. /* long fd_startln;     /* for _offset calculations */
  467.  
  468. {
  469.     char    *p;
  470.     char    buf[BUFSIZ];
  471.     char    *nargv[MAXARG_COUNT];
  472.     int     nargc;
  473.     int     retval;
  474.  
  475.     if(**argv == COMMENTCHAR) {
  476.         if (debug[0] && !debug[1]) {    /* avoids duplicatation */
  477.             arg2vstr(BUFSIZ,BUFSIZ,buf,argv);
  478.             display(buf,nest_level);
  479.         }
  480.     }
  481.     else if(**argv == FLAGCHAR) {
  482.  
  483.         /* dump_args(-1,argv); */
  484.         arg2vstr(BUFSIZ,BUFSIZ,buf,argv);
  485.  
  486.         /*
  487.         fflush(muout);
  488.         fprintf(muout,"muout flushed\n");
  489.         */
  490.  
  491.         if (debug[0]) {
  492.             fprintf(muout,"arg2vstr returns <%s>\n",buf);
  493.             PP_LOG (LLOG_TRACE,("mu: arg2vstr returns <%s>",buf));
  494.         }
  495.         p=malloc(strlen(buf)+6);
  496.         sprintf(p,"DUMMY %s",buf);
  497.         if (debug[0]) {
  498.             fprintf(muout,"\nin_all RECURSION with %s\n\n",p);
  499.             PP_LOG (LLOG_TRACE,("mu: in_all RECURSION with %s",p));
  500.         }
  501.         strip(p);                       /* remove trailing spaces */
  502.         /* nargc = str2arg (p, 50, nargv, " \t\n"); */
  503.         nargc = str2arg (p, MAXARG_COUNT, nargv, NULLCP);
  504.         nargv[nargc] = NULLCP;
  505. /*
  506.         if (debug[0]) {
  507.             dump_args(nargc,nargv);
  508.         }
  509. */
  510.         if (nargc != 0) {
  511.             nest_level++;
  512.  
  513.             in_all(nargc,nargv);    /* ***** RECURSION ***** */
  514.  
  515.             nest_level--;
  516.         }
  517.     }
  518.     else {
  519.         retval = txt2prm (&prm, argv, argc);
  520.         if (rp_isgood(retval) || retval == PRM_END)
  521.             return(OK);
  522.  
  523.         retval = txt2q (&q, (long)0, argv, argc);
  524.         if (rp_isgood(retval) || retval == Q_END)
  525.             return(OK);
  526.  
  527.         if (lexequ(argv[0],"Origs") == 0) {
  528.             if (debug[0]) {
  529.                 fprintf(muout,"Origs in input\n");
  530.                 PP_LOG (LLOG_TRACE,("mu: Origs in input"));
  531.             }
  532.             if (ad_originator == NULLADDR) { /* Only one Origs */
  533.                 retval = txt2adr (&ad_originator, 0L, argv, argc);
  534.                 if (rp_isgood(retval) || retval == AD_END)
  535.                     return(OK);
  536.             }
  537.         }
  538.         else {
  539.             retval = txt2adr (&ad_recipient, 0L, argv, argc);
  540.             if (rp_isgood(retval) || retval == AD_END)
  541.                 return(OK);
  542.         }
  543.  
  544.         /* error if get here */
  545.         arg2vstr(BUFSIZ,BUFSIZ,buf,argv);
  546.         advise(NULL,"error `%s' (retval=%s)",buf,digit_word(retval));
  547.             return(NOTOK);
  548.     }
  549.     return(OK);
  550. }
  551.  
  552. /* ----------------------------------------------------------------- */
  553. print_structures()      /* print out result of merge */
  554. {
  555.     ADDR    *ap;
  556.  
  557.     fprintf (muout,"-----------------------------------------------------------------\n");
  558.     prm2txt (muout,&prm);
  559.     q2txt   (muout,&q);
  560.     adr2txt (muout,ad_originator,AD_ORIGINATOR);
  561.     ap = ad_recipient;
  562.     do {
  563.         adr2txt (muout,ap,AD_RECIPIENT);
  564.         ap = ap->ad_next;
  565.     } while ( ap != NULL );
  566.     fprintf (muout,"-----------------------------------------------------------------\n");
  567. }
  568. /* ----------------------------------------------------------------- */
  569. int     prompt(copybuf,buf,repeat,tokenfound)   /* user input to expand embedded TOKENCHAR's */
  570. char    *copybuf,*buf;                          /* buf is original line from file */
  571. int     repeat;
  572. int     *tokenfound;
  573. {
  574.     char    *p;
  575.     char    inbuf[BUFSIZ];
  576.     int     user_input=FALSE;
  577.  
  578.     strcpy(copybuf,buf);    /* only modify copy */
  579.  
  580.     *tokenfound = FALSE;    /* to be tested with repeat */
  581.  
  582.     if( (*buf != COMMENTCHAR) && (index(buf,TOKENCHAR)) ) {
  583.         for(;;) {       /* Loop to allow line re-input if not confirmed */
  584.             p=copybuf;
  585.             while (p = index(p,TOKENCHAR)) {
  586.                 p++;
  587.                 if ( *p == TOKENCHAR ) {        /* $$ - do not set tokenfound */
  588.                     *p = '\0';
  589.                     strcat(copybuf,p+1);
  590.                 }
  591.                 else {
  592.                     *tokenfound = TRUE;
  593.                     *(--p) = '\0';
  594.                     printf("\n%s%c ",copybuf,TOKENCHAR);
  595.                     scanfcr(inbuf);         /* scanf("%s",inbuf); */
  596.                     if (repeat && (strlen(inbuf) == 0)) {
  597.                         user_input=FALSE;
  598.                         return(user_input);     /* I HATE THIS */
  599.                     }
  600.                     else {
  601.                         user_input=TRUE;
  602.                         strcat(inbuf,p+1);
  603.                         strcat(p,inbuf);
  604.                     }
  605.                 }
  606.             }
  607.             if (user_input && confirm_input) {
  608.                 if (confirm(copybuf)) {
  609.                     break;
  610.                 }
  611.                 else {
  612.                     strcpy(copybuf,buf);
  613.                     continue;       /* re-input whole line */
  614.                 }
  615.             }
  616.             else {
  617.                 break;          /* confirm_input FALSE or TRUE and confirmed */
  618.             }
  619.         }
  620.     }
  621.     return(user_input);
  622. }
  623.  
  624. /* ----------------------------------------------------------------- */
  625. scanfcr(inbuf)  /* equiv. to scanf("%s",inbuf) with CR only allowed */
  626. char    *inbuf;
  627. {       
  628.     int     i;
  629.     char    c;
  630.  
  631.     for(i=0,inbuf[i]='\0';((inbuf[i]=getchar()) != '\n');i++) {
  632.     }
  633.     inbuf[i]='\0';
  634. }
  635. /* ----------------------------------------------------------------- */
  636. confirm(buf)    /* offer confirmation of user input */
  637. char    *buf;
  638. {
  639.     int     i;
  640.     char    s[10];
  641.  
  642.     for(;;) {
  643.         printf("\n%s\n\t%s",buf,CONFIRM_STRING);
  644.         scanfcr(s);
  645.         if (s[0] == '\0')
  646.             continue;
  647.         if (index(YES_STRING,s[0])) {
  648.             i=TRUE;
  649.             break;
  650.         }
  651.         if (index( NO_STRING,s[0])) {
  652.             i=FALSE;
  653.             break;
  654.         }
  655.     }
  656.     return(i);
  657. }
  658. /* ----------------------------------------------------------------- */
  659. msg_init()
  660. {
  661.     /*      prm_init (p); */
  662.     q_init(&q);
  663.     ad_init();
  664. }
  665. /* ----------------------------------------------------------------- */
  666. ad_init()   /* -- initialise the linked lists -- */
  667. {
  668.     if (ad_recipient  != NULLADDR)  adr_tfree (ad_recipient);
  669.     if (ad_originator != NULLADDR)  adr_tfree (ad_originator);
  670.     ad_originator   = NULLADDR;
  671.     ad_recipient    = NULLADDR;
  672. }
  673.  
  674. /* ----------------------------------------------------------------- */
  675. submit_message(argv)
  676. char    **argv;
  677. {
  678.     int     type = OK;
  679.     int     offset;
  680.     char    *p,*r;
  681.     char    t[MAXPATHLENGTH];            /* for copy of directory specified in -tree */
  682.     char    dir_fname[MAXPATHLENGTH];
  683.     char    submit_fname[MAXPATHLENGTH];
  684.     ADDR    *ap;
  685.  
  686.     if (debug[0]) {
  687.         fprintf(muout,"submit_message io_init\n");
  688.         PP_LOG (LLOG_TRACE,("mu: submit_message io_init"));
  689.     }
  690.     if(rp_isbad(io_init(rp)))
  691.         rp_error(rp);
  692.     if (debug[0]) {
  693.         fprintf(muout,"submit_message io_wprm\n");
  694.         PP_LOG (LLOG_TRACE,("mu: submit_message io_wprm"));
  695.     }
  696.     if(rp_isbad(io_wprm(&prm,rp)))
  697.         rp_error(rp);
  698.     if (debug[0]) {
  699.         fprintf(muout,"submit_message io_wrq\n");
  700.         PP_LOG (LLOG_TRACE,("mu: submit_message io_wrq"));
  701.     }
  702.     if(rp_isbad(io_wrq(&q,rp)))
  703.         rp_error(rp);
  704.  
  705.     ap = ad_originator;
  706.     if (debug[0]) {
  707.         fprintf(muout,"submit_message io_wadr originator %s\n",ap->ad_value);
  708.         PP_LOG (LLOG_TRACE,("mu: submit_message io_wadr originator %s",ap->ad_value));
  709.     }
  710.     if(rp_isbad(io_wadr(ap,AD_ORIGINATOR,rp)))
  711.         rp_error(rp);
  712.  
  713.     ap = ad_recipient;
  714.     do {
  715.         if (debug[0]) {
  716.             fprintf(muout,"submit_message io_wadr recipient %s\n",ap->ad_value);
  717.             PP_LOG (LLOG_TRACE,("mu: submit_message io_wadr recipient %s",ap->ad_value));
  718.         }
  719.         if(rp_isbad(io_wadr(ap,AD_RECIPIENT,rp)))
  720.             rp_error(rp);
  721.         ap = ap->ad_next;
  722.     } while ( ap != NULL );
  723.  
  724.     if (debug[0]) {
  725.         fprintf(muout,"submit_message io_adend\n");
  726.         PP_LOG (LLOG_TRACE,("mu: submit_message io_adend"));
  727.     }
  728.     if(rp_isbad(io_adend(rp)))
  729.         rp_error(rp);
  730.  
  731.     if(((p=next_arg("body",argv)) !=NULL) || ((p=next_arg("tree",argv)) != NULL)) {
  732.  
  733.         if (debug[0]) {
  734.             fprintf(muout,"submit_message io_tinit\n");
  735.             PP_LOG (LLOG_TRACE,("mu: submit_message io_tinit"));
  736.         }
  737.         if(rp_isbad(io_tinit(rp)))
  738.             rp_error(rp);
  739.  
  740.         p=next_arg("",argv);            /* dummy to clear next_args memory */
  741.  
  742.         if(((p=next_arg("body",argv)) !=NULL) ) {
  743.             do {
  744.                 if ((r=index(p,FILEMARKCHAR)) == NULL)
  745.                     r=p;
  746.                 else
  747.                     ++r;
  748.                 /* pass pointer just after FILECHARMARK */
  749.                 if (debug[0]) {
  750.                     fprintf(muout,"submit_message io_tpart  file %s\n",r);
  751.                     PP_LOG (LLOG_TRACE,("mu: submit_message io_tpart  file %s",r));
  752.                 }
  753.                 if(rp_isbad(io_tpart(r,FALSE,rp)))
  754.                     rp_error(rp);
  755.                 if (debug[0]) {
  756.                     fprintf(muout,"submit_message io_tdata loop\n");
  757.                     PP_LOG (LLOG_TRACE,("mu: submit_message io_tdata loop"));
  758.                 }
  759.  
  760.                 loop_data(p);           /* and transfer file */
  761.  
  762.                 if (debug[0]) {
  763.                     fprintf(muout,"submit_message io_tdend\n");
  764.                     PP_LOG (LLOG_TRACE,("mu: submit_message io_tdend"));
  765.                 }
  766.                 if(rp_isbad(io_tdend(rp))) {
  767.                     rp_error(rp);
  768.                 }
  769.             } while(p=next_arg("body",argv));
  770.         }
  771.  
  772.         p=next_arg("",argv);            /* dummy to clear next_args memory */
  773.  
  774.         if(((p=next_arg("tree",argv)) !=NULL) ) {
  775.  
  776.             do {
  777.                 strcpy(t,p);            /* copy for FILCHARMARK manipulation */
  778.                 if ((r=index(t,FILEMARKCHAR))) {
  779.                     *r = '\0';
  780.                     strcat(t,r+1);
  781.                     offset = r-t;   /* offset to intended name - just after FILECHARMARK */
  782.                 }
  783.                 else {
  784.                     offset = 0;
  785.                 }
  786.  
  787.                 if (debug[0]) {
  788.                     fprintf(muout,"submit_message dir_rinit %s\n",t);
  789.                     PP_LOG (LLOG_TRACE,("mu: submit_message dir_rinit %s",t));
  790.                 }
  791.                 if ( dir_rinit( t ) != RP_OK )
  792.                     adios (NULL,"Cannot initialise directory %s\n",t);
  793.  
  794.                 while (dir_rfile(dir_fname) == RP_OK ) {
  795.                     if (debug[0]) {
  796.                         fprintf(muout,"mu: dir_rfile %s\n",dir_fname);
  797.                         PP_LOG (LLOG_TRACE,("mu: mu/dir_rfile %s",dir_fname));
  798.                     }
  799.  
  800.                     strcpy(submit_fname,&dir_fname[offset]);
  801.  
  802.                     if (debug[0]) {
  803.                         if (offset) {
  804.                             fprintf(muout,"mu: offset %d submitted name io_tpart : %s\n",offset,submit_fname);
  805.                             PP_LOG (LLOG_TRACE,("mu: offset %d submitted name io_tpart : %s",offset,submit_fname));
  806.                         }
  807.                     }
  808.                     if(rp_isbad(io_tpart(submit_fname,FALSE,rp)))
  809.                         rp_error(rp);
  810.                     if (debug[0]) {
  811.                         fprintf(muout,"submit_message io_tdata loop\n");
  812.                         PP_LOG (LLOG_TRACE,("mu: submit_message io_tdata loop"));
  813.                     }
  814.  
  815.                     loop_data(dir_fname);
  816.  
  817.                     if (debug[0]) {
  818.                         fprintf(muout,"submit_message io_tdend\n");
  819.                         PP_LOG (LLOG_TRACE,("mu: submit_message io_tdend"));
  820.                     }
  821.                     if(rp_isbad(io_tdend(rp))) {
  822.                         rp_error(rp);
  823.                     }
  824.                 }
  825.                 dir_rend();
  826.             } while(p=next_arg("tree",argv));
  827.         }
  828.     }
  829.  
  830.     if (debug[0]) {
  831.         fprintf(muout,"submit_message io_tend\n");
  832.         PP_LOG (LLOG_TRACE,("mu: submit_message io_tend"));
  833.     }
  834.     if(rp_isbad(io_tend(rp)))
  835.         rp_error(rp);
  836.  
  837.     if (debug[0]) {
  838.         fprintf(muout,"submit_message io_end\n");
  839.         PP_LOG (LLOG_TRACE,("mu: submit_message io_end"));
  840.     }
  841.     if(io_end(type) == NOTOK)
  842.         rp_error(rp);
  843.     else {
  844.         if (debug[0]) {
  845.             fprintf(muout,"submit_message OK\n");
  846.             PP_LOG (LLOG_TRACE,("mu: submit_message OK"));
  847.         }
  848.     }
  849.     return;
  850. }
  851. /* ----------------------------------------------------------------- */
  852. loop_data(p)
  853. char    *p;
  854. {
  855.     int     length;
  856.     char    buf[BUFSIZ];
  857.     FILE    *fd;
  858.     char    pp[MAXNAME_LENGTH],*r;
  859.  
  860.     strcpy(pp,p);
  861.     if (r=index(pp,FILEMARKCHAR)) {
  862.         *r = '\0';
  863.         strcat(pp,r+1);
  864.     }
  865.  
  866.     if ((fd = fopen(pp,"r")) == NULL )
  867.         adios("","unable to open body part for reading %s",pp);
  868.  
  869.     while ( (length=fread(buf,1,BUFSIZ,fd)) ) {
  870.         if (debug[2])
  871.             fwrite(buf,1,length,muout);
  872.         io_tdata(buf,length);
  873.     }
  874.     fclose(fd);
  875. }
  876. /* ----------------------------------------------------------------- */
  877. rp_error(rp)
  878. RP_Buf  *rp;
  879. {
  880.     adios (NULL,"RP_ERROR %d %s\n",rp->rp_val,rp->rp_line);
  881. }
  882.  
  883. /* ----------------------------------------------------------------- */
  884. display (s,level)
  885. char    *s;
  886. int     level;
  887. {
  888.     fprintf(muout,"%*s%s\n",level * DISP_INDENT, "", s);
  889.     PP_LOG (LLOG_DEBUG,("mu: input line %s", s));
  890. }
  891. /* ----------------------------------------------------------------- */
  892. /* VARARGS */
  893. void    adios (what, fmt, a, b, c, d, e, f, g, h, i, j)
  894. char          *what,*fmt,*a,*b,*c,*d,*e,*f,*g,*h,*i,*j;
  895. {
  896.     PP_LOG (LLOG_FATAL,(fmt, a, b, c, d, e, f, g, h, i, j));
  897.     advise (what, fmt, a, b, c, d, e, f, g, h, i, j);
  898.     cleanquit ();
  899. }
  900. /* ----------------------------------------------------------------- */
  901. /* VARARGS */
  902. void    advise (what, fmt, a, b, c, d, e, f, g, h, i, j)
  903. char           *what,*fmt,*a,*b,*c,*d,*e,*f,*g,*h,*i,*j;
  904. {
  905.     if (muout != stdout) {
  906.         fprintf (muout, fmt, a, b, c, d, e, f, g, h, i, j);
  907.         if (what)
  908.             (void) fputc (' ', muout), perror (what);
  909.         else
  910.             (void) fputc ('\n', muout);
  911.         (void) fflush (muout);
  912.     }
  913.     fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j);
  914.     if (what)
  915.         (void) fputc (' ', stderr), perror (what);
  916.     else
  917.         (void) fputc ('\n', stderr);
  918.     (void) fflush (stderr);
  919.     PP_LOG (LLOG_EXCEPTIONS,(fmt, a, b, c, d, e, f, g, h, i, j));
  920. }
  921. /* ----------------------------------------------------------------- */
  922. /* *****************  These routines taken from :- *******************
  923.     : ut_msg.c : library of routines to read a message directory struct */
  924.  
  925. dir_rinit (dir)         /* was msg_rinit (dir) */
  926. char    *dir;
  927. {       /* Now pass full or relative path for each invocation - unlike msg_rinit */
  928.  
  929.     PP_DBG (("mu: dir_rinit: (%s)", dir));
  930.  
  931.     if (ST_dir)  dir_rend();
  932.  
  933.     ST_level = 0;
  934.     ST_name = malloc (LINESIZE);
  935.     bzero (ST_name, LINESIZE);
  936.  
  937.     /*
  938.         full path not assumed
  939.     */
  940.     (void) sprintf (ST_name, "%s", dir);
  941.  
  942.     if (!UM_isdir (ST_name)) {
  943.         PP_LOG (LLOG_FATAL,("mu: dir_rinit: %s is not a dir", ST_name));
  944.         return (RP_FOPN);
  945.     }
  946.  
  947.     if ((ST_dir = opendir (ST_name)) == NULLDIR) {
  948.         PP_LOG (LLOG_FATAL,("mu: dir_rinit: unable to open %s", ST_name));
  949.         return (RP_FOPN);
  950.     }
  951.  
  952.     basedir_len = strlen(ST_name);
  953.  
  954.     return (RP_OK);
  955.  
  956. }
  957. /* ----------------------------------------------------------------- */
  958. dir_rfile (buf)         /* was msg_rfile (dir) */
  959. char    *buf;
  960. {
  961.     char    *ptr;
  962.  
  963.     PP_DBG (("mu: dir_rfile: (%s)", ST_name));
  964.  
  965.     if (ST_no == NULL) {
  966.         while (UM_rfile (buf) == RP_OK) {
  967.             ptr = strdup (buf);
  968.             ST_array [ST_no] = ptr;
  969.             ++ST_no;
  970.         }
  971.  
  972.         qsort ((char *)ST_array,
  973.             ST_no,
  974.             (sizeof (ST_array[0])),
  975.             fcmp);
  976.  
  977.     }
  978.  
  979.     if (ST_curr < ST_no) {
  980.         (void) strcpy (buf, ST_array[ST_curr]);
  981.         ++ST_curr;
  982.         return (RP_OK);
  983.     }
  984.  
  985.     return (RP_DONE);
  986. }
  987. /* ----------------------------------------------------------------- */
  988. dir_rend()              /* was msg_rend (dir) */
  989. {
  990.     PP_DBG (("mu: dir_rend: (%s)", ST_name));
  991.  
  992.     if (ST_dir) {
  993.         closedir (ST_dir);
  994.         ST_dir = NULLDIR;
  995.     }
  996.  
  997.     if (ST_name) {
  998.         free (ST_name);
  999.         ST_name = NULLCP;
  1000.     }
  1001.  
  1002.     if (ST_no)
  1003.         UM_array_free();
  1004.  
  1005.     ST_level = NULL;
  1006.     return (RP_OK);
  1007. }
  1008. /* ----------------------------------------------------------------- */
  1009. fcmp (f1, f2)
  1010. register char   **f1, **f2;
  1011. {
  1012.     char    *stripedf1,
  1013.         *stripedf2;
  1014.  
  1015.     stripedf1 = (*f1)+basedir_len+1;
  1016.     stripedf2 = (*f2)+basedir_len+1;
  1017.  
  1018.     return recur_fcmp(stripedf1,stripedf2);
  1019. }
  1020. /* ----------------------------------------------------------------- */
  1021. recur_fcmp(f1,f2)
  1022. register char   *f1,
  1023.         *f2;
  1024. {
  1025.     /* atoi stops at the first non digit */
  1026.     int f1digit = atoi(f1);
  1027.     int f2digit = atoi(f2);
  1028.  
  1029.     if (f1digit < f2digit)
  1030.         return -1;
  1031.  
  1032.     else if (f1digit > f2digit)
  1033.         return 1;
  1034.     else {
  1035.         int f1isdir, f2isdir;
  1036.         char *ixf1, *ixf2;
  1037.         /* dificult case may have to recurse */
  1038.         f1isdir = ((ixf1 = index(f1,'/')) != NULL);
  1039.         f2isdir = ((ixf2 = index(f2,'/')) != NULL);
  1040.         if (f1isdir && f2isdir)
  1041.             return recur_fcmp(++ixf1,++ixf2);
  1042.         return 0;
  1043.     }
  1044.  
  1045. }
  1046. /* --------------------------  Static  Routines  -------------------------- */
  1047. static UM_rfile (buf)
  1048. char    *buf;
  1049. {
  1050.     struct dirent   *dp;
  1051.  
  1052.     if (ST_dir == NULLDIR) {
  1053.         PP_LOG (LLOG_FATAL,("mu: UM_rfile: opendir not performed"));
  1054.         return (RP_DONE);
  1055.     }
  1056.  
  1057.  
  1058.     dp = UM_readdir (NULLCP);
  1059.  
  1060.     if (dp == NULLDCT)
  1061.         if (ST_level == 0)
  1062.             return (RP_DONE);
  1063.         else
  1064.             if ((dp = UM_pop()) == NULLDCT)
  1065.                 return (RP_DONE);
  1066.  
  1067.     if (UM_isdir (dp->d_name)) {
  1068.         /*
  1069.         new subdir
  1070.         */
  1071.         UM_push (dp->d_name);
  1072.         return (UM_rfile (buf));
  1073.     }
  1074.  
  1075.  
  1076.     if (isstr (ST_name))
  1077.         (void) sprintf (buf, "%s/%s", ST_name, dp->d_name);
  1078.     else
  1079.         (void) strcpy (buf, dp->d_name);
  1080.  
  1081.     return (RP_OK);
  1082.  
  1083. }
  1084. /* ----------------------------------------------------------------- */
  1085. static struct dirent *UM_pop()
  1086. {
  1087.     struct dirent   *dp;
  1088.     char            tbuf[LINESIZE],
  1089.             *ptr;
  1090.  
  1091.     --ST_level;
  1092.     ptr = rindex (ST_name, '/');
  1093.     (void) strcpy (tbuf, ++ptr);
  1094.     *--ptr = '\0';
  1095.  
  1096.     PP_DBG (("mu: UM_pop: (%s, %d)", ST_name, ST_level));
  1097.  
  1098.     closedir (ST_dir);
  1099.     ST_dir = opendir (ST_name);
  1100.  
  1101.     dp = UM_readdir (&tbuf[0]);
  1102.  
  1103.     if (dp)
  1104.         return (dp);
  1105.  
  1106.     if (ST_level)
  1107.         return (UM_pop());
  1108.  
  1109.     return (NULLDCT);
  1110. }
  1111. /* ----------------------------------------------------------------- */
  1112. static UM_push (name)
  1113. char    *name;
  1114. {
  1115.     char    tbuf[LINESIZE];
  1116.  
  1117.     (void) sprintf (tbuf, "%s/%s", ST_name, name);
  1118.  
  1119.     (void) strcpy (ST_name, tbuf);
  1120.  
  1121.     closedir (ST_dir);
  1122.  
  1123.     PP_DBG (("mu: UM_push: (%s, %d)", ST_name, ST_level+1));
  1124.  
  1125.     if ((ST_dir = opendir (ST_name)) == NULLDIR) {
  1126.         PP_LOG (LLOG_FATAL,("mu: UM_push: Unable to open %s", ST_name));
  1127.         return;
  1128.     }
  1129.  
  1130.     ++ST_level;
  1131. }
  1132. /* ----------------------------------------------------------------- */
  1133. static UM_isdir (name)
  1134. char    *name;
  1135. {
  1136.     struct stat     st_rec;
  1137.     char            tbuf[LINESIZE];
  1138.  
  1139.     if (!isstr (name))
  1140.         return (FALSE);
  1141.  
  1142.     (void) strcpy (&tbuf[0], ST_name);
  1143.  
  1144.     if (strcmp (ST_name, name) != 0) {
  1145.         (void) strcat (&tbuf[0], "/");
  1146.         (void) strcat (&tbuf[0], name);
  1147.     }
  1148.     fprintf(muout,"mu/UM_isdir testing %s as %s\n",name,tbuf);
  1149.  
  1150.     if (stat (&tbuf[0], &st_rec) == NOTOK) {
  1151.         PP_LOG (LLOG_FATAL, ("mu: UM_isdir: Unable to stat %s %d",&tbuf[0], errno));
  1152.         return (FALSE);
  1153.     }
  1154.  
  1155.     switch (st_rec.st_mode & S_IFMT) {
  1156.     case S_IFDIR:
  1157.         PP_DBG (("mu/: UM_isdir (%s = TRUE)", &tbuf[0]));
  1158.         return (TRUE);
  1159.     default:
  1160.         PP_DBG (("mu: UM_isdir (%s = FALSE)", &tbuf[0]));
  1161.         return (FALSE);
  1162.     }
  1163. }
  1164. /* ----------------------------------------------------------------- */
  1165. static struct dirent *UM_readdir (current)
  1166. char    *current;
  1167. {
  1168.     struct dirent   *dp;
  1169.     int             passed_current = FALSE;
  1170.  
  1171.     if (current)
  1172.         PP_DBG (("mu: UM_readdir (current = %s)", current));
  1173.  
  1174.     for (dp=readdir(ST_dir); dp != NULLDCT; dp=readdir(ST_dir)) {
  1175.         if (strcmp (dp->d_name, ".")  == 0)   continue;
  1176.         if (strcmp (dp->d_name, "..") == 0)  continue;
  1177.         if (current)
  1178.             if (strcmp (dp->d_name, current) == 0) {
  1179.                 passed_current = TRUE;
  1180.                 continue;
  1181.             }
  1182.             else if (passed_current == FALSE)
  1183.                 continue;
  1184.         break;
  1185.     }
  1186.  
  1187.     if (dp)
  1188.         PP_DBG (("mu: UM_readdir (%s)", dp->d_name));
  1189.  
  1190.     return (dp);
  1191. }
  1192. /* ----------------------------------------------------------------- */
  1193. static UM_array_free ()
  1194. {
  1195.     int     i;
  1196.  
  1197.     for (i=0; i < ST_no; i++)
  1198.         if (ST_array[i])  {
  1199.             free (ST_array [i]);
  1200.             ST_array[i] = NULLCP;
  1201.         }
  1202.  
  1203.     ST_no = NULL;
  1204.     ST_curr = NULL;
  1205. }
  1206. /* *****************  End routines taken from ut_msg ******************* */
  1207. /* ----------------------------------------------------------------- */
  1208. strip(x)        /* strip trailing spaces and tabs */
  1209. char    *x;
  1210. {
  1211.     int     i = strlen(x);
  1212.     char    *p;
  1213.  
  1214.     PP_DBG (("mu: strip trailing spaces & tabs from <%s>", x));
  1215.  
  1216.     if ( i ) {
  1217.         p = &x[ i - 1 ];
  1218.         while ( i && (*p == ' ' || *p == '\t') ) {
  1219.             *p-- = '\0';
  1220.             i--;
  1221.         }
  1222.     }
  1223. }
  1224. /* ----------------------------------------------------------------- */
  1225. dump_args(argc, argv)
  1226. int     argc;
  1227. char    **argv;
  1228. {
  1229.     int     i = 0;
  1230.     int     j = argc;
  1231.  
  1232.     fprintf(muout,"dump_args argc %d\n",argc);
  1233.     PP_LOG (LLOG_TRACE,("dump_args argc %d",argc));
  1234.     while (j && (argv[i] != NULLCP)) {
  1235.         fprintf(muout,"dump_args argv[%d] %s\n",i,argv[i]);
  1236.         PP_LOG (LLOG_TRACE,("dump_args argv[%d] %s",i,argv[i]));
  1237.         j--;
  1238.         i++;
  1239.     }
  1240. }
  1241.  
  1242. /* ARGSUSED */
  1243. SFD sig_cleanquit (sig)
  1244. int sig;
  1245. {
  1246.     cleanquit();
  1247. }
  1248.