home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / vsoup128.zip / qsoup.cc < prev    next >
C/C++ Source or Header  |  1996-11-09  |  15KB  |  583 lines

  1. //  $Id: qsoup.cc 1.4 1996/11/09 18:48:16 hardy Exp $
  2. //
  3. //  This progam/module was written by Hardy Griech based on ideas and
  4. //  pieces of code from Chin Huang (cthuang@io.org).  Bug reports should
  5. //  be submitted to rgriech@ibm.net.
  6. //
  7. //  This file is part of soup++ for OS/2.  Soup++ including this file
  8. //  is freeware.  There is no warranty of any kind implied.  The terms
  9. //  of the GNU Gernal Public Licence are valid for this piece of software.
  10. //
  11. //
  12. //  This is a very simple simulation of inews for VSoup
  13. //
  14. //  Algorithm is as follows:
  15. //  ------------------------
  16. //  for (;;) {
  17. //     wait until no replies-file exists in that subdir
  18. //     lock %yarn%\history.pag (write access)
  19. //     recheck replies
  20. //     if (ok) 
  21. //        break
  22. //     unlock history.pag
  23. //  }
  24. //  unzip -oq reply.zip
  25. //  if (I have got news article)
  26. //     add news.msg to replies (if not already there)
  27. //     append the temporary to news.msg (know USENET & binary format)
  28. //  else
  29. //     add mail.msg to replies (if not already there)
  30. //     append the temporary to mail.msg (know USENET & binary format)
  31. //  delete temporary
  32. //  zip -0m reply.zip replies *.msg
  33. //  unlock history.pag
  34. //
  35. //  Attention:
  36. //  ----------
  37. //  -  lines of the written message are delimited by '\n' only
  38. //  -  this is a hack with almost no subroutines
  39. //
  40. //  
  41. //  Fixed settings:
  42. //  ---------------
  43. //  - call of unzip (unzip.exe -oq)
  44. //  - call of zip (zip -0mq)
  45. //  - name of history.pag
  46. //  - name of yarn config file (%HOME%\yarn\config)
  47. //  - name of reply-packet field in yarn config file
  48. //  - name of the SOUP replies file
  49. //
  50. //  Parameters:
  51. //  -----------
  52. //  -m        input file is a mail
  53. //  -v        be verbose
  54. //  -l<file>  lockfile, default is %YARN%\history.pag
  55. //  -r<file>  set the name of the reply packet, default is to check %HOME%\yarn\config
  56. //  -i        ignore rest of command line
  57. //  <file>    one input file (if left out, stdin will be used)
  58. //
  59.  
  60.  
  61.  
  62. #include <assert.h>
  63. #include <fcntl.h>
  64. #include <io.h>
  65. #include <getopt.h>
  66. #include <share.h>
  67. #include <stdio.h>
  68. #include <stdlib.h>
  69. #include <strings.h>
  70.  
  71.  
  72.  
  73. #define ENVHOME          "HOME"
  74. #define ENVYARN          "YARN"
  75. #define YARNLOCKFILE     "history.pag"
  76. #define YARNCONFIGFILE   "yarn\\config"
  77. #define REPLYPACKETFIELD "reply-packet"
  78. #define AREANEWS         "news"
  79. #define AREAMAIL         "mail"
  80. #define FILENEWS         "NEWS"
  81. #define FILEMAIL         "MAIL"
  82. #define SOUPREPLIES      "replies"
  83. #define SOUPMSG          "*.msg"
  84. #define SOUPEXT          ".msg"
  85. #define CMDUNZIP         "unzip -oq"
  86. #define CMDZIP           "zip -0mq"
  87.  
  88. #define CMDSENDMAIL      "sendmail"
  89. #define CMDINEWS         "inews"
  90.  
  91.  
  92.  
  93. static char  progname[FILENAME_MAX];
  94. static char  *homedir   = NULL;
  95. static char  *yarndir   = NULL;
  96. static int   doNews     = 1;
  97. static int   verbose    = 0;
  98. static FILE  *inputF    = NULL;
  99. static FILE  *tmpInputF = NULL;
  100.  
  101. static int   lockF      = -1;
  102.  
  103. static char lockFile[FILENAME_MAX];
  104. static char replyPacket[FILENAME_MAX];
  105. static char replyDir[FILENAME_MAX];
  106. static char startCwd[FILENAME_MAX];
  107.  
  108. static char fitFile[FILENAME_MAX];
  109. static char fitType;
  110.  
  111.  
  112.  
  113. static int fileExists( const char *s )
  114. {
  115.     int h;
  116.     
  117.     h = open( s, O_BINARY | O_RDONLY );
  118.     if (h == -1)
  119.     return 0;
  120.     close( h );
  121.     return 1;
  122. }   // fileExists
  123.  
  124.  
  125.  
  126. static int existReplies( void )
  127. {
  128.     char name[FILENAME_MAX];
  129.  
  130.     sprintf( name,"%s\\%s",replyDir,SOUPREPLIES );
  131.     if ( !fileExists(name)) {
  132.     if (verbose)
  133.         printf( "(%s:ok)",name );
  134.     return 0;
  135.     }
  136.     if (verbose)
  137.     printf( "(%s:denied)",name );
  138.     return 1;
  139. }   // existReplies
  140.  
  141.  
  142.  
  143. static int lockYarn( void )
  144. {
  145.     assert( lockF == -1 );
  146.  
  147.     lockF = sopen( lockFile, O_WRONLY | O_BINARY, SH_DENYRW );
  148.     if (verbose)
  149.     printf( "(%s:%s)",lockFile, (lockF == -1) ? "denied" : "ok" );
  150.     return lockF != -1;
  151. }   // lockYarn
  152.  
  153.  
  154.  
  155. static void unlockYarn( void )
  156. {
  157.     assert( lockF != -1 );
  158.  
  159.     close( lockF );
  160.     lockF = -1;
  161. }   // unlockYarn
  162.  
  163.  
  164.  
  165. static void usage( void )
  166. {
  167.     printf( "\n%s v0.10 (rg071196)\n\tcopy input into the yarn reply-packet (simulates inews)\n\n", progname );
  168.     printf( "usage:  %s [OPTION] [<inputfile>]\n",progname );
  169.     printf( "  -m        the input is a mail (default news)\n" );
  170.     printf( "  -v        be verbose\n" );
  171.     printf( "  -l<file>  specify lockfile, default %%%s%%\\%s\n",ENVYARN,YARNLOCKFILE );
  172.     printf( "  -r<file>  specify name of reply packet, default is to get it\n\t    from %%HOME%%\\%s\n",YARNCONFIGFILE );
  173.     printf( "  -i        ignore remainder of command line\n" );
  174.     printf( "if <inputfile> is omitted stdin will be used\n" );
  175.     exit( EXIT_FAILURE );
  176. }   // usage
  177.  
  178.  
  179.  
  180. int main( int argc, char *argv[] )
  181. {
  182.     int c;
  183.     FILE *tmpf;
  184.     char line[512];
  185.  
  186.     {
  187.     char *p1 = strrchr( argv[0],'/' );
  188.     char *p2 = strrchr( argv[0],'\\' );
  189.     if (p1 == NULL  &&  p2 == NULL)
  190.         strcpy( progname,argv[0] );
  191.     else
  192.         strcpy( progname, (p1 > p2) ? p1+1 : p2+1 );
  193.     if ((p1 = strrchr(progname,'.')) != NULL)
  194.         *p1 = '\0';
  195.     }
  196.  
  197.     homedir = getenv( ENVHOME );
  198.     yarndir = getenv( ENVYARN );
  199.  
  200.     inputF = stdin;
  201.     _fsetmode( inputF,"t" );
  202.  
  203.     if (stricmp(progname,CMDSENDMAIL) == NULL) {
  204.     doNews = 0;
  205.     verbose = 0;
  206.     }
  207.     else if (stricmp(progname,CMDINEWS) == NULL) {
  208.     doNews = 1;
  209.     verbose = 0;
  210.     }
  211.     else {
  212.     while ((c = getopt(argc, argv, "?mvr:l:i")) != EOF) {
  213.             switch (c) {
  214.         case '?':
  215.             usage();
  216.             break;
  217.         case 'm':
  218.             doNews = 0;
  219.             break;
  220.         case 'v':
  221.             verbose = 1;
  222.             break;
  223.         case 'r':
  224.             strcpy( replyPacket,optarg );
  225.             break;
  226.         case 'l':
  227.             strcpy( lockFile,optarg );
  228.             break;
  229.         case 'i':
  230.             goto IgnoreCmdLine;
  231.         default:
  232.             printf( "%s: ill option -%c\n", progname,c );
  233.             usage();
  234.             break;
  235.         }
  236.     }
  237.     if (argc-optind > 1) {
  238.         printf( "\n%s: too many args\n", progname );
  239.         usage();
  240.     }
  241.  
  242.     if (argc-optind == 1) {
  243.         if (verbose)
  244.         printf( "%s: input file %s\n",progname,argv[optind] );
  245.         inputF = fopen( argv[optind],"rt" );
  246.         if (inputF == NULL) {
  247.         printf( "%s: cannot open %s\n",progname,argv[optind] );
  248.         exit( EXIT_FAILURE );
  249.         }
  250.     }
  251.     }
  252.  
  253. IgnoreCmdLine:
  254.     if (homedir == NULL  &&  *replyPacket == '\0') {
  255.     printf( "%s: %%%s%% or -r<file> required\n", progname,ENVHOME );
  256.     exit( EXIT_FAILURE );
  257.     }
  258.  
  259.     if (yarndir == NULL  &&  *lockFile == '\0') {
  260.     printf( "%s: %%%s%% or -l<file> required\n", progname,ENVYARN );
  261.     exit( EXIT_FAILURE );
  262.     }
  263.  
  264.     if (*lockFile == '\0')
  265.     sprintf( lockFile, "%s\\%s",yarndir,YARNLOCKFILE );
  266.     if (verbose)
  267.     printf( "%s: using %s as lockfile\n",progname,lockFile );
  268.  
  269.     if (*replyPacket == '\0') {
  270.     char yarnConfFile[FILENAME_MAX];
  271.  
  272.     //
  273.     //
  274.     //  get reply-packet line from yarn config file
  275.     //
  276.     sprintf( yarnConfFile, "%s\\%s",homedir,YARNCONFIGFILE );
  277.     if (verbose)
  278.         printf( "%s: using %s as yarn config file\n",progname,yarnConfFile );
  279.  
  280.     tmpf = fopen( yarnConfFile,"rt" );
  281.     if (tmpf == NULL) {
  282.         printf( "%s: cannot open %s\n",progname,yarnConfFile );
  283.         exit( EXIT_FAILURE );
  284.     }
  285.  
  286.     while (fgets(line,sizeof(line),tmpf) != NULL) {
  287.         char tag[512];
  288.     
  289.         *replyPacket = *tag = '\0';
  290.         sscanf( line,"%[^=]=%s",tag,replyPacket );
  291.         if (stricmp(tag,REPLYPACKETFIELD) == 0  &&  *replyPacket != '\0')
  292.         break;
  293.         *replyPacket = '\0';
  294.     }
  295.     fclose( tmpf );
  296.  
  297.     if (*replyPacket == '\0') {
  298.         printf( "%s: %s configuration in %s required\n",progname,REPLYPACKETFIELD,yarnConfFile );
  299.         exit( EXIT_FAILURE );
  300.     }
  301.  
  302.     if (verbose)
  303.         printf( "%s: %s=%s\n",progname,REPLYPACKETFIELD,replyPacket );
  304.     }
  305.     if (verbose)
  306.     printf( "%s: using %s as reply packet\n",progname,replyPacket );
  307.  
  308.  
  309.     //
  310.     //  get directory of reply-packet
  311.     //
  312.     {
  313.     char *p1, *p2;
  314.  
  315.     strcpy( replyDir,replyPacket );
  316.     p1 = strrchr( replyDir,'/' );
  317.     p2 = strrchr( replyDir,'\\' );
  318.     if (p1 == NULL  &&  p2 == NULL) {
  319.         printf( "%s: ill definition of %s\n",progname,REPLYPACKETFIELD );
  320.         exit( EXIT_FAILURE );
  321.     }
  322.     if (p1 > p2)
  323.         *p1 = '\0';
  324.     else
  325.         *p2 = '\0';
  326.     }
  327.     if (verbose)
  328.     printf( "%s: directory of %s: %s\n",progname,REPLYPACKETFIELD,replyDir );
  329.  
  330.  
  331.     //
  332.     //  set working directory to replyDir
  333.     //  (before tmpfile() is called!  Advantage: the tempfiles are in the replyDir)
  334.     //
  335.     _getcwd2( startCwd,sizeof(startCwd) );
  336.     if (verbose)
  337.     printf( "%s: current working dir %s\n", progname,startCwd );
  338.     if (_chdir2(replyDir) == -1) {
  339.     printf( "%s: cannot change to %s\n", progname,replyDir );
  340.     exit( EXIT_FAILURE );
  341.     }
  342.     if (verbose)
  343.     printf( "%s: directory changed to %s\n", progname,replyDir );
  344.  
  345.  
  346.     //
  347.     //  read the input file and copy it to tmpInputF
  348.     //  Advantage:  tmpInputF lines are delimited by '\n' only!!!
  349.     //
  350.     tmpInputF = tmpfile();
  351.     if (verbose)
  352.     printf( "%s: copying input to tmpfile\n",progname );
  353.  
  354.     {
  355.     int c;
  356.     int sol = 1;
  357.     while ((c = fgetc(inputF)) != EOF  &&  c != 0x1a) {  // check for 0x1a, because sendmail requires it!
  358.         fputc( c,tmpInputF );
  359.         if (verbose) {
  360.         if (sol)
  361.             printf( "%s: ",progname );
  362.         putchar( c );
  363.         sol = (c == '\n');
  364.         }
  365.     }
  366.     }
  367.     fseek( tmpInputF, 0,SEEK_SET );
  368.  
  369.  
  370.     //
  371.     //  wait for access
  372.     //
  373.     if (verbose)
  374.     printf( "%s: waiting for access to %s\n", progname,replyPacket );
  375.     for (;;) {
  376.     int noReplies, lockOk;
  377.  
  378.     noReplies = lockOk = 0;
  379.     if ((noReplies = !existReplies())) {
  380.         if ((lockOk = lockYarn())) {
  381.         if (verbose)
  382.             printf( "\r" );
  383.         if ((noReplies = !existReplies()))
  384.             break;
  385.         unlockYarn();
  386.         }
  387.     }
  388.     if ( !verbose) {
  389.         if ( !noReplies)
  390.         printf( "\ranother instance accessing %s", replyPacket );
  391.         else if ( !lockOk)
  392.         printf( "\ranother instance holding %s", lockFile );
  393.     }
  394.     sleep( 4 );
  395.     printf( "\r%79s\r","" );
  396.     sleep( 1 );
  397.     }
  398.     if (verbose) {
  399.     printf( "\r%79s\r","" );
  400.     printf( "%s: got access, %s locked\n", progname,lockFile );
  401.     }
  402.  
  403.  
  404.     //
  405.     //  do the unzip
  406.     //
  407.     if (verbose)
  408.     printf( "%s: unzipping\n", progname );
  409.     if (fileExists(replyPacket)) {
  410.     for (;;) {
  411.         char cmd[512];
  412.  
  413.         sprintf( cmd,"%s %s",CMDUNZIP,replyPacket );
  414.         if (system(cmd) == 0)
  415.         break;
  416.         if (verbose)
  417.         printf( "\r%s failed",cmd );
  418.         sleep( 4 );
  419.         if (verbose)
  420.         printf( "\r%79s\r","" );
  421.         sleep( 1 );
  422.     }
  423.     if (verbose)
  424.         printf( "%s: %s unzipped\n", progname,replyPacket );
  425.     }
  426.     else {
  427.     if (verbose)
  428.         printf( "%s: no %s found (ok)\n", progname,replyPacket );
  429.     }
  430.  
  431.  
  432.     //
  433.     //  search for best fit in SOUPREPLIES
  434.     //  Yarn/Vsoup dependent
  435.     //
  436.     *fitFile = '\0';
  437.     tmpf = fopen( SOUPREPLIES,"rt" );
  438.     if (tmpf != NULL) {
  439.     while (fgets(line,sizeof(line),tmpf) != NULL) {
  440.         char file[512],area[512],type[512];
  441.         *type = '\0';
  442.         sscanf( line,"%[^\t]\t%[^\t]\t%[^\t]",file,area,type );
  443.         if (doNews) {
  444.         if (*type == 'B'  &&
  445.             (stricmp(file,FILENEWS) == NULL  ||  *fitFile == '\0')) {
  446.             strcpy( fitFile,file );
  447.             fitType = *type;
  448.         }
  449.         else if (*type == 'u'  &&  stricmp(area,AREANEWS) == 0) {
  450.             if (stricmp(file,FILENEWS) == NULL  ||  *fitFile == '\0') {
  451.             strcpy( fitFile,file );
  452.             fitType = *type;
  453.             }
  454.         }
  455.         }
  456.         else {
  457.         if (*type == 'b'  &&
  458.             (stricmp(file,FILEMAIL) == NULL  ||  *fitFile == '\0')) {
  459.             strcpy( fitFile,file );
  460.             fitType = *type;
  461.         }
  462.         else if (*type == 'u'  &&  stricmp(area,AREAMAIL) == 0) {
  463.             if (stricmp(file,FILEMAIL) == NULL  ||  *fitFile == '\0') {
  464.             strcpy( fitFile,file );
  465.             fitType = *type;
  466.             }
  467.         }
  468.         }
  469.     }
  470.     fclose( tmpf );
  471.     if (verbose  &&  *fitFile != '\0')
  472.         printf( "%s: fitting file is %s%s, type %c\n", progname,fitFile,SOUPEXT,fitType );
  473.     }
  474.  
  475.  
  476.     //
  477.     //  of there was no fit, then setup default and append it to REPLIES
  478.     //
  479.     if (*fitFile == '\0') {
  480.     int fcnt = 0;
  481.  
  482.     strcpy( fitFile, doNews ? FILENEWS : FILEMAIL );
  483.     fitType = doNews ? 'B' : 'b';
  484.     for (;;) {
  485.         char msgname[FILENAME_MAX];
  486.  
  487.         sprintf( msgname,"%s%s",fitFile,SOUPEXT );
  488.         if ( !fileExists(msgname))
  489.         break;
  490.         ++fcnt;
  491.         sprintf( fitFile,"%s%d", doNews ? FILENEWS : FILEMAIL, fcnt );
  492.     }
  493.  
  494.     tmpf = fopen( SOUPREPLIES,"ab" );
  495.     if (tmpf == NULL) {
  496.         printf( "%s: cannot create %s\n", progname, SOUPREPLIES );
  497.         exit( EXIT_FAILURE );
  498.     }
  499.     fprintf( tmpf,"%s\t%s\t%c\n", fitFile, (doNews) ? AREANEWS : AREAMAIL, fitType );
  500.     fclose( tmpf );
  501.     if (verbose)
  502.         printf( "%s: %s, type %c appended to %s\n",progname,fitFile,fitType,SOUPREPLIES );
  503.     }
  504.  
  505.  
  506.     //
  507.     //  copy the temporary input file to the destination SOUP file
  508.     //  first write length of packet to destination (depending on fitType)
  509.     //
  510.     {
  511.     char msgname[FILENAME_MAX];
  512.     long tmpSize;
  513.  
  514.     sprintf( msgname,"%s%s",fitFile,SOUPEXT );
  515.     tmpf = fopen( msgname,"ab" );
  516.     if (tmpf == NULL) {
  517.         printf( "%s:  cannot append to %s\n", progname,msgname );
  518.         exit( EXIT_FAILURE );
  519.     }
  520.  
  521.     fseek( tmpInputF,0,SEEK_END );
  522.     tmpSize = ftell( tmpInputF );
  523.     fseek( tmpInputF,0,SEEK_SET );
  524.     if (verbose)
  525.         printf( "%s: length of input=%ld\n",progname,tmpSize );
  526.     if (fitType == 'u')
  527.         fprintf( tmpf,"#! rnews %ld\n",tmpSize );
  528.     else {
  529.         unsigned char size[4];
  530.         size[0] = (tmpSize >> 24) & 0xff;
  531.         size[1] = (tmpSize >> 16) & 0xff;
  532.         size[2] = (tmpSize >>  8) & 0xff;
  533.         size[3] = (tmpSize >>  0) & 0xff;
  534.         fwrite( size,sizeof(size),1,tmpf );
  535.     }
  536.     for (;;) {
  537.         char buf[4096];
  538.         size_t got;
  539.         got = fread( buf,1,sizeof(buf),tmpInputF );
  540.         if (got == 0)
  541.         break;
  542.         fwrite( buf,1,got,tmpf );
  543.     }
  544.     if (verbose)
  545.         printf( "%s: input copied to %s%s\n", progname,fitFile,SOUPEXT );
  546.     fclose( tmpf );
  547.     }
  548.  
  549.  
  550.     //
  551.     //  do the zipping (kann nur was werden, wenn REPLIES existiert)
  552.     //
  553.     if (verbose)
  554.     printf( "%s: zipping\n",progname );
  555.     if ( fileExists(SOUPREPLIES)) {
  556.     for (;;) {
  557.         char cmd[512];
  558.         
  559.         sprintf( cmd,"%s %s %s %s",CMDZIP,replyPacket,SOUPMSG,SOUPREPLIES );
  560.         if (system(cmd) == 0)
  561.         break;
  562.     }
  563.     if (verbose)
  564.         printf( "%s: %s & %s zipped into %s\n", progname,SOUPREPLIES,SOUPMSG,replyPacket );
  565.     }
  566.     else {
  567.     if (verbose)
  568.         printf( "%s: %s does not exist, nothing zipped & nothing done\n", progname,SOUPREPLIES );
  569.     }
  570.     
  571.  
  572. #if 0    
  573.     //
  574.     //  go back to cwd
  575.     //
  576.     _chdir2( startCwd );
  577.     if (verbose)
  578.     printf( "%s: directory changed to %s\n", progname,startCwd );
  579. #endif
  580.  
  581.     exit( EXIT_SUCCESS );
  582. }   // main
  583.