home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MXMS_160.LZH / MAXMAIL.C < prev    next >
C/C++ Source or Header  |  1991-06-25  |  19KB  |  506 lines

  1. /****************************************************************************/
  2. /*                                                                          */
  3. /*    Maxmail     : By Craig Derouen                                        */
  4. /*                   October 10,1990                                        */
  5. /*                   Maximus ARCHIVE Mail Xfer Utility                      */
  6. /*                                                                          */
  7. /****************************************************************************/
  8.  
  9.  
  10. /* Version History: 
  11. Version 1.0   12-23-90 First release to public
  12. Version 1.5   02-24-91 Changed WRITE file ptr casting, altered activity divit.
  13.                        Alter display of hi message numbers to insure unsigned
  14.                          values.
  15.                        Fixed weird problems with lastread ptr updating in
  16.                          LOCAL message areas thanks to John Musslewhite.
  17.                        Allow default for Packing and Protocol questions on
  18.                          configure menu.
  19.                        Allow NON-Swap mode for exec'ing externals
  20.                        Alternate directory for creating and packing up
  21.                          archive mail
  22.                        Message text file will carry bbs name like ARC file
  23.                        Rework fossil code, eliminate external lib.
  24.                        OPUS style and MAX style barricaded areas support
  25.                        Support for non-numeric message areas
  26.                        Color support
  27.                        Sysop/user chat mode
  28.                        Hangup after download, DTR or AT command
  29.                        Signon bulletin file option
  30.                        Check disk space before running.
  31.                        Progress message for scanning areas
  32.                        Allow message ptr reset to 1 in non-echomail areas
  33. Version 1.52  04-17-91 Add count for # of times called today,plus control
  34.                          for sysop to limit it.
  35. Version 1.60  06-08-91 Add Sysop local menu
  36.                        Add daily message pack count and sysop control
  37.                        Adjust RCV flag for messages to specific user in
  38.                          local msg areas.
  39.                        Allow packer execution to be redirected to COM1,2,3,4
  40.                        Fix temp dir problems
  41.                        Fix problems with filesize testing/time at download
  42.                          prompt.
  43.                        Qwk support!
  44.                        Add newfiles list include option
  45.                        If xfer program error, return to menu instead of
  46.                          aborting back to MaxMail, allowing user to retry
  47.                        Add user configurable max pack count per message area
  48.                          for QWK packets.
  49.                        Add hangup after download countdown option
  50.                        Input REP packets from prompt in local mode..
  51.                        Add configuration menu
  52.                        Add forced messages areas
  53.                        Support QWK reader add/del msg area functions
  54.  
  55. */
  56.  
  57. #define  MAIN  1
  58.  
  59. #include "MaxMail.h"
  60.  
  61. extern int Bells;
  62. int secret = FALSE;
  63.  
  64. void main(int argc,char **argv)
  65. {
  66.    int x,z;
  67.    unsigned y;
  68.    unsigned long count;
  69.    struct stat fbuf;
  70.    time_t thistime;
  71.    struct tm *newtime;
  72.    struct _yell *yellptr;
  73.    union REGS r,r1;
  74.    struct find_t fileinfo;
  75.  
  76.  
  77. /* Parse out the drive and dir where maxmail is located */
  78.    _splitpath(argv[0],hdrive,hdir,temp,temp1);        /* Ignore name and extension */
  79.  
  80.  
  81.    IsLocal = TRUE;
  82.    TimeAdjust = FALSE;
  83.    msg_update = TRUE;
  84.    packer_del = TRUE;
  85.    HaveUpl = FALSE;
  86.    WatchDog = FALSE;
  87.    ChatOk = FALSE;
  88.    YellOn= FALSE;
  89.    MaxDaily = 0;        /* Defaults, allow infinite calls per day */
  90.    SwapMode = -1;
  91.    SysopMode = FALSE;
  92.    newuser = FALSE;
  93.    HangupMode = 0;
  94.    Hangup = 0;        /* Disable it */
  95.    MaxMsgs = 400;        /* Maximum number of messages to parse */
  96.    Task = 0;        /* If > 0, Multiuser mode */
  97.    strcpy(MCfgFile,"MaxMail.cfg");
  98.    strcpy(LastUse,"Lastuser.bbs");
  99.    strcpy(PrmFile,"Max.Prm");
  100.    strcpy(CfgFile,"MaxMail.usr");
  101.    strcpy(TxtFile,"MaxMsgs.txt");
  102.    strcpy(StatName,"MsgStats");
  103.    strcpy(SumFile,"Summary");
  104.    Exitcode = 0;
  105.  
  106.    for (x = 1; x < argc; x++) {        /* Parse out command line */
  107.       if (argv[x][0] == '-' || argv[x][0] == '/') {
  108.          y = toupper(argv[x][1]);        /* Argument switch */
  109.          switch (y) {
  110.             case 'A':        /* Adjust time online */
  111.                TimeAdjust = TRUE;
  112.                break;
  113.  
  114.             case 'C':        /* MaxMail configfile */
  115.                strcpy(CfgFile,argv[x]+2);
  116.                break;
  117.  
  118.             case 'D':        /* Don't swap */
  119.                SwapMode = FALSE;
  120.                break;
  121.  
  122.             case 'L':        /* Force Local mode */
  123.                IsLocal = 2;
  124.                break;
  125.  
  126.             case 'N':        /* Don't delete packed file */
  127.                packer_del = FALSE;
  128.                break;
  129.  
  130.             case 'P':        /* Parm file */
  131.                strcpy(PrmFile,argv[x]+2);
  132.                break;
  133.  
  134.             case 'S':        /* Enable Sysop mode */
  135.                SysopMode = TRUE;
  136.                IsLocal = 2;
  137.                break;
  138.  
  139.             case 'T':        /* Task number */
  140.                Task = argv[x][2] - '0';
  141.                sprintf(LastUse,"Lastus%02x.bbs",Task);
  142.                break;
  143.  
  144.             case 'U':        /* Turn off lastread update */
  145.                msg_update = FALSE;
  146.                break;
  147.  
  148.             case 'Z':        /* Show parms */
  149.                secret = TRUE;
  150.                show_opts();
  151.                break;
  152.  
  153.             case '?':        /* Show parms */
  154.                show_opts();
  155.                break;
  156.          }
  157.       }
  158.       else {        /* Only non-switch argument specifies the Maxmail config file */
  159.          strcpy(MCfgFile,argv[x]);
  160.       }
  161.    }
  162.  
  163.    init();
  164.  
  165.    if (!SysopMode)  {
  166.  
  167.       if (SwapMode == -1)
  168.          SwapMode = TRUE;        /* Default to swapping */
  169.  
  170.    /* Open the last userfile.  Without it, we can't do a thing! */
  171.  
  172.       x = sopen(LastUse,O_RDONLY | O_BINARY,SH_DENYNO,S_IREAD); 
  173.       if (x == -1) 
  174.          aborterror(FILEOPEN,"Missing Lastuse file");
  175.  
  176.       y = read(x,&LastUser,sizeof(struct _usr));
  177.       user_slen = (LastUser.struct_len ? LastUser.struct_len * 20 : 180);
  178.       lseek(x,0L,SEEK_SET);
  179.       y = read(x,&LastUser,user_slen);
  180.       if (y < (unsigned) user_slen) {        /* Humm couldnt read all of file! */
  181.          close(x);
  182.          aborterror(FILEOPEN,"Error reading LastUse file");
  183.       }
  184.       close(x);        /* We only need the file for the structure info */
  185.  
  186.       strcpy(UserName,LastUser.name);
  187.  
  188.       if (IsLocal < 2)
  189.          /* IsLocal = LastUser.flag == 0 ? TRUE : FALSE; */
  190.          IsLocal = FALSE;
  191.  
  192.       if (!IsLocal) {
  193.          if(!FossilInit())
  194.             aborterror(FILEOPEN,"Couldn't open FOSSIL");
  195.       }
  196.  
  197.    /* Now Compute the maximum messages caller can have for this run
  198.       based upon time remaining and baud rate. This is really a 
  199.       ROUGH guess and I will polish it in time! */
  200.  
  201.       count = get_kminute(); /* Fetch # of Kilobytes per minute at current baud */
  202.       count *= LastUser.timeremaining;        /* Total # of Kbytes we can download */
  203.  
  204.    /* Assume message is average of 500 bytes when packed */
  205.       count /= 500;
  206.  
  207.       MaxMsgs = ((MaxMsgs > (unsigned) count) && LastUser.flag) ? (unsigned) count : MaxMsgs;
  208.  
  209.       UserCfgnum = 0;        /* Startup */
  210.       if(stat(CfgFile,&fbuf) == 0 )         /* Does file exist? */
  211.          x = sopen(CfgFile,O_RDWR | O_BINARY,SH_DENYNO,S_IREAD);
  212.       else x = sopen(CfgFile,O_RDWR | O_BINARY | O_CREAT,SH_DENYNO,S_IWRITE);
  213.       if (x == -1)
  214.          aborterror(FILEOPEN,"Error opening/creating User config file");
  215.       UserCfgnum = find_config(x,LastUser.name,&USERCFG);
  216.       if (UserCfgnum < 0) {        /* Couldn't be found */
  217.          newuser_help();        /* Display a file to the new user */
  218.          newuser = TRUE;
  219.          memset(&USERCFG,0,sizeof(struct user_cfg));
  220.          USERCFG.flags |= USRCFG_UPD;        /* Force the user to update his configuration */
  221.          memcpy(USERCFG.name,LastUser.name,36);
  222.          UserCfgnum = find_blconfig(x);        /* Look for an empty slot */
  223.          if (UserCfgnum < 0)  /* Couldn't be found */
  224.             UserCfgnum = new_user(x);
  225.       }
  226.       close(x);        /* We only need the file for the structure info */
  227.  
  228.          
  229.       afile = _fsopen(PRM(adat_name),"rb",SH_DENYNO); 
  230.       if (afile == NULL)
  231.          aborterror(FILEOPEN,"Missing AREA.DAT file");
  232.       fread(&AREA,sizeof(struct _area),1,afile);
  233.       astrlen = AREA.struct_len;
  234.  
  235.       find_class();
  236.  
  237.       if(fidomsg_init()) 
  238.          aborterror(BADALLOC,NULL);
  239.  
  240.    /* Check disk space before really starting up things */
  241.       if (tdir[0])
  242.          strcpy(temp,tdir);
  243.       else strcpy(temp,PRM(sys_path));
  244.       signon();        /* Sign on message */
  245.  
  246.    /* Extract drive from pathname */
  247.       r.h.dl = (unsigned char) (toupper(temp[0]) - 0x40);     /* A=1,B=2,etc */
  248.       r.h.ah = 0x36;        /* DOS get free space call */
  249.       intdos(&r,&r1);
  250.       if (r1.x.ax == 0xffff) {        /* Invalid temp drive? */
  251.          strcpy(temp,PRM(sys_path));        /* Try Max root drive instead */
  252.          r.h.dl = (unsigned char) (temp[0] - 0x40);        /* A=1,B=2,etc */
  253.          intdos(&r,&r1);
  254.          if (r1.x.ax == 0xffff)         /* We are really in trouble now! */
  255.             aborterror(FILECREATE,"Invalid drive specified");
  256.       }
  257.       count = r1.x.cx;        /* Bytes per sector */
  258.       count *= r1.x.ax;        /* # of sectors per cluster */
  259.       count *= r1.x.bx;        /* # of available clusters = total byte space */
  260.  
  261.       if (count < 512000 ) {        /* Look for about 500K free */
  262.          setcolor(TextAttr[ATTN_TEXT]);
  263.          strout("Sorry but there is not enough disk space left on this drive\r\n");
  264.          strout("  to run MaxMail. Notify the sysop....\r\n");
  265.          logit("Working drive has too low disk space",'!');
  266.          deinit(2);
  267.       }
  268.  
  269.       if (USERCFG.flags & (USRCFG_UPD | USRCFG_FUPD | USRCFG_MSGUPD)) 
  270.          getconfig();
  271.       else {
  272.          strout("\r\nScanning selected message areas. Hang on....");
  273.          y = USERCFG.totareas;
  274.          build_areas(FALSE,TRUE);
  275.          if (USERCFG.totareas != y && USERCFG.totareas) {
  276.             USERCFG.flags |= USRCFG_MSGUPD;
  277.             getconfig();
  278.          }
  279.          if (USERCFG.totpackers != (unsigned) totpackers) {
  280.             setcolor(TextAttr[ATTN_TEXT]);
  281.             strout("\r\nMessage packer types have changed since your last call.");
  282.             get_packer(TRUE);
  283.          }
  284.          if (USERCFG.totprotos != (unsigned) totprotocols) {
  285.             setcolor(TextAttr[ATTN_TEXT]);
  286.             strout("\r\nDownload protocols have changed since your last call.");
  287.             get_proto(TRUE);
  288.          }
  289.       }
  290.  
  291.    /* Determine if yell can be enabled */
  292.  
  293.       Bells = 0;
  294.       if (prm.noise_ok) {
  295.          time(&thistime);
  296.          newtime = localtime(&thistime);
  297.          yellptr = NULL;
  298.          for (z = 0; z < MAX_YELL; z++) {        /* Scan yell sched array */
  299.             if (prm.yell[z].weekday == (unsigned char) newtime->tm_wday ) {
  300.                yellptr = &prm.yell[z];        /* Fetch current yell event */
  301.                break;
  302.             }
  303.          }
  304.          if (yellptr && yellptr->weekday) {        /* It is valid */
  305.             if (newtime->tm_hour >= (int) yellptr->start_hour) {
  306.                if (newtime->tm_hour == (int) yellptr->start_hour) {
  307.                   if (newtime->tm_min <= (int) yellptr->end_min) {
  308.                      YellOn = TRUE;
  309.                      Bells = yellptr->bells;
  310.                   }
  311.                }
  312.                else {
  313.                   if (newtime->tm_hour == (int) yellptr->end_hour) {
  314.                      if (newtime->tm_min <= (int) yellptr->end_min) {
  315.                         YellOn = TRUE;
  316.                         Bells = yellptr->bells;
  317.                      }
  318.                   }
  319.                   else if (newtime->tm_hour < (int) yellptr->end_hour) {
  320.                      YellOn = TRUE;
  321.                      Bells = yellptr->bells;
  322.                   }
  323.                }
  324.             }
  325.          }
  326.       }
  327.  
  328.       menu();
  329.       strout("\r\n\r\n");
  330.       if (*SignOff) {
  331.          strout(SignOff);
  332.          strout("\r\n");
  333.       }
  334.  
  335.       if (totmsgs)
  336.          update_msgs(); /* Update the lastread pointers */
  337.  
  338.       if (!IsLocal) {
  339.          if (Hangup < 1) 
  340.             strout("Heading back to Maximus. Please wait a sec....\r\n");
  341.          else {        /* Hang up the user */
  342.             setcolor(TextAttr[HILITE_TEXT]);
  343.             strout("Hanging you up now!\r\n");
  344.             setcolor(TextAttr[STD_TEXT]);
  345.             strout("Press [H]ang up for quick log off or [ENTER] to abort .....     ");
  346.             setcolor(TextAttr[MENU_KEY]);
  347.             FossPurgeBuff(TRUE);
  348.             for (z = 10; z >= 0; z--) {
  349.                sprintf(temp,"\b\b%02d",z);
  350.                strout(temp);
  351.                FossSendStr("\07");
  352.                delay_s(1);
  353.                if((y = FossGetCh()) != 0xFFFF) {
  354.                   y &= 0x00ff;
  355.                   if (y == 'h' || y == 'H') {
  356.                      z = 0;        /* Force hangup */
  357.                      break;
  358.                   }
  359.                   else if (y == '\r') {
  360.                      z = 1;
  361.                      break;
  362.                   }
  363.                }
  364.             }
  365.             if (z <= 0) {
  366.                setcolor(TextAttr[STD_TEXT]);
  367.                sprintf(temp,"\r\n\tSo long %s .......\r\n",LastUser.name);
  368.                strout(temp);
  369.                delay_s(2);
  370.                logit("User requested hangup after download",'#');
  371.                FossFlow(0);        /* Turn Control-S off */
  372.                FossPurgeBuff(FALSE);        /* Output buffer */
  373.                while (!(FossMdmStatus() & 0x4000)); /* Check output buffer */
  374.                if (HangupMode == 1) {        /* Use HAYES method */
  375.                   z = 0;        /* Deadlock counter */
  376.                   do
  377.                   {
  378.                      FossSendCh('+');        /* Get modem's attention */
  379.                      delay_ms(400);
  380.                      FossSendCh('+');        /* Get modem's attention */
  381.                      delay_ms(400);
  382.                      FossSendCh('+');        /* Get modem's attention */
  383.                      delay_s(2);
  384.                      FossSendStr("ATH0\r\n");        /* Hayes AT command to hang up */
  385.                      delay_s(1);
  386.                      z++;
  387.                   }
  388.                   while ((FossMdmStatus() & 128) && z < 10); /* Check carrier */
  389.                }
  390.                else {        /* Use DTR method */
  391.                   delay_ms(500);
  392.                   FossDtr(FALSE);        /* Lower DTR */
  393.                   delay_ms(1500);        /* 1.5 seconds */
  394.                   FossDtr(TRUE);        /* Raise DTR */
  395.                }
  396.                deinit(5);        /* Leave MaxMail and tell caller user hangup */
  397.             }
  398.             else {        /* User aborted auto hangup */
  399.                setcolor(TextAttr[STD_TEXT]);
  400.                strout("\r\nHeading back to Maximus. Please wait a sec....\r\n");
  401.                logit("User aborted auto hangup after download",'#');
  402.             }
  403.          }
  404.       }
  405.    }
  406.    else {        /* Special local sysop maintainence mode */
  407.       sprintf(temp,"Begin, v%2.2f",Version);
  408.       logit(temp,'+');
  409.       strcpy(temp1,"Local sysop maintainence mode");
  410.       logit(temp1,':');
  411.       strout("MaxMail - a MAXIMUS message utility by Craig Derouen\r\n");
  412.       printf("\t*** Version %2.2f ***\r\n",Version);
  413.       printf("Last compiled: %s\n",__TIMESTAMP__);
  414.       strout(temp1);
  415.       strout("\n");
  416.  
  417.       if (!parmread) {
  418.          if(read_prm(PrmFile) < 0)
  419.             aborterror(FILEOPEN,"Error opening PRM file!\r\n");
  420.       }
  421.  
  422.       afile = _fsopen(PRM(adat_name),"rb",SH_DENYNO); 
  423.       if (afile == NULL)
  424.          aborterror(FILEOPEN,"Missing AREA.DAT file");
  425.       fread(&AREA,sizeof(struct _area),1,afile);
  426.       astrlen = AREA.struct_len;
  427.  
  428. /* We still have to read the lastuse file, but just to get length for
  429.    later. So just look for ANY lastuser file. */
  430.  
  431.       if(_dos_findfirst("Lastus??.bbs",_A_NORMAL,&fileinfo) == 0) {
  432.          strcpy(LastUse,fileinfo.name);
  433.          x = sopen(LastUse,O_RDONLY | O_BINARY,SH_DENYNO,S_IREAD); 
  434.          if (x == -1) 
  435.             aborterror(FILEOPEN,"Missing Lastuse file");
  436.          read(x,&LastUser,sizeof(struct _usr));
  437.          user_slen = (LastUser.struct_len ? LastUser.struct_len * 20 : 180);
  438.          close(x);
  439.       }
  440.       else {        /* Create a fake one */
  441.          LastUser.ansi = TRUE;
  442.          LastUser.avatar = FALSE;
  443.       }
  444.       strcpy(LastUser.name,"Local Sysop");        /* Special mode */
  445.       strcpy(UserName,"Local Sysop");        /* Special mode */
  446.  
  447.       Sys_menu();
  448.       packer_del = TRUE;
  449.       TimeAdjust = FALSE;
  450.       deinit(0);
  451.    }
  452.  
  453.    deinit(Exitcode);
  454. }
  455.  
  456. /* Display version and compiler time to user. Put this function here
  457.     in this module since TIMESTAMP checks only this module for date */
  458.  
  459. void ShowVers(void)
  460. {
  461.    struct tm *newtime;
  462.    time_t aclock;
  463.  
  464.    setcolor(TextAttr[STD_TEXT]);
  465.    sprintf(temp,"MaxMail, Version %2.2f, By Craig Derouen\r\n",Version);
  466.    strout(temp);
  467.    setcolor(TextAttr[ATTN_TEXT]);
  468.    sprintf(temp,"Running under DOS %d.%d\r\n",_osmajor,_osminor);
  469.    strout(temp);
  470.    setcolor(TextAttr[HILITE_TEXT]);
  471.    sprintf(temp,"Program was last compiled: %s\r\n",__TIMESTAMP__);
  472.    strout(temp);
  473.    setcolor(TextAttr[MENU_KEY]);
  474.    sprintf(temp,"Remaining heap: %u bytes\r\n",_memavl());
  475.    strout(temp);
  476.    time(&aclock);
  477.    newtime = localtime(&aclock);
  478.    setcolor(TextAttr[STD_TEXT]);
  479.    sprintf(temp,"Current date and time are: %s\r\n",asctime(newtime));
  480.    strout(temp);
  481. }
  482.  
  483. void show_opts(void)
  484. {
  485.    printf("\nMaxmail Version: %2.2f by Craig Derouen\n",Version);
  486.    printf("Last compiled: %s\n",__TIMESTAMP__);
  487.    if (secret) {
  488.       printf("\t\a\aWaka! Waka! Waka! Author's secret function!\n");
  489.       printf("\tRemaining heap: %u bytes\n",_memavl());
  490.       printf("Since you are NOT the author, I am aborting...\n\n");
  491.    }
  492.    printf("Command line options:\n");
  493.    printf("\t /A: Adjust for time user is online\n");
  494.    printf("\t /C: Specify alt Maxmail USER config file\n");
  495.    printf("\t /D: Turn off SWAPPING mode for external programs\n");
  496.    printf("\t /L: Turns on local mode. No fossil handling\n");
  497.    printf("\t /N: Don't delete archive pack on exit (Use with local mode)\n");
  498.    printf("\t /P: Specify alt Max.prm file\n");
  499.    printf("\t /T: Specify Task number. Tells Maxmail we are running multiuser\n");
  500.    printf("\t /S: Sysop local maintainence mode\n");
  501.    printf("\t /U: Don't update LASTREAD message pointers\n");
  502.    printf("\t {Filename} use this file as alt Maxmail.cfg file\n");
  503.    exit(0);
  504. }
  505.  
  506.