home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / MISC / LO241SRV.ZIP / lmsg.c < prev    next >
C/C++ Source or Header  |  1998-08-01  |  83KB  |  3,177 lines

  1.  
  2. // LoraBBS Version 2.41 Free Edition
  3. // Copyright (C) 1987-98 Marco Maccaferri
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation; either version 2 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program; if not, write to the Free Software
  17. // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <stdio.h>
  20. #include <io.h>
  21. #include <fcntl.h>
  22. #include <string.h>
  23. #include <ctype.h>
  24. #include <stdlib.h>
  25. #include <conio.h>
  26. #include <time.h>
  27. #include <dir.h>
  28. #include <alloc.h>
  29. #include <sys\stat.h>
  30.  
  31. #include "lsetup.h"
  32. #include "quickmsg.h"
  33. #include "msgapi.h"
  34. #include "pipbase.h"
  35. #include "version.h"
  36.  
  37. struct _qlastread {
  38.     word msgnum[200];
  39. };
  40.  
  41. struct _glastread {
  42.     word msgnum[500];
  43. };
  44.  
  45. typedef struct {
  46.     long crc;
  47.     unsigned int num;
  48.     unsigned char board;
  49. } MSGLINK;
  50.  
  51.  
  52. char *cfgname = "CONFIG.DAT";
  53. struct _configuration cfg;
  54.  
  55. extern unsigned int _stklen = 13000;
  56.  
  57. unsigned long far cr3tab[] = {                /* CRC polynomial 0xedb88320 */
  58.           0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, 0x706af48fL, 0xe963a535L, 0x9e6495a3L,
  59.           0x0edb8832L, 0x79dcb8a4L, 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, 0x90bf1d91L,
  60.           0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L,
  61.           0x136c9856L, 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, 0xfa0f3d63L, 0x8d080df5L,
  62.           0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
  63.           0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L,
  64.           0x26d930acL, 0x51de003aL, 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, 0xb8bda50fL,
  65.           0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL,
  66.         0x76dc4190L, 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, 0x9fbfe4a5L, 0xe8b8d433L,
  67.         0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
  68.         0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L,
  69.         0x65b0d9c6L, 0x12b7e950L, 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, 0xfbd44c65L,
  70.         0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL,
  71.         0x4369e96aL, 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, 0xaa0a4c5fL, 0xdd0d7cc9L,
  72.         0x5005713cL, 0x270241aaL, 0xbe0b1010L, 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
  73.         0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL,
  74.         0xedb88320L, 0x9abfb3b6L, 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, 0x73dc1683L,
  75.         0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L,
  76.         0xf00f9344L, 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, 0x196c3671L, 0x6e6b06e7L,
  77.         0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
  78.         0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL,
  79.         0xd80d2bdaL, 0xaf0a1b4cL, 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, 0x4669be79L,
  80.         0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL,
  81.         0xc5ba3bbeL, 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, 0x2cd99e8bL, 0x5bdeae1dL,
  82.         0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
  83.         0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L,
  84.         0x86d3d2d4L, 0xf1d4e242L, 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, 0x18b74777L,
  85.         0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L,
  86.         0xa00ae278L, 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, 0x4969474dL, 0x3e6e77dbL,
  87.         0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
  88.           0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, 0xcdd70693L, 0x54de5729L, 0x23d967bfL,
  89.         0xb3667a2eL, 0xc4614ab8L, 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, 0x2d02ef8dL
  90. };
  91.  
  92. #define Z_32UpdateCRC(c,crc) (cr3tab[((int) crc ^ c) & 0xff] ^ ((crc >> 8) & 0x00FFFFFFL))
  93.  
  94. long crc_name (char *name)
  95. {
  96.    int i;
  97.    long crc;
  98.  
  99.     crc = 0xFFFFFFFFL;
  100.    for (i=0; i < strlen(name); i++)
  101.       crc = Z_32UpdateCRC (((unsigned short) name[i]), crc);
  102.  
  103.     return (crc);
  104. }
  105.  
  106. void Append_Backslash (char *s)
  107. {
  108.     int i;
  109.  
  110.     i = strlen(s) - 1;
  111.     if (s[i] != '\\')
  112.         strcat (s, "\\");
  113. }
  114.  
  115. void Get_Config_Info (void)
  116. {
  117.     int fd;
  118.     char linea[256], *p;
  119.  
  120.     fd = open (cfgname, O_RDONLY|O_BINARY);
  121.     if (fd == -1) {
  122.         if ((p=getenv ("LORA")) != NULL) {
  123.             strcpy (linea, p);
  124.             Append_Backslash (linea);
  125.             strcat (linea, cfgname);
  126.         }
  127.         fd = open (linea, O_RDONLY|O_BINARY);
  128.         if (fd == -1) {
  129.             printf ("\nCouldn't open DAT file: %s\a\n", strupr (cfgname));
  130.             exit (1);
  131.         }
  132.     }
  133.  
  134.     read (fd, &cfg, sizeof (struct _configuration));
  135.     close (fd);
  136. }
  137.  
  138. /* -----------------------------------------------------------------------
  139.  
  140.     Sezione di gestione della base messaggi Squish.
  141.  
  142.     ----------------------------------------------------------------------- */
  143. void Link_Squish_Areas (void)
  144. {
  145.     int fd;
  146.     unsigned int i, msgnum, m, prev, next, firsttime = 1;
  147.     long crc;
  148.     char subj[80], lwrite;
  149.     struct _sys tsys;
  150.     struct _minf minf;
  151.     MSG *sq_ptr;
  152.     MSGH *msgh;
  153.     XMSG xmsg;
  154.     MSGLINK *ml;
  155.  
  156.     minf.def_zone = 0;
  157.     if (MsgOpenApi (&minf))
  158.         return;
  159.  
  160.     clreol ();
  161.     printf(" * Linking Squish messages\n");
  162.  
  163.     sprintf (subj, "%sSYSMSG.DAT", cfg.sys_path);
  164.     fd = open (subj, O_RDONLY|O_BINARY);
  165.     if (fd == -1){
  166.         printf("! Unable to open SYSMSG.DAT\n");
  167.         exit (1);
  168.     }
  169.  
  170.     msgnum = 0;
  171.  
  172.     while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  173.         if ( !tsys.squish )
  174.             continue;
  175.         sq_ptr = MsgOpenArea (tsys.msg_path, MSGAREA_CRIFNEC, MSGTYPE_SQUISH);
  176.         if (sq_ptr == NULL){
  177.             printf("Unable to open %s area\n",tsys.msg_name);
  178.             continue;
  179.         }
  180.  
  181.         MsgLock (sq_ptr);
  182.  
  183.         msgnum = (int)MsgGetNumMsg (sq_ptr);
  184.         ml = (MSGLINK *)malloc (sizeof (MSGLINK) * msgnum);
  185.  
  186.         if (ml == NULL){
  187.             if (!firsttime) {
  188.                 gotoxy (wherex (), wherey () - 1);
  189.                 printf ("   ├\n");
  190.             }
  191.             else
  192.                 firsttime = 0;
  193.             if(!msgnum){
  194.                 clreol ();
  195.                 printf("   └─ %3d - %-25.25s - Empty\n", tsys.msg_num, tsys.msg_name);
  196.             }
  197.             else
  198.                 printf(" Unable to allocate msgmem: %u area: %s\n",msgnum,tsys.msg_name);
  199.             MsgUnlock (sq_ptr);
  200.             MsgCloseArea (sq_ptr);
  201.             continue;
  202.         }
  203.  
  204.         if (!firsttime) {
  205.             gotoxy (wherex (), wherey () - 1);
  206.             printf ("   ├\n");
  207.         }
  208.         else
  209.             firsttime = 0;
  210.  
  211.         clreol ();
  212.         printf("   └─ %3d - %-25.25s %-25.25s ", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "");
  213.  
  214.         for (i = 1; i <= msgnum; i++) {
  215.             msgh = MsgOpenMsg (sq_ptr, MOPEN_RW, (dword)i);
  216.             if (msgh == NULL)
  217.                 continue;
  218.  
  219.             if (MsgReadMsg (msgh, &xmsg, 0L, 0L, NULL, 0, NULL) == -1) {
  220.                 MsgCloseMsg (msgh);
  221.                 continue;
  222.             }
  223.  
  224.             strcpy (subj, strupr (xmsg.subj));
  225.             if (!strncmp (subj, "RE: ", 4))
  226.                 strcpy (subj, &subj[4]);
  227.             if (!strncmp (subj, "RE:", 3))
  228.                 strcpy (subj, &subj[3]);
  229.             ml[i - 1].crc = crc_name (subj);
  230.             ml[i - 1].num = i;
  231.  
  232.             MsgCloseMsg (msgh);
  233.         }
  234.  
  235.         for (i = 1; i <= msgnum; i++) {
  236.             msgh = MsgOpenMsg (sq_ptr, MOPEN_RW, (dword)i);
  237.             if (msgh == NULL)
  238.                 continue;
  239.  
  240.             if (MsgReadMsg (msgh, &xmsg, 0L, 0L, NULL, 0, NULL) == -1) {
  241.                 MsgCloseMsg (msgh);
  242.                 continue;
  243.             }
  244.  
  245.             prev = next = 0;
  246.             crc = ml[i - 1].crc;
  247.  
  248.             for (m = 0; m < msgnum; m++) {
  249.                 if (ml[m].num == i)
  250.                     continue;
  251.                 if (ml[m].crc == crc) {
  252.                     if (ml[m].num < i)
  253.                         prev = ml[m].num;
  254.                     else if (ml[m].num > i) {
  255.                         next = ml[m].num;
  256.                         break;
  257.                     }
  258.                 }
  259.             }
  260.  
  261.             lwrite = 0;
  262.  
  263.             if (prev && xmsg.replyto != MsgMsgnToUid (sq_ptr, (long)prev)) {
  264.                 xmsg.replyto = MsgMsgnToUid (sq_ptr, (long)prev);
  265.                 lwrite = 1;
  266.             }
  267.             else if (!prev && xmsg.replyto != 0) {
  268.                 xmsg.replyto = 0;
  269.                 lwrite = 1;
  270.             }
  271.  
  272.             if (next && xmsg.replies[0] != MsgMsgnToUid (sq_ptr, (long)next)) {
  273.                 xmsg.replies[0] = MsgMsgnToUid (sq_ptr, (long)next);
  274.                 lwrite = 1;
  275.             }
  276.             else if (!next && xmsg.replies[0] != 0) {
  277.                 xmsg.replies[0] = 0;
  278.                 lwrite = 1;
  279.             }
  280.  
  281.             if (lwrite)
  282.                 MsgWriteMsg (msgh, 1, &xmsg, NULL, 0, 0, 0, NULL);
  283.  
  284.             MsgCloseMsg (msgh);
  285.         }
  286.  
  287.         MsgUnlock (sq_ptr);
  288.         MsgCloseArea (sq_ptr);
  289.         free (ml);
  290.  
  291.         printf ("\n");
  292.     }
  293.  
  294.     close (fd);
  295. }
  296.  
  297. void Purge_Squish_Areas (void)
  298. {
  299.     int fdu, fd, last, i, msgnum, kill=0, nummsg, maxmsgs;
  300.     int yr, mo, dy, month[12], m, days, *lastr, lrpos;
  301.     char filename[80], firsttime = 1, mese[4];
  302.     long day_mess, day_now, tempo, pos;
  303.     struct tm *tim;
  304.     struct _sys tsys;
  305.     struct _minf minf;
  306.     struct _usr usr;
  307.     MSG *sq_ptr;
  308.     MSGH *msgh;
  309.     XMSG xmsg;
  310.     UMSGID waterid;
  311.  
  312.     char *mon[] = {
  313.         "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  314.         "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
  315.     };
  316.  
  317.     month[0] = 31;
  318.     month[1] = 28;
  319.     month[2] = 31;
  320.     month[3] = 30;
  321.     month[4] = 31;
  322.     month[5] = 30;
  323.     month[6] = 31;
  324.     month[7] = 31;
  325.     month[8] = 30;
  326.     month[9] = 31;
  327.     month[10] = 30;
  328.     month[11] = 31;
  329.  
  330.     tempo = time(0);
  331.     tim = localtime(&tempo);
  332.  
  333.     day_now = 365 * tim->tm_year;
  334.     for (m = 0; m < tim->tm_mon; m++)
  335.         day_now += month[m];
  336.     day_now += tim->tm_mday;
  337.  
  338.     minf.def_zone = 0;
  339.     if (MsgOpenApi (&minf))
  340.         return;
  341.  
  342.     clreol ();
  343.     printf(" * Purging Squish messages\n");
  344.  
  345.     sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  346.     fd = open (filename, O_RDONLY|O_BINARY);
  347.     if (fd == -1){
  348.         printf("! Unable to open SYSMSG.DAT\n");
  349.         exit (1);
  350.     }
  351.  
  352.     msgnum = last = 0;
  353.  
  354.     while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  355.         if ( !tsys.squish )
  356.             continue;
  357.  
  358.         sq_ptr = MsgOpenArea (tsys.msg_path, MSGAREA_CRIFNEC, MSGTYPE_SQUISH);
  359.         if (sq_ptr == NULL)
  360.             continue;
  361.         MsgLock (sq_ptr);
  362.  
  363.         msgnum = (int)MsgGetNumMsg (sq_ptr);
  364.         last = msgnum;
  365.  
  366.         if (msgnum == 0) {
  367.             MsgUnlock (sq_ptr);
  368.             MsgCloseArea (sq_ptr);
  369.             continue;
  370.         }
  371.  
  372.         msgnum++;
  373.         if ((lastr = (int *)malloc (msgnum * sizeof (int))) == NULL) {
  374.             MsgUnlock (sq_ptr);
  375.             MsgCloseArea (sq_ptr);
  376.             continue;
  377.         }
  378.         memset (lastr, 0, msgnum * sizeof (int));
  379.         msgnum--;
  380.  
  381.         if (!firsttime) {
  382.             gotoxy (wherex (), wherey () - 1);
  383.             printf ("   ├\n");
  384.         }
  385.         else
  386.             firsttime = 0;
  387.  
  388.         clreol ();
  389.         printf("   └─ %3d - %-23.23s %-23.23s ", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "");
  390.  
  391.         waterid = MsgMsgnToUid (sq_ptr, MsgGetHighWater (sq_ptr));
  392.         msgnum = (int)MsgGetNumMsg (sq_ptr);
  393.         nummsg = 1;
  394.         maxmsgs = last;
  395.         lrpos = 1;
  396.  
  397.         if ( tsys.max_msgs && tsys.max_msgs < msgnum )
  398.             kill = msgnum - tsys.max_msgs;
  399.  
  400.         for (i = 1; i <= last; i++) {
  401.             if (kill-- <= 0) {
  402.                 kill = 0;
  403.  
  404.                 msgh = MsgOpenMsg (sq_ptr, MOPEN_RW, (dword)i);
  405.                 if (msgh == NULL)
  406.                     continue;
  407.  
  408.                 if (MsgReadMsg (msgh, &xmsg, 0L, 0L, NULL, 0, NULL) == -1) {
  409.                     MsgCloseMsg (msgh);
  410.                     continue;
  411.                 }
  412.  
  413.                 MsgCloseMsg (msgh);
  414.  
  415.                 sscanf (xmsg.ftsc_date, "%2d %3s %2d", &dy, mese, &yr);
  416.                 mese[3] = '\0';
  417.                 for (mo = 0; mo < 12; mo++)
  418.                     if (!stricmp(mese, mon[mo]))
  419.                         break;
  420.                 if (mo == 12)
  421.                     mo = 0;
  422.  
  423.                 day_mess = 365 * yr;
  424.                 for (m = 0; m < mo; m++)
  425.                     day_mess += month[m];
  426.                 day_mess += dy;
  427.  
  428.                 days = (int)(day_now - day_mess);
  429.  
  430.                 if ( days > tsys.max_age && tsys.max_age != 0 ) {
  431.                     MsgKillMsg (sq_ptr, (dword)i);
  432.                     i--;
  433.                     last--;
  434.                 }
  435.                 else if ( ((xmsg.attr & MSGREAD) && (xmsg.attr & MSGPRIVATE)) && days > tsys.age_rcvd && tsys.age_rcvd != 0) {
  436.                     MsgKillMsg (sq_ptr, (dword)i);
  437.                     i--;
  438.                     last--;
  439.                 }
  440.                 else
  441.                     lastr[lrpos] = i;
  442.             }
  443.             else {
  444.                 MsgKillMsg (sq_ptr, (dword)i);
  445.                 i--;
  446.                 last--;
  447.             }
  448.  
  449.             if ((lrpos++ % 5) == 0)
  450.                 printf ("%4d / %-4d\b\b\b\b\b\b\b\b\b\b\b", nummsg, maxmsgs);
  451.             nummsg++;
  452.         }
  453.  
  454.         printf ("%4d / %-4d %4d\b\b\b\b\b\b\n", nummsg - 1, maxmsgs, (nummsg-1)-last);
  455.  
  456.         if (waterid) {
  457.             waterid = MsgUidToMsgn (sq_ptr, waterid, UID_PREV);
  458.             if (waterid)
  459.                 MsgSetHighWater (sq_ptr, waterid);
  460.         }
  461.  
  462.         MsgUnlock (sq_ptr);
  463.         MsgCloseArea (sq_ptr);
  464.  
  465.         if (last < maxmsgs) {
  466.             sprintf (filename, "%s.BBS", cfg.user_file);
  467.             fdu = open (filename, O_RDWR | O_BINARY);
  468.             pos = tell (fdu);
  469.  
  470.             while (read(fdu, (char *) &usr, sizeof(struct _usr)) == sizeof(struct _usr)) {
  471.                 for (i = 0; i < MAXLREAD; i++)
  472.                     if (usr.lastread[i].area == tsys.msg_num)
  473.                         break;
  474.  
  475.                 if (i < MAXLREAD) {
  476.                     m = usr.lastread[i].msg_num;
  477.                     if (m > msgnum)
  478.                         m = msgnum;
  479.                     if (m < 0)
  480.                         m = 0;
  481.                     while (m > 0 && lastr[m] == 0)
  482.                         m--;
  483.                     usr.lastread[i].msg_num = lastr[m];
  484.  
  485.                     lseek (fdu, pos, 0);
  486.                     write (fdu, (char *) &usr, sizeof(struct _usr));
  487.                 }
  488.                 else {
  489.                     for (i = 0; i < MAXDLREAD; i++)
  490.                         if (usr.dynlastread[i].area == tsys.msg_num)
  491.                             break;
  492.  
  493.                     if (i < MAXDLREAD) {
  494.                         m = usr.dynlastread[i].msg_num;
  495.                         if (m > msgnum)
  496.                             m = msgnum;
  497.                         if (m < 0)
  498.                             m = 0;
  499.                         while (m > 0 && lastr[m] == 0)
  500.                             m--;
  501.                         usr.dynlastread[i].msg_num = lastr[m];
  502.  
  503.                         lseek (fdu, pos, 0);
  504.                         write (fdu, (char *) &usr, sizeof (struct _usr));
  505.                     }
  506.                 }
  507.  
  508.                 pos = tell (fdu);
  509.             }
  510.  
  511.             close (fdu);
  512.  
  513.             if (lastr != NULL)
  514.                 free (lastr);
  515.  
  516. //            printf ("\n");
  517.         }
  518.     }
  519.  
  520.     close (fd);
  521. }
  522.  
  523. void Pack_Squish_Areas (void)
  524. {
  525.     int fd, fd2, i, msgnum, ctrlen, m, msgl, waterid;
  526.     char filename[80], destname[80], *kludge, *text, farea = 1;
  527.     struct _sys tsys;
  528.     struct _minf minf;
  529.     MSG *sq_ptr, *sq_dest;
  530.     XMSG xmsg;
  531.     MSGH *sq_msgh, *msgh_dest;
  532.     long textlen, fpos, *sql;
  533.  
  534.     minf.def_zone = 0;
  535.     if (MsgOpenApi (&minf))
  536.         return;
  537.  
  538.     clreol ();
  539.     printf(" * Packing Squish messages\n");
  540.  
  541.     sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  542.     fd = open (filename, O_RDONLY|O_BINARY);
  543.     if (fd == -1)
  544.         exit (1);
  545.  
  546.     while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  547.         if ( !tsys.squish )
  548.             continue;
  549.  
  550.         sq_ptr = MsgOpenArea (tsys.msg_path, MSGAREA_CRIFNEC, MSGTYPE_SQUISH);
  551.         if (sq_ptr == NULL)
  552.             continue;
  553.         MsgLock (sq_ptr);
  554.  
  555.         if ((msgnum = (int)MsgGetNumMsg (sq_ptr)) > 0) {
  556.             strcpy (filename, tsys.msg_path);
  557.             strcat (filename, ".SQL");
  558.  
  559.             sql = NULL;
  560.  
  561.             fd2 = open (filename, O_RDONLY|O_BINARY);
  562.             if (fd2 != -1) {
  563.                 sql = (long *)malloc ((unsigned int)filelength (fd2));
  564.                 if (sql != NULL) {
  565.                     read (fd2, sql, (unsigned int)filelength (fd2));
  566.                     msgl = (int)(filelength (fd2) / sizeof (long));
  567.                     for (i = 0; i < msgl; i++)
  568.                         sql[i] = MsgUidToMsgn (sq_ptr, sql[i], UID_PREV);
  569.                 }
  570.                 close (fd2);
  571.             }
  572.  
  573. //            else {
  574. //                printf("! Unable to open %s (orig)\n",filename);
  575. //                MsgUnlock (sq_ptr);
  576. //                MsgCloseArea (sq_ptr);
  577. //                continue;
  578. //            }
  579.  
  580.             strcpy (filename, tsys.msg_path);
  581.             filename[strlen (filename) - 1] = '!';
  582.  
  583.             if (!farea) {
  584.                 gotoxy (wherex (), wherey () - 1);
  585.                 printf("   ├\n");
  586.             }
  587.             else
  588.                 farea = 0;
  589.  
  590.             clreol ();
  591.             printf("   └─ %3d - %-25.25s %-25.25s ", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "");
  592.  
  593.             sq_dest = MsgOpenArea (filename, MSGAREA_CRIFNEC, MSGTYPE_SQUISH);
  594.             MsgLock (sq_dest);
  595.             waterid = (int)MsgGetHighWater (sq_ptr);
  596.             text = (char *)malloc (16384);
  597.  
  598.             for (m = 0; m < msgnum; m++) {
  599.                 sq_msgh = MsgOpenMsg (sq_ptr, MOPEN_READ, (long )m + 1);
  600.                 if (sq_msgh == NULL)
  601.                     continue;
  602.  
  603.                 if ((m % 5) == 0)
  604.                     printf ("%4d / %-4d\b\b\b\b\b\b\b\b\b\b\b", m, msgnum);
  605.  
  606.                 if (MsgReadMsg (sq_msgh, &xmsg, 0L, 0L, NULL, 0, NULL) == -1) {
  607.                     MsgCloseMsg (sq_msgh);
  608.                     continue;
  609.                 }
  610.  
  611.                 ctrlen = (int )MsgGetCtrlLen (sq_msgh);
  612.                 kludge = (char *)malloc (ctrlen + 1);
  613.                 textlen = MsgGetTextLen (sq_msgh);
  614.                 msgh_dest = MsgOpenMsg (sq_dest, MOPEN_CREATE, 0L);
  615.  
  616.                 MsgReadMsg (sq_msgh, &xmsg, 0L, 0L, NULL, ctrlen, kludge);
  617.                 MsgWriteMsg (msgh_dest, 0, &xmsg, NULL, 0L, textlen, (long)ctrlen, kludge);
  618.                 fpos = 0L;
  619.  
  620.                 do {
  621.                     i = (int)MsgReadMsg (sq_msgh, NULL, fpos, 16384L, text, 0, NULL);
  622.                     fpos += (long)i;
  623.  
  624.                     MsgWriteMsg (msgh_dest, 1, NULL, text, (long)i, textlen, 0L, NULL);
  625.                 } while (i == 16384);
  626.  
  627.                 MsgCloseMsg (msgh_dest);
  628.                 MsgCloseMsg (sq_msgh);
  629.             }
  630.  
  631.             printf ("%4d / %-4d\b\b\b\b\b\b\b\b\b\b\b\n", m, msgnum);
  632.  
  633.             if (waterid)
  634.                 MsgSetHighWater (sq_dest, waterid);
  635.  
  636.             free (text);
  637.  
  638.             if (sql != NULL) {
  639.                 strcpy (filename, tsys.msg_path);
  640.                 strcat (filename, ".SQL");
  641.  
  642.                 for (i = 0; i < msgl; i++) {
  643.                     if (sql[i])
  644.                         sql[i] = MsgMsgnToUid (sq_dest, sql[i]);
  645.                 }
  646.  
  647.                 fd2 = open (filename, O_WRONLY|O_BINARY);
  648.  
  649.                 if(fd2==-1){
  650.                     printf(" ! Unable to open %s (dest)\n",filename);
  651.                     MsgUnlock (sq_ptr);
  652.                     MsgCloseArea (sq_ptr);
  653.                     MsgUnlock (sq_dest);
  654.                     MsgCloseArea (sq_dest);
  655.                     continue;
  656.                 }
  657.  
  658.                 write (fd2, sql, msgl * sizeof (long));
  659.                 close (fd2);
  660.  
  661.                 free (sql);
  662.                 sql = NULL;
  663.             }
  664.  
  665.             MsgUnlock (sq_dest);
  666.             MsgCloseArea (sq_dest);
  667.         }
  668.  
  669.         MsgUnlock (sq_ptr);
  670.         MsgCloseArea (sq_ptr);
  671.  
  672.         strcpy (filename, tsys.msg_path);
  673.         i = strlen (filename);
  674.         filename[i - 1] = '!';
  675.         strcpy (destname, tsys.msg_path);
  676.  
  677.         strcpy (&destname[i], ".SQD");
  678.         unlink (destname);
  679.         strcpy (&filename[i], ".SQD");
  680.         rename (filename, destname);
  681.  
  682.         strcpy (&destname[i], ".SQI");
  683.         unlink (destname);
  684.         strcpy (&filename[i], ".SQI");
  685.         rename (filename, destname);
  686.     }
  687.  
  688.     close (fd);
  689. }
  690.  
  691. /* -----------------------------------------------------------------------
  692.  
  693.     Sezione di gestione della base messaggi Fido *.MSG.
  694.  
  695.     ----------------------------------------------------------------------- */
  696. int Scan_Fido_Area (char *path, int *first_m, int *last_m)
  697. {
  698.     int i, first, last, msgnum;
  699.     char filename[80], *p;
  700.     struct ffblk blk;
  701.  
  702.     first = 0;
  703.     last = 0;
  704.     msgnum = 0;
  705.  
  706.     sprintf(filename, "%s*.MSG", path);
  707.  
  708.     if (!findfirst(filename, &blk, 0))
  709.         do {
  710.             if ((p = strchr(blk.ff_name,'.')) != NULL)
  711.                 *p = '\0';
  712.  
  713.             i = atoi(blk.ff_name);
  714.             if (last < i || !last)
  715.                 last = i;
  716.             if (first > i || !first)
  717.                 first = i;
  718.             msgnum++;
  719.         } while (!findnext(&blk));
  720.  
  721.     *first_m = first;
  722.     *last_m = last;
  723.  
  724.    return (msgnum);
  725. }
  726.  
  727. #define MSGREAD    0x0004
  728.  
  729. void Create_Fido_Index (void)
  730. {
  731.    FILE *fp;
  732.    int fd, fdidx, fdmsg, i;
  733.    char filename[80], *p;
  734.    struct ffblk blk;
  735.    struct _sys tsys;
  736.    struct _msg msg;
  737.    struct _mail mail;
  738.  
  739.    clreol ();
  740.    printf(" * Creating Fido *.MSG index\n");
  741.  
  742.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  743.    fd = open (filename, O_RDONLY|O_BINARY);
  744.    if (fd == -1)
  745.       exit (1);
  746.  
  747.    sprintf (filename, "%sMSGTOIDX.DAT", cfg.sys_path);
  748.    fdidx = open (filename, O_WRONLY|O_BINARY|O_CREAT|O_TRUNC, S_IREAD|S_IWRITE);
  749.    if (fdidx == -1)
  750.       exit (1);
  751.    fp = fdopen (fdidx, "wb");
  752.  
  753.    memset (&mail, 0, sizeof (struct _mail));
  754.  
  755.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  756.       if ( tsys.quick_board || tsys.pip_board || tsys.squish || tsys.gold_board)
  757.             continue;
  758.  
  759.       mail.area = tsys.msg_num;
  760.  
  761.       sprintf (filename, "%s*.MSG", tsys.msg_path);
  762.       if (!findfirst (filename, &blk, 0))
  763.          do {
  764.             if ((p = strchr (blk.ff_name, '.')) != NULL)
  765.                *p = '\0';
  766.  
  767.             i = atoi (blk.ff_name);
  768.             mail.msg_num = i;
  769.  
  770.             sprintf (filename, "%s%d.MSG", tsys.msg_path, i);
  771.             fdmsg = open (filename, O_RDONLY|O_BINARY);
  772.             if (fdmsg == -1)
  773.                continue;
  774.             read (fdmsg, &msg, sizeof (struct _msg));
  775.             close (fdmsg);
  776.  
  777.             if (!(msg.attr & MSGREAD)) {
  778.                mail.to = crc_name (msg.to);
  779.                fwrite (&mail, sizeof (struct _mail), 1, fp);
  780.             }
  781.          } while (!findnext(&blk));
  782.    }
  783.  
  784.    fclose (fp);
  785.    close (fd);
  786. }
  787.  
  788. void Fido_Renum (char *msg_path, int first, int last, int area_n)
  789. {
  790.    unsigned long p;
  791.    int fdm, fd, m, i, x, msg[1000], flag1, flag2, flag, area;
  792.     long pos;
  793.    char filename [60], newname [40], curdir[80];
  794.    struct _msg mesg;
  795.    struct _usr usr;
  796.  
  797.    getcwd (curdir, 79);
  798.  
  799.    if (msg_path[1] == ':')
  800.       setdisk (toupper (msg_path[0]) - 'A');
  801.    msg_path[strlen(msg_path)-1] = '\0';
  802.    chdir(msg_path);
  803.    msg_path[strlen(msg_path)] = '\\';
  804.  
  805.    m = flag = 0;
  806.  
  807.    for (i = first; i <= last; i++) {
  808.       sprintf(filename, "%d.MSG", i);
  809.       fdm = open(filename, O_RDWR | O_BINARY);
  810.       if (fdm != -1) {
  811.          close(fdm);
  812.  
  813.          msg[m++] = i;
  814.  
  815.          if (i != m) {
  816.             sprintf(newname, "%d.MSG", m);
  817.             flag = 1;
  818.             rename(filename, newname);
  819.          }
  820.       }
  821.    }
  822.  
  823.    if (!flag) {
  824.       setdisk (toupper (curdir[0]) - 'A');
  825.       chdir(curdir);
  826.       return;
  827.     }
  828.  
  829.    for (i = 1; i <= m; i++) {
  830.       sprintf(filename, "%d.MSG", i);
  831.       fdm = open(filename, O_RDWR | O_BINARY);
  832.       read(fdm, (char *) &mesg, sizeof(struct _msg));
  833.       flag1 = flag2 = 0;
  834.       for (x = 0; x < m; x++) {
  835.          if (!flag1 && mesg.up == msg[x]) {
  836.             mesg.up = x + 1;
  837.             flag1 = 1;
  838.          }
  839.          if (!flag2 && mesg.reply == msg[x]) {
  840.             mesg.reply = x + 1;
  841.             flag2 = 1;
  842.          }
  843.          if (flag1 && flag2)
  844.             break;
  845.       }
  846.       if (!flag1)
  847.          mesg.up = 0;
  848.       if (!flag2)
  849.          mesg.reply = 0;
  850.  
  851.       lseek(fdm, 0L, 0);
  852.       write(fdm, (char *) &mesg, sizeof(struct _msg));
  853.       close(fdm);
  854.    }
  855.  
  856.    fd = open ("LASTREAD", O_RDWR | O_BINARY);
  857.    if (fd != -1) {
  858.       while (read(fd, (char *) &i, 2) == 2) {
  859.          p = tell(fd) - 2L;
  860.          flag1 = 0;
  861.          for (x = 0; x < m; x++)
  862.                 if (msg[x] > flag1 && msg[x] <= i)
  863.                flag1 = x + 1;
  864.          i = flag1;
  865.          lseek(fd, p, 0);
  866.          write(fd, (char *) &i, 2);
  867.       }
  868.       close(fd);
  869.    }
  870.  
  871.    close(fd);
  872.  
  873.    setdisk (toupper (curdir[0]) - 'A');
  874.    chdir (curdir);
  875.  
  876.    sprintf (filename, "%s.BBS", cfg.user_file);
  877.    fd = open(filename, O_RDWR | O_BINARY);
  878.    pos = tell (fd);
  879.  
  880.    while (read(fd, (char *) &usr, sizeof(struct _usr)) == sizeof(struct _usr)) {
  881.       for (area=0; area<MAXLREAD; area++)
  882.          if (usr.lastread[area].area == area_n)
  883.             break;
  884.  
  885.       if (area < MAXLREAD) {
  886.          flag1 = 0;
  887.  
  888.          for (x = 0; x < m; x++)
  889.             if (msg[x] > flag1 && msg[x] <= usr.lastread[area].msg_num)
  890.                flag1 = x + 1;
  891.  
  892.          usr.lastread[area].msg_num = flag1;
  893.  
  894.          lseek(fd, pos, 0);
  895.          write(fd, (char *) &usr, sizeof(struct _usr));
  896.       }
  897.         else {
  898.          for (area=0; area<MAXDLREAD; area++)
  899.             if (usr.dynlastread[area].area == area_n)
  900.                break;
  901.  
  902.          if (area < MAXDLREAD) {
  903.             flag1 = 0;
  904.  
  905.             for (x = 0; x < m; x++)
  906.                if (msg[x] > flag1 && msg[x] <= usr.dynlastread[area].msg_num)
  907.                   flag1 = x + 1;
  908.  
  909.             usr.dynlastread[area].msg_num = flag1;
  910.  
  911.             lseek(fd, pos, 0);
  912.             write(fd, (char *) &usr, sizeof(struct _usr));
  913.          }
  914.       }
  915.  
  916.       pos = tell (fd);
  917.    }
  918.  
  919.    close(fd);
  920. }
  921.  
  922. void Renum_Fido_Areas (void)
  923. {
  924.    int fd, first, last, msgnum;
  925.    char filename[60], farea = 1;
  926.    struct _sys tsys;
  927.  
  928.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  929.    fd = open(filename, O_RDONLY|O_BINARY);
  930.    if (fd == -1)
  931.       exit (1);
  932.  
  933.    clreol ();
  934.    printf(" * Renumber Fido *.MSG messages\n");
  935.  
  936.    first = last = 0;
  937.  
  938.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  939.       if ( tsys.quick_board || tsys.pip_board || tsys.squish || tsys.gold_board)
  940.          continue;
  941.  
  942.       msgnum = Scan_Fido_Area (tsys.msg_path, &first, &last);
  943.  
  944.       if (!farea) {
  945.          gotoxy (wherex (), wherey () - 1);
  946.          printf("   ├\n");
  947.       }
  948.       else
  949.          farea = 0;
  950.  
  951.       printf("   └─ %3d - %-25.25s %-25.25s %d Msg.\n", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  952.  
  953.       Fido_Renum (tsys.msg_path, first, last, tsys.msg_num);
  954.    }
  955.  
  956.    close(fd);
  957. }
  958.  
  959. void Kill_by_Age (int max_age, int age_rcvd, int first, int last)
  960. {
  961.    int fd, yr, mo, dy, i, month[12], m, days;
  962.    char mese[4], filename [40];
  963.    long day_mess, day_now;
  964.    struct tm *tim;
  965.    struct _msg msg;
  966.    long tempo;
  967.  
  968.    char *mon[] = {
  969.       "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  970.       "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
  971.    };
  972.  
  973.    month[0] = 31;
  974.    month[1] = 28;
  975.    month[2] = 31;
  976.    month[3] = 30;
  977.    month[4] = 31;
  978.    month[5] = 30;
  979.    month[6] = 31;
  980.    month[7] = 31;
  981.    month[8] = 30;
  982.    month[9] = 31;
  983.    month[10] = 30;
  984.    month[11] = 31;
  985.  
  986.    tempo = time(0);
  987.    tim = localtime(&tempo);
  988.  
  989.    day_now = 365 * tim->tm_year;
  990.    for (m = 0; m < tim->tm_mon; m++)
  991.       day_now += month[m];
  992.    day_now += tim->tm_mday;
  993.  
  994.    for (i = first; i <= last; i++) {
  995.       sprintf(filename, "%d.MSG", i);
  996.       fd = open(filename, O_RDONLY | O_BINARY);
  997.       if (fd == -1)
  998.          continue;
  999.       read(fd, (char *) &msg, sizeof(struct _msg));
  1000.       close(fd);
  1001.  
  1002.         sscanf(msg.date, "%2d %3s %2d", &dy, mese, &yr);
  1003.       mese[3] = '\0';
  1004.       for (mo = 0; mo < 12; mo++)
  1005.          if (!stricmp(mese, mon[mo]))
  1006.             break;
  1007.       if (mo == 12)
  1008.          mo = 0;
  1009.  
  1010.       day_mess = 365 * yr;
  1011.       for (m = 0; m < mo; m++)
  1012.          day_mess += month[m];
  1013.       day_mess += dy;
  1014.  
  1015.       days = (int)(day_now - day_mess);
  1016.  
  1017.       if ( days > max_age && max_age != 0 )
  1018.             unlink(filename);
  1019.  
  1020.         if ( ((msg.attr & MSGREAD) && (msg.attr & MSGPRIVATE)) &&
  1021.               days > age_rcvd && age_rcvd != 0)
  1022.             unlink(filename);
  1023.     }
  1024. }
  1025.  
  1026. void Link_Fido_Areas (void)
  1027. {
  1028.     int fds, fd, first, last, i, m, msgnum, prev, next, lwrite,firsttime=1;
  1029.     char filename [80], curdir [80], subj[72];
  1030.     long crc;
  1031.     struct _sys tsys;
  1032.     struct _msg msg;
  1033.     MSGLINK *ml;
  1034.  
  1035.     getcwd (curdir, 79);
  1036.  
  1037.     clreol ();
  1038.     printf(" * Linking Fido *.MSG messages\n");
  1039.  
  1040.     sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  1041.     fds = open(filename, O_RDONLY|O_BINARY);
  1042.     if (fds == -1)
  1043.         exit (1);
  1044.  
  1045.     msgnum = first = last = 0;
  1046.  
  1047.     while ( read (fds, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  1048.         if ( tsys.quick_board || tsys.pip_board || tsys.squish || tsys.gold_board)
  1049.             continue;
  1050.  
  1051.         msgnum = Scan_Fido_Area (tsys.msg_path, &first, &last);
  1052.         ml = (MSGLINK *)malloc (sizeof (MSGLINK) * last);
  1053.         if (ml == NULL)
  1054.             continue;
  1055.  
  1056.         if (tsys.msg_path[1] == ':')
  1057.             setdisk (toupper (tsys.msg_path[0]) - 'A');
  1058.         tsys.msg_path[strlen(tsys.msg_path)-1] = '\0';
  1059.         chdir(tsys.msg_path);
  1060.         tsys.msg_path[strlen(tsys.msg_path)] = '\\';
  1061.  
  1062.         if (first == 1 && tsys.echomail)
  1063.             first++;
  1064.  
  1065.         if (!firsttime) {
  1066.             gotoxy (wherex (), wherey () - 1);
  1067.             printf ("   ├\n");
  1068.         }
  1069.         else
  1070.             firsttime = 0;
  1071.  
  1072.         clreol ();
  1073.         printf("   └─ %3d - %-25.25s %-25.25s %d Msg.", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  1074.  
  1075.  
  1076.         for (i = first; i <= last; i++) {
  1077.             sprintf (filename, "%d.MSG", i);
  1078.             fd = open (filename, O_RDONLY|O_BINARY);
  1079.             if (fd == -1)
  1080.                 continue;
  1081.             read (fd, &msg, sizeof (struct _msg));
  1082.             close (fd);
  1083.  
  1084.             strcpy (subj, strupr (msg.subj));
  1085.             if (!strncmp (subj, "RE: ", 4))
  1086.                 strcpy (subj, &subj[4]);
  1087.             if (!strncmp (subj, "RE:", 3))
  1088.                 strcpy (subj, &subj[3]);
  1089.             ml[i - 1].crc = crc_name (subj);
  1090.             ml[i - 1].num = i;
  1091.         }
  1092.  
  1093.         for (i = first; i <= last; i++) {
  1094.             sprintf (filename, "%d.MSG", i);
  1095.             fd = open (filename, O_RDWR|O_BINARY);
  1096.             if (fd == -1)
  1097.                 continue;
  1098.             read (fd, &msg, sizeof (struct _msg));
  1099.  
  1100.             prev = next = 0;
  1101.             crc = ml[i - 1].crc;
  1102.  
  1103.             for (m = first - 1; m < last; m++) {
  1104.                 if (ml[m].num == i)
  1105.                     continue;
  1106.                 if (ml[m].crc == crc) {
  1107.                     if (ml[m].num < i)
  1108.                         prev = ml[m].num;
  1109.                     else if (ml[m].num > i) {
  1110.                         next = ml[m].num;
  1111.                         break;
  1112.                     }
  1113.                 }
  1114.             }
  1115.  
  1116.             lwrite = 0;
  1117.  
  1118.             if (next && msg.up != next) {
  1119.                 msg.up = next;
  1120.                 lwrite = 1;
  1121.             }
  1122.             else if (!next && msg.up != 0) {
  1123.                 msg.up = 0;
  1124.                 lwrite = 1;
  1125.             }
  1126.  
  1127.             if (prev && msg.reply != prev) {
  1128.                 msg.reply = prev;
  1129.                 lwrite = 1;
  1130.             }
  1131.             else if (!prev && msg.reply != 0) {
  1132.                 msg.reply = 0;
  1133.                 lwrite = 1;
  1134.             }
  1135.  
  1136.             if (lwrite) {
  1137.                 lseek (fd, 0L, SEEK_SET);
  1138.                 write (fd, &msg, sizeof (struct _msg));
  1139.             }
  1140.  
  1141.             close (fd);
  1142.         }
  1143.         printf ("\n");
  1144.     }
  1145.  
  1146.     close (fds);
  1147.  
  1148.     setdisk (toupper (curdir[0]) - 'A');
  1149.     chdir (curdir);
  1150. }
  1151.  
  1152. void Purge_Fido_Areas (int renum)
  1153. {
  1154.     int fd, first, last, i, msgnum, kill,firsttime=1;
  1155.     char filename [80], curdir [80];
  1156.     struct _sys tsys;
  1157.  
  1158.     getcwd (curdir, 79);
  1159.  
  1160.    clreol ();
  1161.    printf(" * Purging Fido *.MSG messages\n");
  1162.  
  1163.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  1164.    fd = open(filename, O_RDONLY|O_BINARY);
  1165.    if (fd == -1)
  1166.       exit (1);
  1167.  
  1168.    msgnum = first = last = 0;
  1169.  
  1170.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  1171.       if ( tsys.quick_board || tsys.pip_board || tsys.squish || tsys.gold_board)
  1172.          continue;
  1173.  
  1174.       msgnum = Scan_Fido_Area (tsys.msg_path, &first, &last);
  1175.  
  1176.       if (first == 1 && tsys.echomail)
  1177.          first++;
  1178.  
  1179.       if (tsys.msg_path[1] == ':')
  1180.          setdisk (toupper (tsys.msg_path[0]) - 'A');
  1181.       tsys.msg_path[strlen(tsys.msg_path)-1] = '\0';
  1182.       chdir(tsys.msg_path);
  1183.         tsys.msg_path[strlen(tsys.msg_path)] = '\\';
  1184.  
  1185.         if (!firsttime) {
  1186.             gotoxy (wherex (), wherey () - 1);
  1187.             printf ("   ├\n");
  1188.         }
  1189.         else
  1190.             firsttime = 0;
  1191.  
  1192.         clreol ();
  1193.         printf("   └─ %3d - %-25.25s %-25.25s %d Msg.", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  1194.  
  1195.         if ( tsys.max_age || tsys.age_rcvd )
  1196.             Kill_by_Age (tsys.max_age, tsys.age_rcvd, first, last);
  1197.  
  1198.         setdisk (toupper (curdir[0]) - 'A');
  1199.         chdir (curdir);
  1200.  
  1201.         msgnum = Scan_Fido_Area (tsys.msg_path, &first, &last);
  1202.  
  1203.         if (tsys.msg_path[1] == ':')
  1204.             setdisk (toupper (tsys.msg_path[0]) - 'A');
  1205.         tsys.msg_path[strlen(tsys.msg_path)-1] = '\0';
  1206.         chdir(tsys.msg_path);
  1207.         tsys.msg_path[strlen(tsys.msg_path)] = '\\';
  1208.  
  1209.         if ( tsys.max_msgs && tsys.max_msgs < msgnum ) {
  1210.             kill = msgnum - tsys.max_msgs;
  1211.  
  1212.             for (i = first; i <= last; i++) {
  1213.                 sprintf (filename, "%d.MSG", i);
  1214.                 unlink (filename);
  1215.  
  1216.                 if (--kill <= 0)
  1217.                     break;
  1218.             }
  1219.         }
  1220.  
  1221.         if (renum) {
  1222.             setdisk (toupper (curdir[0]) - 'A');
  1223.             chdir (curdir);
  1224.             Fido_Renum (tsys.msg_path, first, last, tsys.msg_num);
  1225.         }
  1226.         printf("\n");
  1227.     }
  1228.  
  1229.     close (fd);
  1230.  
  1231.     setdisk (toupper (curdir[0]) - 'A');
  1232.     chdir (curdir);
  1233. }
  1234.  
  1235. /* -----------------------------------------------------------------------
  1236.  
  1237.     Sezione di gestione della base messaggi Hudson (QuickBBS).
  1238.  
  1239.     ----------------------------------------------------------------------- */
  1240. void Create_Quick_Index (int xlink, int unknow, int renum)
  1241. {
  1242.     int fd, fdidx, fdto, m, flag;
  1243.     short know[200];
  1244.     char filename[60];
  1245.     word msgnum;
  1246.     long pos;
  1247.     struct _sys tsys;
  1248.     struct _msghdr msghdr;
  1249.     struct _msgidx msgidx;
  1250.     struct _msginfo msginfo;
  1251.  
  1252.     msgnum = 1;
  1253. //    if (xlink);
  1254.  
  1255.     if (unknow) {
  1256.         for (m = 0; m < 200; m++)
  1257.             know[m] = 0;
  1258.  
  1259.         sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  1260.         fd = open(filename, O_RDONLY|O_BINARY);
  1261.         if (fd == -1)
  1262.             exit (1);
  1263.  
  1264.         while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  1265.             if ( !tsys.quick_board )
  1266.                 continue;
  1267.  
  1268.             know[tsys.quick_board-1] = 1;
  1269.         }
  1270.  
  1271.         close (fd);
  1272.     }
  1273.  
  1274.     sprintf (filename, "%sMSGHDR.BBS", cfg.quick_msgpath);
  1275.     fd = open (filename, O_RDWR|O_BINARY);
  1276.     if (fd == -1)
  1277.         exit (1);
  1278.  
  1279.     printf(" * Regenerating message base indices\n");
  1280.  
  1281.     pos = tell (fd);
  1282.  
  1283.     memset((char *)&msginfo, 0, sizeof(struct _msginfo));
  1284.  
  1285.     sprintf (filename, "%sMSGIDX.BBS", cfg.quick_msgpath);
  1286.     fdidx = open(filename,O_WRONLY|O_BINARY|O_TRUNC);
  1287.  
  1288.     sprintf (filename, "%sMSGTOIDX.BBS", cfg.quick_msgpath);
  1289.     fdto = open(filename,O_WRONLY|O_BINARY|O_TRUNC);
  1290.  
  1291.     while (read(fd, (char *)&msghdr, sizeof (struct _msghdr)) == sizeof (struct _msghdr)) {
  1292.         flag = 0;
  1293.  
  1294.         if (unknow) {
  1295.             if (know[msghdr.board-1] != 1) {
  1296.                 msghdr.msgattr |= Q_RECKILL;
  1297.                 if (know[msghdr.board-1] != 2) {
  1298.                     printf(" * Unknow board #%d\n", msghdr.board);
  1299.                     know[msghdr.board-1] = 2;
  1300.                 }
  1301.                 flag = 1;
  1302.             }
  1303.         }
  1304.  
  1305.         if (renum)
  1306.             msghdr.msgnum = msgnum++;
  1307.         else
  1308.             msgnum++;
  1309.  
  1310.         if (renum || flag) {
  1311.             lseek (fd, pos, SEEK_SET);
  1312.             write (fd, (char *)&msghdr, sizeof (struct _msghdr));
  1313.             pos = tell (fd);
  1314.         }
  1315.  
  1316.         if (flag) {
  1317.             msgidx.msgnum = 0;
  1318.             write (fdto, "\x0B* Deleted *                        ", 36);
  1319.         }
  1320.         else {
  1321.             write (fdto, (char *)&msghdr.whoto, sizeof (struct _msgtoidx));
  1322.             msgidx.msgnum = msghdr.msgnum;
  1323.         }
  1324.  
  1325.         msgidx.board = msghdr.board;
  1326.         write (fdidx, (char *)&msgidx, sizeof (struct _msgidx));
  1327.  
  1328.         msginfo.totalmsgs++;
  1329.  
  1330.         if (!msginfo.lowmsg)
  1331.             msginfo.lowmsg = msghdr.msgnum;
  1332.  
  1333.         if (msginfo.lowmsg > msghdr.msgnum)
  1334.             msginfo.lowmsg = msghdr.msgnum;
  1335.         if (msginfo.highmsg < msghdr.msgnum)
  1336.             msginfo.highmsg = msghdr.msgnum;
  1337.  
  1338.         if (!flag)
  1339.             msginfo.totalonboard[msgidx.board-1]++;
  1340.     }
  1341.  
  1342.     close (fdto);
  1343.     close (fdidx);
  1344.     close (fd);
  1345.  
  1346.     sprintf (filename, "%sMSGINFO.BBS", cfg.quick_msgpath);
  1347.     fd = open(filename,O_WRONLY|O_BINARY);
  1348.     write(fd, (char *)&msginfo, sizeof(struct _msginfo));
  1349.     close (fd);
  1350. }
  1351.  
  1352. void Renum_Quick_Areas (void)
  1353. {
  1354.     int fd, fdidx;
  1355.     char filename[60];
  1356.     word msgnum, *lastr, *newnum, lrpos, i, m;
  1357.     long pos;
  1358.     struct _msghdr msghdr;
  1359.     struct _msgidx msgidx;
  1360.     struct _msginfo msginfo;
  1361.     struct _qlastread lr;
  1362.  
  1363.     printf(" * Renumber QuickBBS messages\n");
  1364.  
  1365.     sprintf (filename, "%sMSGINFO.BBS", cfg.quick_msgpath);
  1366.     fd = open (filename,O_RDONLY|O_BINARY);
  1367.     read (fd, (char *)&msginfo, sizeof(struct _msginfo));
  1368.     close (fd);
  1369.  
  1370.     if(!msginfo.totalmsgs){
  1371.         printf(" * No Messages in Hudson base\n");
  1372.         return;
  1373.     }
  1374.  
  1375.  
  1376.     lastr = (word *)malloc (msginfo.totalmsgs * sizeof (word));
  1377.     if (lastr == NULL) {
  1378.         printf ("MEM Err: LASTREAD allocation (lastr).\n");
  1379.         exit (1);
  1380.     }
  1381.     memset (lastr, 0, msginfo.totalmsgs * sizeof (word));
  1382.  
  1383.     newnum = (word *)malloc (msginfo.totalmsgs * sizeof (word));
  1384.     if (newnum == NULL) {
  1385.         printf ("MEM Err: LASTREAD allocation (newnum).\n");
  1386.         exit (1);
  1387.     }
  1388.     memset (newnum, 0, msginfo.totalmsgs * sizeof (word));
  1389.  
  1390.     lrpos = 0;
  1391.     msgnum = 1;
  1392.  
  1393.     sprintf (filename, "%sMSGHDR.BBS", cfg.quick_msgpath);
  1394.     fd = open (filename, O_RDWR | O_BINARY);
  1395.     if (fd == -1)
  1396.         exit (1);
  1397.  
  1398.     pos = tell (fd);
  1399.  
  1400.     memset((char *)&msginfo, 0, sizeof(struct _msginfo));
  1401.  
  1402.     sprintf (filename, "%sMSGIDX.BBS", cfg.quick_msgpath);
  1403.     fdidx = open(filename,O_WRONLY|O_BINARY|O_TRUNC);
  1404.  
  1405.     while (read(fd, (char *)&msghdr, sizeof (struct _msghdr)) == sizeof (struct _msghdr)) {
  1406.         if (!(msghdr.msgattr & Q_RECKILL) && msghdr.msgnum && msghdr.board) {
  1407.             lastr[lrpos] = msghdr.msgnum;
  1408.             msghdr.msgnum = msgnum++;
  1409.             newnum[lrpos++] = msghdr.msgnum;
  1410.             lseek (fd, pos, SEEK_SET);
  1411.             write (fd, (char *)&msghdr, sizeof (struct _msghdr));
  1412.       }
  1413.       pos = tell (fd);
  1414.  
  1415.       if (!(msghdr.msgattr & Q_RECKILL) && msghdr.msgnum && msghdr.board)
  1416.          msgidx.msgnum = msghdr.msgnum;
  1417.       else
  1418.          msgidx.msgnum = 0;
  1419.       msgidx.board = msghdr.board;
  1420.  
  1421.       write (fdidx, (char *)&msgidx, sizeof (struct _msgidx));
  1422.  
  1423.       if (!(msghdr.msgattr & Q_RECKILL) && msghdr.msgnum && msghdr.board) {
  1424.          if (!msginfo.lowmsg)
  1425.             msginfo.lowmsg = msghdr.msgnum;
  1426.  
  1427.          if (msginfo.lowmsg > msghdr.msgnum)
  1428.             msginfo.lowmsg = msghdr.msgnum;
  1429.          if (msginfo.highmsg < msghdr.msgnum)
  1430.             msginfo.highmsg = msghdr.msgnum;
  1431.  
  1432.          msginfo.totalmsgs++;
  1433.          msginfo.totalonboard[msgidx.board-1]++;
  1434.       }
  1435.    }
  1436.  
  1437.    close (fdidx);
  1438.    close (fd);
  1439.  
  1440.    sprintf (filename, "%sMSGINFO.BBS", cfg.quick_msgpath);
  1441.    fd = open(filename,O_WRONLY|O_BINARY);
  1442.    write(fd, (char *)&msginfo, sizeof(struct _msginfo));
  1443.    close (fd);
  1444.  
  1445.    printf(" * Updating LASTREAD.BBS pointer\n");
  1446.  
  1447.    sprintf (filename, "%sLASTREAD.BBS", cfg.quick_msgpath);
  1448.    fd = open (filename,O_RDWR|O_BINARY);
  1449.  
  1450.    pos = 0L;
  1451.    while (read (fd, &lr, sizeof (struct _qlastread)) == sizeof (struct _qlastread)) {
  1452.       for (i = 0; i < 200; i++) {
  1453.          m = 0;
  1454.          while (lastr[m] < lr.msgnum[i] && m < lrpos)
  1455.             m++;
  1456.          while (m > 0 && lastr[m] == 0)
  1457.             m--;
  1458.          lr.msgnum[i] = newnum[m];
  1459.       }
  1460.  
  1461.       lseek (fd, pos, SEEK_SET);
  1462.       write (fd, &lr, sizeof (struct _qlastread));
  1463.       pos = tell (fd);
  1464.    }
  1465.  
  1466.    close (fd);
  1467. }
  1468.  
  1469. char *pascal_string (char *s)
  1470. {
  1471.    static char e_input[90];
  1472.  
  1473.    strncpy(e_input,(char *)&s[1],(int)s[0]);
  1474.    e_input[(int)s[0]] = '\0';
  1475.  
  1476.    return (e_input);
  1477. }
  1478.  
  1479. void Link_Quick_Areas (void)
  1480. {
  1481.     int fd;
  1482.     unsigned int i, m, nummsg, cur, prev, next;
  1483.     char subj[80], lwrite;
  1484.     long crc;
  1485.     struct _msghdr msghdr;
  1486.     MSGLINK *ml;
  1487.  
  1488.     sprintf (subj, "%sMSGHDR.BBS", cfg.quick_msgpath);
  1489.     fd = open (subj, O_RDWR|O_BINARY);
  1490.     if (fd == -1)
  1491.         return;
  1492.  
  1493.     clreol ();
  1494.     printf(" * Linking QuickBBS messages\n");
  1495.  
  1496.     nummsg = (unsigned int)(filelength (fd) / sizeof (struct _msghdr));
  1497.     ml = (MSGLINK *)malloc (nummsg * sizeof (MSGLINK));
  1498.     memset (ml, 0, nummsg * sizeof (MSGLINK));
  1499.     cur = 1;
  1500.  
  1501.     while (read(fd, (char *)&msghdr, sizeof (struct _msghdr)) == sizeof (struct _msghdr)) {
  1502.         strcpy (subj, strupr (pascal_string (msghdr.subject)));
  1503.         if (!strncmp (subj, "RE: ", 4))
  1504.             strcpy (subj, &subj[4]);
  1505.         if (!strncmp (subj, "RE:", 3))
  1506.             strcpy (subj, &subj[3]);
  1507.         ml[cur - 1].crc = crc_name (subj);
  1508.         ml[cur - 1].num = cur;
  1509.         ml[cur - 1].board = msghdr.board;
  1510.         cur++;
  1511.     }
  1512.  
  1513.     lseek (fd, 0L, SEEK_SET);
  1514.  
  1515.     i = 0;
  1516.  
  1517.     while (read(fd, (char *)&msghdr, sizeof (struct _msghdr)) == sizeof (struct _msghdr)) {
  1518.         crc = ml[i].crc;
  1519.         i++;
  1520.  
  1521.         prev = next = 0;
  1522.  
  1523.         for (m = 0; m < nummsg; m++) {
  1524.             if (ml[m].num == i)
  1525.                 continue;
  1526.             if (ml[m].crc == crc && ml[m].board == msghdr.board) {
  1527.                 if (ml[m].num < i)
  1528.                     prev = ml[m].num;
  1529.                 else if (ml[m].num > i) {
  1530.                     next = ml[m].num;
  1531.                     break;
  1532.                 }
  1533.             }
  1534.         }
  1535.  
  1536.         lwrite = 0;
  1537.  
  1538.         if (msghdr.prevreply != prev) {
  1539.             msghdr.prevreply = prev;
  1540.             lwrite = 1;
  1541.         }
  1542.         if (msghdr.nextreply != next) {
  1543.             msghdr.nextreply = next;
  1544.             lwrite = 1;
  1545.         }
  1546.  
  1547.         if (lwrite) {
  1548.             lseek (fd, -1L * sizeof (struct _msghdr), SEEK_CUR);
  1549.             write (fd, (char *)&msghdr, sizeof (struct _msghdr));
  1550.         }
  1551.     }
  1552.  
  1553.     close (fd);
  1554.     free (ml);
  1555. }
  1556.  
  1557. void Purge_Quick_Areas (int renum)
  1558. {
  1559.     #define MAXREADIDX   100
  1560.     int fd, fdidx, max_msgs[200], max_age[200], age_rcvd[200], month[12];
  1561.     int cnum[200], pnum[200], area, flag1, x, m, i;
  1562.     int far *qren[200];
  1563.     char filename[60];
  1564.    int fdto, dy, mo, yr, days, flag;
  1565.    word msgnum, deleted = 0, *lastr, lrpos;
  1566.    long pos, tempo, day_now, day_mess;
  1567.    struct tm *tim;
  1568.    struct _msghdr msghdr;
  1569.    struct _msgidx msgidx;
  1570.    struct _msgidx idx[MAXREADIDX];
  1571.    struct _msginfo msginfo;
  1572.     struct _qlastread lr;
  1573.    struct _sys tsys;
  1574.    struct _usr usr;
  1575.  
  1576.     month[0] = 31;
  1577.    month[1] = 28;
  1578.    month[2] = 31;
  1579.     month[3] = 30;
  1580.    month[4] = 31;
  1581.    month[5] = 30;
  1582.    month[6] = 31;
  1583.     month[7] = 31;
  1584.    month[8] = 30;
  1585.    month[9] = 31;
  1586.    month[10] = 30;
  1587.    month[11] = 31;
  1588.  
  1589.    for (m = 0; m < 200; m++) {
  1590.         max_msgs[m] = 0;
  1591.       max_age[m] = 0;
  1592.         age_rcvd[m] = 0;
  1593.         cnum[m] = 0;
  1594.         pnum[m] = 0;
  1595.    }
  1596.  
  1597.    msgnum = 0;
  1598.    flag = 0;
  1599.  
  1600.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  1601.    fd = open(filename, O_RDONLY|O_BINARY);
  1602.    if (fd == -1)
  1603.       exit (1);
  1604.  
  1605.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  1606.       if ( tsys.quick_board < 1 || tsys.quick_board > 200)
  1607.             continue;
  1608.  
  1609.       max_msgs[tsys.quick_board-1] = tsys.max_msgs;
  1610.       max_age[tsys.quick_board-1] = tsys.max_age;
  1611.         age_rcvd[tsys.quick_board-1] = tsys.age_rcvd;
  1612.  
  1613.       if (tsys.max_msgs || tsys.max_age || tsys.age_rcvd)
  1614.             flag = 1;
  1615.    }
  1616.  
  1617.    close (fd);
  1618.  
  1619.     if (!flag)
  1620.       return;
  1621.  
  1622.    printf(" * Reading message base data\n");
  1623.  
  1624.    memset (&msginfo, 0, sizeof (struct _msginfo));
  1625.  
  1626.    sprintf(filename, "%sMSGIDX.BBS", cfg.quick_msgpath);
  1627.     fd = open (filename, O_RDONLY|O_BINARY, S_IREAD|S_IWRITE);
  1628.  
  1629.    do {
  1630.       m = read (fd, (char *)&idx, sizeof(struct _msgidx) * MAXREADIDX);
  1631.         m /= sizeof (struct _msgidx);
  1632.  
  1633.       for (x = 0; x < m; x++) {
  1634.             if (idx[x].board && idx[x].msgnum > 0) {
  1635.                 if (!msginfo.lowmsg)
  1636.                     msginfo.lowmsg = idx[x].msgnum;
  1637.  
  1638.                 if (msginfo.lowmsg > idx[x].msgnum)
  1639.                     msginfo.lowmsg = idx[x].msgnum;
  1640.                 if (msginfo.highmsg < idx[x].msgnum)
  1641.                     msginfo.highmsg = idx[x].msgnum;
  1642.  
  1643.                 msginfo.totalmsgs++;
  1644.                 msginfo.totalonboard[idx[x].board - 1]++;
  1645.             }
  1646.         }
  1647.     } while (m == MAXREADIDX);
  1648.  
  1649.     close(fd);
  1650.  
  1651.     if(!msginfo.totalmsgs){
  1652.         printf(" * No Messages in Hudson base\n");
  1653.         return;
  1654.     }
  1655.  
  1656.  
  1657.     printf(" * Purging QuickBBS messages\n");
  1658.  
  1659.     lastr = (word *)malloc (msginfo.totalmsgs * sizeof (word));
  1660.     if (lastr == NULL) {
  1661.         printf ("MEM Err: LASTREAD allocation.\n");
  1662.         exit (1);
  1663.     }
  1664.     memset (lastr, 0, msginfo.totalmsgs * sizeof (word));
  1665.     lrpos = 0;
  1666.  
  1667.     for (m = 0; m < 200; m++) {
  1668.         if (msginfo.totalonboard[m]) {
  1669.             qren[m] = (int *)malloc (msginfo.totalonboard[m] * (long)sizeof (int));
  1670.             if (qren[m] == NULL)
  1671.                 exit (2);
  1672.         }
  1673.         else
  1674.             qren[m] = NULL;
  1675.     }
  1676.  
  1677.     tempo = time(0);
  1678.     tim = localtime(&tempo);
  1679.  
  1680.     day_now = 365 * tim->tm_year;
  1681.     for (m = 0; m < tim->tm_mon; m++)
  1682.         day_now += month[m];
  1683.     day_now += tim->tm_mday;
  1684.  
  1685.     sprintf (filename, "%sMSGHDR.BBS", cfg.quick_msgpath);
  1686.     fd = open (filename, O_RDWR|O_BINARY);
  1687.     if (fd == -1)
  1688.         exit (1);
  1689.  
  1690.     pos = tell (fd);
  1691.  
  1692.     sprintf (filename, "%sMSGIDX.BBS", cfg.quick_msgpath);
  1693.     fdidx = open(filename,O_RDWR|O_BINARY);
  1694.  
  1695.     sprintf (filename, "%sMSGTOIDX.BBS", cfg.quick_msgpath);
  1696.     fdto = open(filename,O_RDWR|O_BINARY);
  1697.  
  1698.     while (read(fd, (char *)&msghdr, sizeof (struct _msghdr)) == sizeof (struct _msghdr)) {
  1699.         flag = 0;
  1700.         if (msghdr.board >= 1 && msghdr.board <= 200 && !(msghdr.msgattr & Q_RECKILL)) {
  1701.             pnum[msghdr.board-1]++;
  1702.  
  1703.             if (max_msgs[msghdr.board-1] && msginfo.totalonboard[msghdr.board-1] > max_msgs[msghdr.board-1]) {
  1704.                 msghdr.msgattr |= Q_RECKILL;
  1705.                 flag = 1;
  1706.             }
  1707.             else {
  1708.                 sscanf(&msghdr.date[1], "%02d-%02d-%02d", &mo, &dy, &yr);
  1709.  
  1710.                 day_mess = 365 * yr;
  1711.                 mo--;
  1712.                 for (m = 0; m < mo; m++)
  1713.                     day_mess += month[m];
  1714.                 day_mess += dy;
  1715.  
  1716.                 days = (int)(day_now - day_mess);
  1717.  
  1718.                 if (max_age[msghdr.board-1] && days > max_age[msghdr.board-1]) {
  1719.                     msghdr.msgattr |= Q_RECKILL;
  1720.                     flag = 1;
  1721.                 }
  1722.                 else if (age_rcvd[msghdr.board-1] &&
  1723.                  ( (msghdr.msgattr & Q_PRIVATE) && (msghdr.msgattr & Q_RECEIVED) ) &&
  1724.                  days > age_rcvd[msghdr.board-1]) {
  1725.                     msghdr.msgattr |= Q_RECKILL;
  1726.                     flag = 1;
  1727.                 }
  1728.             }
  1729.  
  1730.             if ( flag ) {
  1731.                 deleted++;
  1732.                 lseek (fd, pos, SEEK_SET);
  1733.                 write (fd, (char *)&msghdr, sizeof (struct _msghdr));
  1734.                 msginfo.totalmsgs--;
  1735.                 msginfo.totalonboard[msghdr.board-1]--;
  1736.                 lseek (fdidx, (long)msgnum * sizeof (struct _msgidx), SEEK_SET);
  1737.                 read (fdidx, (char *)&msgidx, sizeof (struct _msgidx));
  1738.                 msgidx.msgnum = -1;
  1739.                 lseek (fdidx, (long)msgnum * sizeof (struct _msgidx), SEEK_SET);
  1740.                 write (fdidx, (char *)&msgidx, sizeof (struct _msgidx));
  1741.  
  1742.                 lseek (fdto, (long)msgnum * 36, SEEK_SET);
  1743.                 write (fdto, "\x0B* Deleted *                        ", 36);
  1744.  
  1745.                 lrpos++;
  1746.             }
  1747.             else {
  1748.                 qren[msghdr.board-1][cnum[msghdr.board-1]++] = pnum[msghdr.board-1];
  1749.                 lastr[lrpos++] = msghdr.msgnum;
  1750.             }
  1751.  
  1752.             if (renum) {
  1753.                 msgidx.msgnum = msghdr.msgnum;
  1754.                 msgidx.board = msghdr.board;
  1755.  
  1756.                 write (fdidx, (char *)&msgidx, sizeof (struct _msgidx));
  1757.             }
  1758.  
  1759. //      sprintf (filename, "%d", msghdr.msgnum);
  1760. //      printf ("%s%*s", filename, strlen (filename), "\b\b\b\b\b\b\b");
  1761.  
  1762.  
  1763.             if ((msgnum % 40) == 0 || flag)
  1764.                 printf("   └─ Msg.: %u, Deleted: %u\r", msgnum, deleted);
  1765.  
  1766.             msgnum++;
  1767.         }
  1768.         pos = tell (fd);
  1769.         if (msghdr.board < 1 && msghdr.board > 200){
  1770.                 printf("Unknown board number: %d",msghdr.board);
  1771.                 printf("Run index utility");
  1772.         }
  1773.     }
  1774.  
  1775.     close (fdidx);
  1776.     close (fd);
  1777.     close (fdto);
  1778.  
  1779.     sprintf (filename, "%sMSGINFO.BBS", cfg.quick_msgpath);
  1780.     fd = open(filename,O_RDWR|O_BINARY);
  1781.     if (fd == -1)
  1782.         exit (1);
  1783.     write (fd, (char *)&msginfo, sizeof(struct _msginfo));
  1784.     close (fd);
  1785.  
  1786.     for (m = 0; m < 200; m++)
  1787.         cnum[m] = 0;
  1788.  
  1789.     if (deleted) {
  1790.         printf("\n * Updating USERS lastread pointer\n");
  1791.  
  1792.         sprintf (filename, "%sLASTREAD.BBS", cfg.quick_msgpath);
  1793.         fd = open (filename,O_RDWR|O_BINARY);
  1794.  
  1795.         pos = 0L;
  1796.         while (read (fd, &lr, sizeof (struct _qlastread)) == sizeof (struct _qlastread)) {
  1797.             for (i = 0; i < 200; i++) {
  1798.                 m = 0;
  1799.                 while (lastr[m] < lr.msgnum[i] && m < msginfo.totalmsgs)
  1800.                     m++;
  1801.                 while (m > 0 && lastr[m] == 0)
  1802.                     m--;
  1803.                 lr.msgnum[i] = lastr[m];
  1804.             }
  1805.  
  1806.             lseek (fd, pos, SEEK_SET);
  1807.             write (fd, &lr, sizeof (struct _qlastread));
  1808.             pos = tell (fd);
  1809.         }
  1810.  
  1811.         close (fd);
  1812.  
  1813.         sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  1814.         fd = open(filename, O_RDONLY|O_BINARY);
  1815.         if (fd == -1)
  1816.             exit (1);
  1817.  
  1818.         while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  1819.             if ( tsys.quick_board < 1 || tsys.quick_board > 200)
  1820.                 continue;
  1821.             cnum[tsys.quick_board-1] = tsys.msg_num;
  1822.         }
  1823.  
  1824.         close (fd);
  1825.  
  1826.         sprintf (filename, "%s.BBS", cfg.user_file);
  1827.         fd = open(filename, O_RDWR | O_BINARY);
  1828.         pos = tell (fd);
  1829.  
  1830.         while (read(fd, (char *) &usr, sizeof(struct _usr)) == sizeof(struct _usr)) {
  1831.             for (area = 0; area < MAXLREAD; area++) {
  1832.                 for (m = 0; m < 200; m++) {
  1833.                     if (usr.lastread[area].area == cnum[m])
  1834.                         break;
  1835.                 }
  1836.  
  1837.                 if (m < 200 && usr.lastread[area].msg_num) {
  1838.                     flag1 = 0;
  1839.  
  1840.                     for (x = 0; x < msginfo.totalonboard[m]; x++)
  1841.                         if (qren[m][x] > flag1 && qren[m][x] <= usr.lastread[area].msg_num)
  1842.                             flag1 = x + 1;
  1843.  
  1844.                     usr.lastread[area].msg_num = flag1;
  1845.                 }
  1846.             }
  1847.  
  1848.             for (area = 0; area < MAXDLREAD; area++) {
  1849.                 for (m = 0; m < 200; m++) {
  1850.                     if (usr.dynlastread[area].area == cnum[m])
  1851.                         break;
  1852.                 }
  1853.  
  1854.                 if (m < 200 && usr.dynlastread[area].msg_num) {
  1855.                     flag1 = 0;
  1856.  
  1857.                     for (x = 0; x < msginfo.totalonboard[m]; x++)
  1858.                         if (qren[m][x] > flag1 && qren[m][x] <= usr.dynlastread[area].msg_num)
  1859.                             flag1 = x + 1;
  1860.  
  1861.                     usr.dynlastread[area].msg_num = flag1;
  1862.                 }
  1863.             }
  1864.  
  1865.             lseek (fd, pos, SEEK_SET);
  1866.             write (fd, (char *) &usr, sizeof(struct _usr));
  1867.  
  1868.             pos = tell (fd);
  1869.         }
  1870.  
  1871.         close(fd);
  1872.     }
  1873.  
  1874.     for (m = 0; m < 200; m ++) {
  1875.         if (qren[m] != NULL)
  1876.             free (qren[m]);
  1877.     }
  1878. }
  1879.  
  1880. void Pack_Quick_Base (int renum)
  1881. {
  1882.     FILE *fph, *fpt, *fpi, *fpto, *outfph, *outfpt;
  1883.     int i;
  1884.     char filename[80], newname[80];
  1885.     unsigned int msgnum;
  1886.     unsigned char text[256];
  1887.     long block, messages, deleted;
  1888.     struct _msghdr msghdr;
  1889.     struct _msgidx msgidx;
  1890.     struct _msginfo msginfo;
  1891.  
  1892.     printf (" * Packing QuickBBS Message Base\r\n");
  1893.  
  1894.     memset (&msginfo, 0, sizeof (struct _msginfo));
  1895.  
  1896.     sprintf (filename, "%sMSGHDR.BBS", cfg.quick_msgpath);
  1897.     if ((fph = fopen (filename, "rb")) == NULL){
  1898.     printf (" ! Unable to open MSGHDR.BBS\n");
  1899.         return;
  1900.     }
  1901.  
  1902.     block = 0;
  1903.     msgnum = 1;
  1904.     deleted = 0;
  1905.     messages = filelength (fileno (fph)) / sizeof (struct _msghdr);
  1906.  
  1907.     while (fread (&msghdr, sizeof (struct _msghdr), 1, fph) == 1) {
  1908.         if (msghdr.msgattr & Q_RECKILL) {
  1909.             deleted++;
  1910.             continue;
  1911.         }
  1912.         if (msghdr.msgnum < 1 || msghdr.board < 1 || msghdr.board > 200) {
  1913.             deleted++;
  1914.             continue;
  1915.         }
  1916.     }
  1917.  
  1918.     if (deleted == 0) {
  1919.         fclose (fph);
  1920.         printf (" * No Messages Deleted\r\n");
  1921.         return;
  1922.     }
  1923.  
  1924.     messages -= deleted;
  1925.  
  1926.     sprintf (filename, "%sMSGTXT.BBS", cfg.quick_msgpath);
  1927.     if ((fpt = fopen (filename, "rb")) == NULL){
  1928.         printf("! Unable to open MSGTXT.BBS\n");
  1929.         exit (2);
  1930.         }
  1931.     sprintf (filename, "%sMSGIDX.BBS", cfg.quick_msgpath);
  1932.     if ((fpi = fopen (filename, "wb")) == NULL){
  1933.     printf("! Unable to open MSGIDX.BBS\n");
  1934.         exit (2);
  1935.     }
  1936.     sprintf (filename, "%sMSGTOIDX.BBS", cfg.quick_msgpath);
  1937.     if ((fpto = fopen (filename, "wb")) == NULL){
  1938.         printf("! Unable to open MSGTOIDX.BBS\n");
  1939.         exit (2);
  1940.         }
  1941.     sprintf (filename, "%sMSGHDR.NEW", cfg.quick_msgpath);
  1942.     if ((outfph = fopen (filename, "wb")) == NULL){
  1943.         printf("! Unable to open tempfile MSGHDR.NEW\n");
  1944.         exit (2);
  1945.     }
  1946.     sprintf (filename, "%sMSGTXT.NEW", cfg.quick_msgpath);
  1947.     if ((outfpt = fopen (filename, "wb")) == NULL){
  1948.         printf("! Unable to open tempfile MSGTXT.NEW\n");
  1949.         exit (2);
  1950.     }
  1951.  
  1952.     fseek (fph, 0L, SEEK_SET);
  1953.  
  1954.     while (fread (&msghdr, sizeof (struct _msghdr), 1, fph) == 1) {
  1955.         if (msghdr.msgattr & Q_RECKILL)
  1956.             continue;
  1957.         if (msghdr.msgnum < 1 || msghdr.board < 1 || msghdr.board > 200)
  1958.             continue;
  1959.  
  1960.         printf ("   Packed Msg.# %d / %ld\r", msgnum, messages);
  1961.  
  1962.         fseek (fpt, (long)msghdr.startblock * 256L, SEEK_SET);
  1963.  
  1964.         msghdr.startblock = (unsigned int)block;
  1965.         if (renum)
  1966.             msghdr.msgnum = msgnum;
  1967.         fwrite (&msghdr, sizeof (struct _msghdr), 1, outfph);
  1968.  
  1969.         for (i = 0; i < msghdr.numblocks; i++) {
  1970.             fread (text, 256, 1, fpt);
  1971.             fwrite (text, 256, 1, outfpt);
  1972.         }
  1973.  
  1974.         msgidx.msgnum = msghdr.msgnum;
  1975.         msgidx.board = msghdr.board;
  1976.         fwrite (&msgidx, sizeof (struct _msgidx), 1, fpi);
  1977.  
  1978.         fwrite (&msghdr.whoto, 36, 1, fpto);
  1979.  
  1980.         if (!msginfo.lowmsg || msghdr.msgnum < msginfo.lowmsg)
  1981.             msginfo.lowmsg = msghdr.msgnum;
  1982.         if (!msginfo.highmsg || msghdr.msgnum > msginfo.highmsg)
  1983.             msginfo.highmsg = msghdr.msgnum;
  1984.         msginfo.totalonboard[msghdr.board - 1]++;
  1985.         msginfo.totalmsgs++;
  1986.  
  1987.         block += msghdr.numblocks;
  1988.         msgnum++;
  1989.     }
  1990.  
  1991.     fclose (outfpt);
  1992.     fclose (outfph);
  1993.     fclose (fpto);
  1994.     fclose (fpi);
  1995.     fclose (fpt);
  1996.     fclose (fph);
  1997.  
  1998.     sprintf (filename, "%sMSGINFO.BBS", cfg.quick_msgpath);
  1999.     if ((fpto = fopen (filename, "wb")) == NULL){
  2000.         printf("! Unable to open MSGINFO.BBS\n");
  2001.         exit (2);
  2002.     }
  2003.     fwrite (&msginfo, sizeof (struct _msginfo), 1, fpto);
  2004.     fclose (fpto);
  2005.  
  2006.     sprintf (filename, "%sMSGHDR.NEW", cfg.quick_msgpath);
  2007.     sprintf (newname, "%sMSGHDR.BBS", cfg.quick_msgpath);
  2008.     unlink (newname);
  2009.     rename (filename, newname);
  2010.  
  2011.     sprintf (filename, "%sMSGTXT.NEW", cfg.quick_msgpath);
  2012.     sprintf (newname, "%sMSGTXT.BBS", cfg.quick_msgpath);
  2013.     unlink (newname);
  2014.     rename (filename, newname);
  2015.  
  2016.     clreol ();
  2017. }
  2018.  
  2019.  
  2020. /* -----------------------------------------------------------------------
  2021.  
  2022.     Sezione di gestione della base messaggi GOLD.
  2023.  
  2024.     ----------------------------------------------------------------------- */
  2025. void Create_Gold_Index (int xlink, int unknow, int renum)
  2026. {
  2027.     int fd, fdidx, fdto, know[500], m, flag;
  2028.     char filename[60];
  2029.     long pos, msgnum;
  2030.     struct _sys tsys;
  2031.     struct _gold_msghdr msghdr;
  2032.     struct _gold_msgidx msgidx;
  2033.     struct _gold_msginfo msginfo;
  2034.  
  2035.     msgnum = 1;
  2036. //    if (xlink);
  2037.  
  2038.     if (unknow) {
  2039.         for (m = 0; m < 500; m++)
  2040.             know[m] = 0;
  2041.  
  2042.         sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2043.         fd = open(filename, O_RDONLY|O_BINARY);
  2044.         if (fd == -1)
  2045.             exit (1);
  2046.  
  2047.         while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2048.             if ( !tsys.gold_board )
  2049.                 continue;
  2050.  
  2051.             know[tsys.gold_board-1] = 1;
  2052.         }
  2053.  
  2054.         close (fd);
  2055.     }
  2056.  
  2057.     sprintf (filename, "%sMSGHDR.DAT", cfg.quick_msgpath);
  2058.     fd = open (filename, O_RDWR|O_BINARY);
  2059.     if (fd == -1)
  2060.         exit (1);
  2061.  
  2062.     printf(" * Regenerating Gold message base indices\n");
  2063.  
  2064.     pos = tell (fd);
  2065.  
  2066.     memset((char *)&msginfo, 0, sizeof(struct _gold_msginfo));
  2067.  
  2068.     sprintf (filename, "%sMSGIDX.DAT", cfg.quick_msgpath);
  2069.     fdidx = open(filename,O_WRONLY|O_BINARY|O_TRUNC);
  2070.  
  2071.     sprintf (filename, "%sMSGTOIDX.DAT", cfg.quick_msgpath);
  2072.     fdto = open(filename,O_WRONLY|O_BINARY|O_TRUNC);
  2073.  
  2074.     while (read(fd, (char *)&msghdr, sizeof (struct _gold_msghdr)) == sizeof (struct _gold_msghdr)) {
  2075.         flag = 0;
  2076.  
  2077.         if (unknow) {
  2078.             if (know[msghdr.board-1] != 1) {
  2079.                 msghdr.msgattr |= Q_RECKILL;
  2080.                 if (know[msghdr.board-1] != 2) {
  2081.                     printf(" * Unknow board #%d\n", msghdr.board);
  2082.                     know[msghdr.board-1] = 2;
  2083.                 }
  2084.                 flag = 1;
  2085.             }
  2086.         }
  2087.  
  2088.         if (renum)
  2089.             msghdr.msgnum = msgnum++;
  2090.         else
  2091.             msgnum++;
  2092.  
  2093.         if (renum || flag) {
  2094.             lseek (fd, pos, SEEK_SET);
  2095.             write (fd, (char *)&msghdr, sizeof (struct _gold_msghdr));
  2096.             pos = tell (fd);
  2097.         }
  2098.  
  2099.         if (flag) {
  2100.             msgidx.msgnum = 0;
  2101.             write (fdto, "\x0B* Deleted *                        ", 36);
  2102.         }
  2103.         else {
  2104.             write (fdto, (char *)&msghdr.whoto, sizeof (struct _msgtoidx));
  2105.             msgidx.msgnum = msghdr.msgnum;
  2106.         }
  2107.  
  2108.         msgidx.board = msghdr.board;
  2109.         write (fdidx, (char *)&msgidx, sizeof (struct _gold_msgidx));
  2110.  
  2111.         msginfo.totalmsgs++;
  2112.  
  2113.         if (!msginfo.lowmsg)
  2114.             msginfo.lowmsg = msghdr.msgnum;
  2115.  
  2116.         if (msginfo.lowmsg > msghdr.msgnum)
  2117.             msginfo.lowmsg = msghdr.msgnum;
  2118.         if (msginfo.highmsg < msghdr.msgnum)
  2119.             msginfo.highmsg = msghdr.msgnum;
  2120.  
  2121.         if (!flag)
  2122.             msginfo.totalonboard[msgidx.board-1]++;
  2123.     }
  2124.  
  2125.     close (fdto);
  2126.     close (fdidx);
  2127.     close (fd);
  2128.  
  2129.     sprintf (filename, "%sMSGINFO.DAT", cfg.quick_msgpath);
  2130.     fd = open(filename,O_WRONLY|O_BINARY);
  2131.     write(fd, (char *)&msginfo, sizeof(struct _gold_msginfo));
  2132.     close (fd);
  2133. }
  2134.  
  2135. void Purge_Gold_Areas (int renum)
  2136. {
  2137.     #define MAXREADIDX   100
  2138.     int fd, fdidx, max_msgs[500], max_age[500], age_rcvd[500], month[12];
  2139.     int cnum[500], pnum[500], area, flag1, x, m, i;
  2140.     int far *qren[500];
  2141.     char filename[60];
  2142.     int fdto, dy, mo, yr, days, flag;
  2143.     word deleted = 0, *lastr, lrpos;
  2144.     long msgnum, pos, tempo, day_now, day_mess;
  2145.     struct tm *tim;
  2146.     struct _gold_msghdr msghdr;
  2147.     struct _gold_msgidx msgidx;
  2148.     struct _gold_msgidx idx[MAXREADIDX];
  2149.     struct _gold_msginfo msginfo;
  2150.     struct _glastread lr;
  2151.     struct _sys tsys;
  2152.     struct _usr usr;
  2153.  
  2154.     month[0] = 31;
  2155.     month[1] = 28;
  2156.     month[2] = 31;
  2157.     month[3] = 30;
  2158.     month[4] = 31;
  2159.     month[5] = 30;
  2160.     month[6] = 31;
  2161.     month[7] = 31;
  2162.     month[8] = 30;
  2163.     month[9] = 31;
  2164.     month[10] = 30;
  2165.     month[11] = 31;
  2166.  
  2167.     for (m = 0; m < 500; m++) {
  2168.         max_msgs[m] = 0;
  2169.         max_age[m] = 0;
  2170.         age_rcvd[m] = 0;
  2171.         cnum[m] = 0;
  2172.         pnum[m] = 0;
  2173.     }
  2174.  
  2175.     msgnum = 0;
  2176.     flag = 0;
  2177.  
  2178.     sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2179.     fd = open(filename, O_RDONLY|O_BINARY);
  2180.     if (fd == -1)
  2181.         exit (1);
  2182.  
  2183.     while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2184.         if ( tsys.gold_board < 1 || tsys.gold_board > 500)
  2185.             continue;
  2186.  
  2187.         max_msgs[tsys.gold_board-1] = tsys.max_msgs;
  2188.         max_age[tsys.gold_board-1] = tsys.max_age;
  2189.         age_rcvd[tsys.gold_board-1] = tsys.age_rcvd;
  2190.  
  2191.         if (tsys.max_msgs || tsys.max_age || tsys.age_rcvd)
  2192.             flag = 1;
  2193.     }
  2194.  
  2195.     close (fd);
  2196.  
  2197.     if (!flag)
  2198.         return;
  2199.  
  2200.     printf(" * Reading message base data\n");
  2201.  
  2202.     memset (&msginfo, 0, sizeof (struct _gold_msginfo));
  2203.  
  2204.     sprintf(filename, "%sMSGIDX.DAT", cfg.quick_msgpath);
  2205.     fd = open (filename, O_RDONLY|O_BINARY, S_IREAD|S_IWRITE);
  2206.     if (fd == -1){
  2207.         printf(" * Unable to open %s\n",filename);
  2208.         return;
  2209.     }
  2210.  
  2211.     do {
  2212.         m = read (fd, (char *)&idx, sizeof (struct _gold_msgidx) * MAXREADIDX);
  2213.         m /= sizeof (struct _gold_msgidx);
  2214.  
  2215.         for (x = 0; x < m; x++) {
  2216.             if (idx[x].board && idx[x].msgnum > 0) {
  2217.                 if (!msginfo.lowmsg)
  2218.                     msginfo.lowmsg = idx[x].msgnum;
  2219.  
  2220.                 if (msginfo.lowmsg > idx[x].msgnum)
  2221.                     msginfo.lowmsg = idx[x].msgnum;
  2222.                 if (msginfo.highmsg < idx[x].msgnum)
  2223.                     msginfo.highmsg = idx[x].msgnum;
  2224.  
  2225.                 msginfo.totalmsgs++;
  2226.                 msginfo.totalonboard[idx[x].board - 1]++;
  2227.             }
  2228.         }
  2229.     } while (m == MAXREADIDX);
  2230.  
  2231.     close(fd);
  2232.  
  2233.     if(!msginfo.totalmsgs){
  2234.         printf(" * No Messages in GoldBase\n");
  2235.         return;
  2236.     }
  2237.  
  2238.     printf(" * Purging GoldBase messages\n");
  2239.  
  2240.     lastr = (word *)malloc (msginfo.totalmsgs * sizeof (word));
  2241.     if (lastr == NULL) {
  2242.         printf ("MEM Err: LASTREAD allocation.\n");
  2243.         exit (1);
  2244.     }
  2245.     memset (lastr, 0, (unsigned int)msginfo.totalmsgs * sizeof (word));
  2246.     lrpos = 0;
  2247.  
  2248.     for (m = 0; m < 500; m++) {
  2249.         if (msginfo.totalonboard[m]) {
  2250.             qren[m] = (int *)malloc (msginfo.totalonboard[m] * (long)sizeof (int));
  2251.             if (qren[m] == NULL)
  2252.                 exit (2);
  2253.         }
  2254.         else
  2255.             qren[m] = NULL;
  2256.     }
  2257.  
  2258.     tempo = time(0);
  2259.     tim = localtime(&tempo);
  2260.  
  2261.     day_now = 365 * tim->tm_year;
  2262.     for (m = 0; m < tim->tm_mon; m++)
  2263.         day_now += month[m];
  2264.     day_now += tim->tm_mday;
  2265.  
  2266.     sprintf (filename, "%sMSGHDR.DAT", cfg.quick_msgpath);
  2267.     fd = open (filename, O_RDWR|O_BINARY);
  2268.     if (fd == -1)
  2269.         exit (1);
  2270.  
  2271.     pos = tell (fd);
  2272.  
  2273.     sprintf (filename, "%sMSGIDX.DAT", cfg.quick_msgpath);
  2274.     fdidx = open(filename,O_RDWR|O_BINARY);
  2275.  
  2276.     sprintf (filename, "%sMSGTOIDX.DAT", cfg.quick_msgpath);
  2277.     fdto = open(filename,O_RDWR|O_BINARY);
  2278.  
  2279.     while (read(fd, (char *)&msghdr, sizeof (struct _gold_msghdr)) == sizeof (struct _gold_msghdr)) {
  2280.         flag = 0;
  2281.         if (msghdr.board >= 1 && msghdr.board <= 500 && msghdr.msgnum > 0) {
  2282.             pnum[msghdr.board-1]++;
  2283.  
  2284.             if (max_msgs[msghdr.board-1] && msginfo.totalonboard[msghdr.board-1] > max_msgs[msghdr.board-1]) {
  2285.                 msghdr.msgattr |= Q_RECKILL;
  2286.                 flag = 1;
  2287.             }
  2288.             else {
  2289.                 sscanf(&msghdr.date[1], "%02d-%02d-%02d", &mo, &dy, &yr);
  2290.  
  2291.                 day_mess = 365 * yr;
  2292.                 mo--;
  2293.                 for (m = 0; m < mo; m++)
  2294.                     day_mess += month[m];
  2295.                 day_mess += dy;
  2296.  
  2297.                 days = (int)(day_now - day_mess);
  2298.  
  2299.                 if (max_age[msghdr.board-1] && days > max_age[msghdr.board-1]) {
  2300.                     msghdr.msgattr |= Q_RECKILL;
  2301.                     flag = 1;
  2302.                 }
  2303.                 else if (age_rcvd[msghdr.board-1] &&
  2304.                  ( (msghdr.msgattr & Q_PRIVATE) && (msghdr.msgattr & Q_RECEIVED) ) &&
  2305.                  days > age_rcvd[msghdr.board-1]) {
  2306.                     msghdr.msgattr |= Q_RECKILL;
  2307.                     flag = 1;
  2308.                 }
  2309.             }
  2310.  
  2311.             if ( flag ) {
  2312.                 deleted++;
  2313.                 lseek (fd, pos, SEEK_SET);
  2314.                 write (fd, (char *)&msghdr, sizeof (struct _gold_msghdr));
  2315.                 msginfo.totalmsgs--;
  2316.                 msginfo.totalonboard[msghdr.board-1]--;
  2317.                 lseek (fdidx, (long)msgnum * sizeof (struct _gold_msgidx), SEEK_SET);
  2318.                 read (fdidx, (char *)&msgidx, sizeof (struct _gold_msgidx));
  2319.                 msgidx.msgnum = -1;
  2320.                 lseek (fdidx, (long)msgnum * sizeof (struct _gold_msgidx), SEEK_SET);
  2321.                 write (fdidx, (char *)&msgidx, sizeof (struct _gold_msgidx));
  2322.  
  2323.                 lseek (fdto, (long)msgnum * 36, SEEK_SET);
  2324.                 write (fdto, "\x0B* Deleted *                        ", 36);
  2325.  
  2326.                 lrpos++;
  2327.             }
  2328.             else {
  2329.                 qren[msghdr.board-1][cnum[msghdr.board-1]++] = pnum[msghdr.board-1];
  2330.                 lastr[lrpos++] = (word)msghdr.msgnum;
  2331.             }
  2332.  
  2333.             if (renum) {
  2334.                 msgidx.msgnum = msghdr.msgnum;
  2335.                 msgidx.board = msghdr.board;
  2336.  
  2337.                 write (fdidx, (char *)&msgidx, sizeof (struct _gold_msgidx));
  2338.             }
  2339.  
  2340. //      sprintf (filename, "%d", msghdr.msgnum);
  2341. //      printf ("%s%*s", filename, strlen (filename), "\b\b\b\b\b\b\b");
  2342.  
  2343.             pos = tell (fd);
  2344.             if ((msgnum % 40) == 0 || flag)
  2345.                 printf("   └─ Msg.: %lu, Deleted: %u\r", msgnum, deleted);
  2346.  
  2347.             msgnum++;
  2348.         }
  2349.         pos = tell (fd);
  2350.       if (msghdr.board < 1 && msghdr.board > 500){
  2351.                 printf("Unknown board number: %d",msghdr.board);
  2352.                 printf("Run index utility");
  2353.       }    }
  2354.  
  2355.     close (fdidx);
  2356.     close (fd);
  2357.     close (fdto);
  2358.  
  2359.     sprintf (filename, "%sMSGINFO.DAT", cfg.quick_msgpath);
  2360.     fd = open(filename,O_RDWR|O_BINARY);
  2361.     if (fd == -1)
  2362.         exit (1);
  2363.     write (fd, (char *)&msginfo, sizeof (struct _gold_msginfo));
  2364.     close (fd);
  2365.  
  2366.     for (m = 0; m < 500; m++)
  2367.         cnum[m] = 0;
  2368.  
  2369.     printf("\n * Updating USERS lastread pointer\n");
  2370.  
  2371.     sprintf (filename, "%sLASTREAD.DAT", cfg.quick_msgpath);
  2372.     fd = open (filename,O_RDWR|O_BINARY);
  2373.  
  2374.     pos = 0L;
  2375.     while (read (fd, &lr, sizeof (struct _glastread)) == sizeof (struct _glastread)) {
  2376.         for (i = 0; i < 500; i++) {
  2377.             m = 0;
  2378.             while (lastr[m] < lr.msgnum[i] && m < msginfo.totalmsgs)
  2379.                 m++;
  2380.             while (m > 0 && lastr[m] == 0)
  2381.                 m--;
  2382.             lr.msgnum[i] = lastr[m];
  2383.         }
  2384.  
  2385.         lseek (fd, pos, SEEK_SET);
  2386.         write (fd, &lr, sizeof (struct _glastread));
  2387.         pos = tell (fd);
  2388.     }
  2389.  
  2390.     close (fd);
  2391.  
  2392.     sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2393.     fd = open(filename, O_RDONLY|O_BINARY);
  2394.     if (fd == -1)
  2395.         exit (1);
  2396.  
  2397.     while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2398.         if ( tsys.gold_board < 1 || tsys.gold_board > 500)
  2399.             continue;
  2400.         cnum[tsys.gold_board-1] = tsys.msg_num;
  2401.     }
  2402.  
  2403.     close (fd);
  2404.  
  2405.     sprintf (filename, "%s.BBS", cfg.user_file);
  2406.     fd = open(filename, O_RDWR | O_BINARY);
  2407.     pos = tell (fd);
  2408.  
  2409.     while (read(fd, (char *) &usr, sizeof(struct _usr)) == sizeof(struct _usr)) {
  2410.         for (area = 0; area < MAXLREAD; area++) {
  2411.             for (m = 0; m < 500; m++) {
  2412.                 if (usr.lastread[area].area == cnum[m])
  2413.                     break;
  2414.             }
  2415.  
  2416.             if (m < 500 && usr.lastread[area].msg_num) {
  2417.                 flag1 = 0;
  2418.  
  2419.                 for (x = 0; x < msginfo.totalonboard[m]; x++)
  2420.                     if (qren[m][x] > flag1 && qren[m][x] <= usr.lastread[area].msg_num)
  2421.                         flag1 = x + 1;
  2422.  
  2423.                 usr.lastread[area].msg_num = flag1;
  2424.             }
  2425.         }
  2426.  
  2427.         for (area = 0; area < MAXDLREAD; area++) {
  2428.             for (m = 0; m < 500; m++) {
  2429.                 if (usr.dynlastread[area].area == cnum[m])
  2430.                     break;
  2431.             }
  2432.  
  2433.             if (m < 500 && usr.dynlastread[area].msg_num) {
  2434.                 flag1 = 0;
  2435.  
  2436.                 for (x = 0; x < msginfo.totalonboard[m]; x++)
  2437.                     if (qren[m][x] > flag1 && qren[m][x] <= usr.dynlastread[area].msg_num)
  2438.                         flag1 = x + 1;
  2439.  
  2440.                 usr.dynlastread[area].msg_num = flag1;
  2441.             }
  2442.         }
  2443.  
  2444.         lseek (fd, pos, SEEK_SET);
  2445.         write (fd, (char *) &usr, sizeof(struct _usr));
  2446.  
  2447.         pos = tell (fd);
  2448.     }
  2449.  
  2450.     close(fd);
  2451.  
  2452.     for (m = 0; m < 500; m ++) {
  2453.         if (qren[m] != NULL){
  2454.  
  2455. //         printf("qren[%d] %d", m,qren[m]);
  2456.      free (qren[m]);
  2457. //         printf("done");
  2458.       }
  2459.  
  2460.     }
  2461. }
  2462.  
  2463. void Pack_Gold_Base (int renum)
  2464. {
  2465.     FILE *fph, *fpt, *fpi, *fpto, *outfph, *outfpt;
  2466.     int i;
  2467.     char filename[80], newname[80];
  2468.     long msgnum;
  2469.     unsigned char text[256];
  2470.     long block, messages, deleted;
  2471.     struct _gold_msghdr msghdr;
  2472.     struct _gold_msgidx msgidx;
  2473.     struct _gold_msginfo msginfo;
  2474.  
  2475.     printf (" * Packing GoldBBS Message Base\r\n");
  2476.  
  2477.     memset (&msginfo, 0, sizeof (struct _gold_msginfo));
  2478.  
  2479.     sprintf (filename, "%sMSGHDR.DAT", cfg.quick_msgpath);
  2480.     if ((fph = fopen (filename, "rb")) == NULL){
  2481.     printf (" ! Unable to open MSGHDR.DAT\n");
  2482.         return;
  2483.     }
  2484.  
  2485.     block = 0;
  2486.     msgnum = 1;
  2487.     deleted = 0;
  2488.     messages = filelength (fileno (fph)) / sizeof (struct _gold_msghdr);
  2489.  
  2490.     while (fread (&msghdr, sizeof (struct _gold_msghdr), 1, fph) == 1) {
  2491.         if (msghdr.msgattr & Q_RECKILL) {
  2492.             deleted++;
  2493.             continue;
  2494.         }
  2495.         if (msghdr.msgnum < 1 || msghdr.board < 1 || msghdr.board > 500) {
  2496.             deleted++;
  2497.             continue;
  2498.         }
  2499.     }
  2500.  
  2501.     if (deleted == 0) {
  2502.         fclose (fph);
  2503.         printf (" * No Messages Deleted\r\n");
  2504.         return;
  2505.     }
  2506.  
  2507.     messages -= deleted;
  2508.  
  2509.     sprintf (filename, "%sMSGTXT.DAT", cfg.quick_msgpath);
  2510.     if ((fpt = fopen (filename, "rb")) == NULL){
  2511.         printf("! Unable to open MSGTXT.DAT\n");
  2512.         exit (2);
  2513.         }
  2514.     sprintf (filename, "%sMSGIDX.DAT", cfg.quick_msgpath);
  2515.     if ((fpi = fopen (filename, "wb")) == NULL){
  2516.     printf("! Unable to open MSGIDX.DAT\n");
  2517.         exit (2);
  2518.     }
  2519.     sprintf (filename, "%sMSGTOIDX.DAT", cfg.quick_msgpath);
  2520.     if ((fpto = fopen (filename, "wb")) == NULL){
  2521.         printf("! Unable to open MSGTOIDX.DAT\n");
  2522.         exit (2);
  2523.         }
  2524.     sprintf (filename, "%sMSGHDR.NEW", cfg.quick_msgpath);
  2525.     if ((outfph = fopen (filename, "wb")) == NULL){
  2526.         printf("! Unable to open tempfile MSGHDR.NEW\n");
  2527.         exit (2);
  2528.     }
  2529.     sprintf (filename, "%sMSGTXT.NEW", cfg.quick_msgpath);
  2530.     if ((outfpt = fopen (filename, "wb")) == NULL){
  2531.         printf("! Unable to open tempfile MSGTXT.NEW\n");
  2532.         exit (2);
  2533.     }
  2534.  
  2535.     fseek (fph, 0L, SEEK_SET);
  2536.  
  2537.     while (fread (&msghdr, sizeof (struct _gold_msghdr), 1, fph) == 1) {
  2538.         if (msghdr.msgattr & Q_RECKILL)
  2539.             continue;
  2540.         if (msghdr.msgnum < 1 || msghdr.board < 1 || msghdr.board > 500)
  2541.             continue;
  2542.  
  2543.         printf ("   Packed Msg.# %ld / %ld\r", msgnum, messages);
  2544.  
  2545.         fseek (fpt, (long)msghdr.startblock * 256L, SEEK_SET);
  2546.  
  2547.         msghdr.startblock = (long)block;
  2548.         if (renum)
  2549.             msghdr.msgnum = msgnum;
  2550.         fwrite (&msghdr, sizeof (struct _gold_msghdr), 1, outfph);
  2551.  
  2552.         for (i = 0; i < msghdr.numblocks; i++) {
  2553.             fread (text, 256, 1, fpt);
  2554.             fwrite (text, 256, 1, outfpt);
  2555.         }
  2556.  
  2557.         msgidx.msgnum = msghdr.msgnum;
  2558.         msgidx.board = msghdr.board;
  2559.         fwrite (&msgidx, sizeof (struct _gold_msgidx), 1, fpi);
  2560.  
  2561.         fwrite (&msghdr.whoto, 36, 1, fpto);
  2562.  
  2563.         if (!msginfo.lowmsg || msghdr.msgnum < msginfo.lowmsg)
  2564.             msginfo.lowmsg = msghdr.msgnum;
  2565.         if (!msginfo.highmsg || msghdr.msgnum > msginfo.highmsg)
  2566.             msginfo.highmsg = msghdr.msgnum;
  2567.         msginfo.totalonboard[msghdr.board - 1]++;
  2568.         msginfo.totalmsgs++;
  2569.  
  2570.         block += msghdr.numblocks;
  2571.         msgnum++;
  2572.     }
  2573.  
  2574.     fclose (outfpt);
  2575.     fclose (outfph);
  2576.     fclose (fpto);
  2577.     fclose (fpi);
  2578.     fclose (fpt);
  2579.     fclose (fph);
  2580.  
  2581.     sprintf (filename, "%sMSGINFO.DAT", cfg.quick_msgpath);
  2582.     if ((fpto = fopen (filename, "wb")) == NULL){
  2583.         printf("! Unable to open MSGINFO.DAT\n");
  2584.         exit (2);
  2585.     }
  2586.     fwrite (&msginfo, sizeof (struct _gold_msginfo), 1, fpto);
  2587.     fclose (fpto);
  2588.  
  2589.     sprintf (filename, "%sMSGHDR.NEW", cfg.quick_msgpath);
  2590.     sprintf (newname, "%sMSGHDR.DAT", cfg.quick_msgpath);
  2591.     unlink (newname);
  2592.     rename (filename, newname);
  2593.  
  2594.     sprintf (filename, "%sMSGTXT.NEW", cfg.quick_msgpath);
  2595.     sprintf (newname, "%sMSGTXT.DAT", cfg.quick_msgpath);
  2596.     unlink (newname);
  2597.     rename (filename, newname);
  2598.  
  2599.     clreol ();
  2600. }
  2601.  
  2602.  
  2603.  
  2604. /* -----------------------------------------------------------------------
  2605.  
  2606.     Sezione di gestione della base messaggi PIP.
  2607.  
  2608.     ----------------------------------------------------------------------- */
  2609. int read0 (unsigned char *s, FILE *f)
  2610. {
  2611.     register int i = 1;
  2612.  
  2613.    while ((*s=fgetc(f)) != 0 && !feof(f) && i < BUFSIZE) {
  2614.       s++;
  2615.       i++;
  2616.    }
  2617.    if (*s == 0)
  2618.       i = 1;
  2619.    else
  2620.       i = 0;
  2621.     *s = 0;
  2622.    return (i);
  2623. }
  2624.  
  2625. int readto0 (FILE *f)
  2626. {
  2627.    register int i = 1;
  2628.  
  2629.    while (fgetc(f) != 0 && !feof(f))
  2630.       i++;
  2631.  
  2632.    return (i);
  2633. }
  2634.  
  2635. void Create_Pip_Index (void)
  2636. {
  2637.    FILE *fpdp = NULL, *f1, *f2;
  2638.    int fd, mn, msgnum;
  2639.    char filename[80], farea = 1, to[36];
  2640.    struct _sys tsys;
  2641.    DESTPTR dp;
  2642.    MSGPTR mp;
  2643.     MSGPKTHDR mpkt;
  2644.  
  2645.    clreol ();
  2646.    printf(" * Create Pip-Base index files\n");
  2647.  
  2648.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2649.    fd = open(filename, O_RDONLY|O_BINARY);
  2650.    if (fd == -1)
  2651.       exit (1);
  2652.  
  2653.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2654.       if ( !tsys.pip_board )
  2655.          continue;
  2656.  
  2657.       if (fpdp == NULL) {
  2658.          sprintf (filename, "%sDESTPTR.PIP", cfg.pip_msgpath);
  2659.          fpdp = fopen (filename, "wb");
  2660.       }
  2661.  
  2662.       sprintf (filename, "%sMPTR%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2663.       f1 = fopen (filename, "rb");
  2664.       if (f1 == NULL)
  2665.          f1 = fopen (filename, "w+b");
  2666.  
  2667.       msgnum = (int)(filelength (fileno (f1)) / (long)sizeof (MSGPTR));
  2668.  
  2669.       sprintf (filename, "%sMPKT%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2670.       f2 = fopen (filename, "rb");
  2671.       if (f2 == NULL)
  2672.          f2 = fopen (filename, "w+b");
  2673.  
  2674.       if (!farea) {
  2675.          gotoxy (wherex (), wherey () - 1);
  2676.          printf("   ├\n");
  2677.       }
  2678.         else
  2679.          farea = 0;
  2680.  
  2681.       printf("   └─ %3d - %-25.25s %-25.25s %d Msg.\n", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  2682.  
  2683.       rewind (f2);
  2684.       rewind (f1);
  2685.       mn = 0;
  2686.  
  2687.       while (fread (&mp, 1, sizeof (MSGPTR), f1) == sizeof (MSGPTR)) {
  2688.          fseek (f2, mp.pos, SEEK_SET);
  2689.          fread (&mpkt, 1, sizeof (MSGPKTHDR), f2);
  2690.  
  2691.             readto0 (f2);     // Date
  2692.          read0 (to, f2);   // To
  2693.  
  2694.          if (!(mp.status & SET_MPTR_DEL)) {
  2695.             memset (&dp, 0, sizeof (MSGPTR));
  2696.             strcpy (dp.to, to);
  2697.             dp.area = tsys.pip_board;
  2698.             dp.msg = mn++;
  2699.             fwrite (&dp, sizeof (DESTPTR), 1, fpdp);
  2700.          }
  2701.          else
  2702.             mn++;
  2703.         }
  2704.  
  2705.       fclose (f2);
  2706.       fclose (f1);
  2707.    }
  2708.  
  2709.    if (fpdp != NULL)
  2710.       fclose (fpdp);
  2711.  
  2712.    close (fd);
  2713. }
  2714.  
  2715. void Link_Pip_Areas (void)
  2716. {
  2717. }
  2718.  
  2719. void Purge_Pip_Areas (void)
  2720. {
  2721.    FILE *f1, *f2;
  2722.    int m, yr, mo, dy, month[12], days;
  2723.    int fd, msgnum, kill, farea = 1;
  2724.    char filename [80], mese[4];
  2725.    long day_mess, day_now, tempo;
  2726.     struct tm *tim;
  2727.    struct _sys tsys;
  2728.    MSGPTR mp;
  2729.  
  2730.    char *mon[] = {
  2731.       "JAN", "FEB", "MAR", "APR", "MAY", "JUN",
  2732.       "JUL", "AUG", "SEP", "OCT", "NOV", "DEC"
  2733.    };
  2734.  
  2735.    month[0] = 31;
  2736.    month[1] = 28;
  2737.    month[2] = 31;
  2738.     month[3] = 30;
  2739.    month[4] = 31;
  2740.    month[5] = 30;
  2741.    month[6] = 31;
  2742.    month[7] = 31;
  2743.    month[8] = 30;
  2744.    month[9] = 31;
  2745.    month[10] = 30;
  2746.    month[11] = 31;
  2747.  
  2748.     clreol ();
  2749.    printf(" * Purging Pip-Base messages\n");
  2750.  
  2751.    tempo = time(0);
  2752.    tim = localtime(&tempo);
  2753.  
  2754.    day_now = 365 * tim->tm_year;
  2755.    for (m = 0; m < tim->tm_mon; m++)
  2756.       day_now += month[m];
  2757.    day_now += tim->tm_mday;
  2758.  
  2759.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2760.    fd = open(filename, O_RDONLY|O_BINARY);
  2761.     if (fd == -1)
  2762.       exit (1);
  2763.  
  2764.    msgnum = 0;
  2765.  
  2766.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2767.       if (!tsys.pip_board)
  2768.          continue;
  2769.  
  2770.       sprintf (filename, "%sMPTR%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2771.       f1 = fopen (filename, "r+b");
  2772.       if (f1 == NULL)
  2773.             f1 = fopen (filename, "w+b");
  2774.  
  2775.       sprintf (filename, "%sMPKT%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2776.       f2 = fopen (filename, "r+b");
  2777.       if (f2 == NULL)
  2778.          f2 = fopen (filename, "w+b");
  2779.  
  2780.       msgnum = (int)(filelength (fileno (f1)) / (long)sizeof (MSGPTR));
  2781.       rewind (f1);
  2782.  
  2783.         if (!farea) {
  2784.          gotoxy (wherex (), wherey () - 1);
  2785.          printf("   ├\n");
  2786.       }
  2787.       else
  2788.          farea = 0;
  2789.  
  2790.       printf("   └─ %3d - %-25.25s %-25.25s %d Msg.\n", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  2791.  
  2792.       if ( (tsys.max_msgs && tsys.max_msgs < msgnum) || tsys.max_age || tsys.age_rcvd ) {
  2793.          kill = msgnum - tsys.max_msgs;
  2794.  
  2795.          while (fread (&mp, sizeof (MSGPTR), 1, f1) == 1) {
  2796.                 if (kill-- <= 0) {
  2797.                kill = 0;
  2798.                fseek (f2, mp.pos + sizeof (MSGPKTHDR), SEEK_SET);
  2799.                read0 (filename, f2);
  2800.  
  2801.                sscanf (filename, "%2d %3s %2d", &dy, mese, &yr);
  2802.                mese[3] = '\0';
  2803.                for (mo = 0; mo < 12; mo++)
  2804.                   if (!stricmp(mese, mon[mo]))
  2805.                      break;
  2806.                if (mo == 12)
  2807.                   mo = 0;
  2808.  
  2809.                day_mess = 365 * yr;
  2810.                for (m = 0; m < mo; m++)
  2811.                   day_mess += month[m];
  2812.                day_mess += dy;
  2813.  
  2814.                days = (int)(day_now - day_mess);
  2815.  
  2816.                if ( days > tsys.max_age && tsys.max_age != 0 ) {
  2817.                   mp.status |= SET_MPTR_DEL;
  2818.                   fseek (f1, -1L * (long)sizeof (MSGPTR), SEEK_CUR);
  2819.                   fwrite (&mp, sizeof (MSGPTR), 1, f1);
  2820.                   fseek (f1, 0L, SEEK_CUR);
  2821.                }
  2822.                else if (mp.status & SET_MPTR_RCVD) {
  2823.                   if ( days > tsys.age_rcvd && tsys.age_rcvd != 0 ) {
  2824.                      mp.status |= SET_MPTR_DEL;
  2825.                      fseek (f1, -1L * (long)sizeof (MSGPTR), SEEK_CUR);
  2826.                      fwrite (&mp, sizeof (MSGPTR), 1, f1);
  2827.                      fseek (f1, 0L, SEEK_CUR);
  2828.                   }
  2829.                }
  2830.             }
  2831.                 else {
  2832.                mp.status |= SET_MPTR_DEL;
  2833.                fseek (f1, -1L * (long)sizeof (MSGPTR), SEEK_CUR);
  2834.                fwrite (&mp, sizeof (MSGPTR), 1, f1);
  2835.                fseek (f1, 0L, SEEK_CUR);
  2836.             }
  2837.          }
  2838.       }
  2839.  
  2840.       fclose (f2);
  2841.       fclose (f1);
  2842.    }
  2843.  
  2844.    close (fd);
  2845. }
  2846.  
  2847. int read0p (unsigned char *s, FILE *f, int max)
  2848. {
  2849.    register int i = 0;
  2850.  
  2851.    while ((*s=fgetc(f)) != 0 && !feof(f) && i < max) {
  2852.       s++;
  2853.       i++;
  2854.    }
  2855.  
  2856.    return (i);
  2857. }
  2858.  
  2859. void Pack_Pip_Areas (void)
  2860. {
  2861.    FILE *f1, *f2, *f1n, *f2n, *fp;
  2862.    int i, fd, fdu, msgnum, farea = 1, nmsg, *lastr, lrpos, m;
  2863.    char filename [80], buff[1024];
  2864.    long pos;
  2865.    struct _sys tsys;
  2866.     struct _usr usr;
  2867.    MSGPTR mp;
  2868.    MSGPKTHDR mpkt;
  2869.    DESTPTR dptr;
  2870.  
  2871.    clreol ();
  2872.    printf(" * Packing Pip-Base messages\n");
  2873.  
  2874.    sprintf (filename, "%sSYSMSG.DAT", cfg.sys_path);
  2875.    fd = open(filename, O_RDONLY|O_BINARY);
  2876.    if (fd == -1)
  2877.       exit (1);
  2878.  
  2879.    msgnum = 0;
  2880.  
  2881.    sprintf (filename, "%sDESTPTR.PIP", cfg.pip_msgpath);
  2882.    fp = fopen (filename, "wb");
  2883.  
  2884.    while ( read(fd, (char *)&tsys.msg_name, SIZEOF_MSGAREA) == SIZEOF_MSGAREA ) {
  2885.       if (!tsys.pip_board)
  2886.          continue;
  2887.  
  2888.       sprintf (filename, "%sMPTR%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2889.       f1 = fopen (filename, "rb");
  2890.       if (f1 == NULL)
  2891.          continue;
  2892.  
  2893.       sprintf (filename, "%sMPKT%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2894.       f2 = fopen (filename, "rb");
  2895.       if (f2 == NULL) {
  2896.          fclose (f1);
  2897.          continue;
  2898.       }
  2899.  
  2900.       sprintf (filename, "%sMPTR%04x.NEW", cfg.pip_msgpath, tsys.pip_board);
  2901.         f1n = fopen (filename, "wb");
  2902.  
  2903.       sprintf (filename, "%sMPKT%04x.NEW", cfg.pip_msgpath, tsys.pip_board);
  2904.       f2n = fopen (filename, "wb");
  2905.  
  2906.       msgnum = (int)(filelength (fileno (f1)) / (long)sizeof (MSGPTR));
  2907.       rewind (f1);
  2908.  
  2909.       msgnum++;
  2910.       lastr = (int *)malloc (msgnum * sizeof (int));
  2911.       memset (lastr, 0, msgnum * sizeof (int));
  2912.       msgnum--;
  2913.  
  2914.       if (!farea) {
  2915.          gotoxy (wherex (), wherey () - 1);
  2916.          printf("   ├\n");
  2917.       }
  2918.       else
  2919.          farea = 0;
  2920.  
  2921.       printf("   └─ %3d - %-25.25s %-25.25s %d Msg.\n", tsys.msg_num, tsys.msg_name, tsys.echomail ? tsys.echotag : "", msgnum);
  2922.       nmsg = 0;
  2923.       lrpos = 1;
  2924.  
  2925.       while (fread (&mp, sizeof (MSGPTR), 1, f1) == 1) {
  2926.          if (!(mp.status & SET_MPTR_DEL)) {
  2927.             lastr[lrpos++] = nmsg + 1;
  2928.             fseek (f2, mp.pos, SEEK_SET);
  2929.  
  2930.             mp.pos = ftell (f2n);
  2931.             fwrite (&mp, sizeof (MSGPTR), 1, f1n);
  2932.  
  2933.             fread (&mpkt, sizeof (MSGPKTHDR), 1, f2);
  2934.             fwrite (&mpkt, sizeof (MSGPKTHDR), 1, f2n);
  2935.  
  2936.                 i = read0p (buff, f2, 20);
  2937.             fwrite (buff, i + 1, 1, f2n);
  2938.             i = read0p (buff, f2, 36);
  2939.             fwrite (buff, i + 1, 1, f2n);
  2940.  
  2941.             memset (&dptr, 0, sizeof (DESTPTR));
  2942.             dptr.area = tsys.pip_board;
  2943.             dptr.msg = nmsg++;
  2944.             strcpy (dptr.to, buff);
  2945.             fwrite (&dptr, sizeof (DESTPTR), 1, fp);
  2946.  
  2947.             i = read0p (buff, f2, 36);
  2948.                 fwrite (buff, i + 1, 1, f2n);
  2949.             i = read0p (buff, f2, 72);
  2950.             fwrite (buff, i + 1, 1, f2n);
  2951.  
  2952.             do {
  2953.                i = read0p (buff, f2, 1024);
  2954.                fwrite (buff, i, 1, f2n);
  2955.             } while (i == 1024);
  2956.  
  2957.             fputc (0, f2n);
  2958.          }
  2959.          else
  2960.             lrpos++;
  2961.       }
  2962.  
  2963.       fputc (0, f2n);
  2964.       fputc (0, f2n);
  2965.  
  2966.       fclose (f2n);
  2967.       fclose (f1n);
  2968.       fclose (f2);
  2969.       fclose (f1);
  2970.  
  2971.         sprintf (filename, "%sMPTR%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2972.       sprintf (buff, "%sMPTR%04x.NEW", cfg.pip_msgpath, tsys.pip_board);
  2973.       unlink (filename);
  2974.       rename (buff, filename);
  2975.  
  2976.       sprintf (filename, "%sMPKT%04x.PIP", cfg.pip_msgpath, tsys.pip_board);
  2977.       sprintf (buff, "%sMPKT%04x.NEW", cfg.pip_msgpath, tsys.pip_board);
  2978.       unlink (filename);
  2979.       rename (buff, filename);
  2980.  
  2981.       sprintf (filename, "%s.BBS", cfg.user_file);
  2982.       fdu = open (filename, O_RDWR | O_BINARY);
  2983.         pos = tell (fdu);
  2984.  
  2985.       while (read(fdu, (char *) &usr, sizeof(struct _usr)) == sizeof(struct _usr)) {
  2986.          for (i = 0; i < MAXLREAD; i++)
  2987.             if (usr.lastread[i].area == tsys.msg_num)
  2988.                break;
  2989.  
  2990.          if (i < MAXLREAD) {
  2991.             m = usr.lastread[i].msg_num;
  2992.             if (m > msgnum)
  2993.                m = msgnum;
  2994.             if (m < 0)
  2995.                m = 0;
  2996.             while (m > 0 && lastr[m] == 0)
  2997.                m--;
  2998.             usr.lastread[i].msg_num = lastr[m];
  2999.  
  3000.             lseek (fdu, pos, 0);
  3001.             write (fdu, (char *) &usr, sizeof(struct _usr));
  3002.          }
  3003.          else {
  3004.             for (i = 0; i < MAXDLREAD; i++)
  3005.                if (usr.dynlastread[i].area == tsys.msg_num)
  3006.                         break;
  3007.  
  3008.             if (i < MAXDLREAD) {
  3009.                m = usr.dynlastread[i].msg_num;
  3010.                if (m > msgnum)
  3011.                   m = msgnum;
  3012.                if (m < 0)
  3013.                   m = 0;
  3014.                while (m > 0 && lastr[m] == 0)
  3015.                   m--;
  3016.                usr.dynlastread[i].msg_num = lastr[m];
  3017.  
  3018.                     lseek (fdu, pos, 0);
  3019.                write (fdu, (char *) &usr, sizeof (struct _usr));
  3020.             }
  3021.          }
  3022.  
  3023.          pos = tell (fdu);
  3024.       }
  3025.  
  3026.       close (fdu);
  3027.  
  3028.       if (lastr != NULL)
  3029.          free (lastr);
  3030.    }
  3031.  
  3032.    fclose (fp);
  3033.    close (fd);
  3034. }
  3035.  
  3036. void main (argc, argv)
  3037. int argc;
  3038. char *argv[];
  3039. {
  3040.    int i, xlink, unknow, renum, pack, purge, overwrite;
  3041.     int link, stats, index, xsquish, xfido, xpip, xquick, xgold;
  3042.  
  3043.    printf("\nLMSG; LoraBBS-OS/2 Message maintenance utility, Version %s\n", LMSG_VERSION);
  3044.    printf("      Copyright (c) 1991-96 by Marco Maccaferri, All Rights Reserved\n\n");
  3045.  
  3046.    xlink = unknow = renum = pack = purge = overwrite = 0;
  3047.    link = stats = index = 0;
  3048.    xquick = xfido = xsquish = xpip = xgold = 0;
  3049.  
  3050.    for (i = 1; i < argc; i++) {
  3051.       if (argv[i][0] != '-') {
  3052.          cfgname = argv[i];
  3053.          continue;
  3054.       }
  3055.       if (!strnicmp (argv[i], "-I", 2)) {
  3056.          index = 1;
  3057.          if (strchr (argv[i], 'C') != NULL || strchr (argv[i], 'c') != NULL)
  3058.             xlink = 1;
  3059.          if (strchr (argv[i], 'U') != NULL || strchr (argv[i], 'u') != NULL)
  3060.             unknow = 1;
  3061.          if (strchr (argv[i], 'R') != NULL || strchr (argv[i], 'r') != NULL)
  3062.             renum = 1;
  3063.       }
  3064.       if (!strnicmp (argv[i], "-P", 2)) {
  3065.          pack = 1;
  3066.          if (strchr (argv[i], 'K') != NULL || strchr (argv[i], 'k') != NULL)
  3067.             purge = 1;
  3068.          if (strchr (argv[i], 'O') != NULL || strchr (argv[i], 'o') != NULL)
  3069.             overwrite = 1;
  3070.             if (strchr (argv[i], 'R') != NULL || strchr (argv[i], 'r') != NULL)
  3071.             renum = 1;
  3072.             if (strchr (argv[i], 'A') != NULL || strchr (argv[i], 'a') != NULL)
  3073.             overwrite = 2;
  3074.       }
  3075.       if (!strnicmp (argv[i], "-X", 2)) {
  3076.          if (strchr (argv[i], 'F') != NULL || strchr (argv[i], 'f') != NULL)
  3077.             xfido = 1;
  3078.          if (strchr (argv[i], 'Q') != NULL || strchr (argv[i], 'q') != NULL)
  3079.             xquick = 1;
  3080.          if (strchr (argv[i], 'S') != NULL || strchr (argv[i], 's') != NULL)
  3081.             xsquish = 1;
  3082.          if (strchr (argv[i], 'P') != NULL || strchr (argv[i], 'p') != NULL)
  3083.             xpip = 1;
  3084.             if (strchr (argv[i], 'G') != NULL || strchr (argv[i], 'g') != NULL)
  3085.             xgold = 1;
  3086.       }
  3087.       if (!stricmp (argv[i], "-K"))
  3088.          purge = 1;
  3089.       if (!stricmp (argv[i], "-L"))
  3090.          link = 1;
  3091.       if (!stricmp (argv[i], "-R"))
  3092.          renum = 1;
  3093.       if (!stricmp (argv[i], "-S"))
  3094.          stats = 1;
  3095.    }
  3096.  
  3097.    if ( (!xlink && !unknow && !renum && !pack && !purge && !overwrite && !link && !stats && !index) || argc == 1 ) {
  3098.       printf(" * Command-line parameters:\n\n");
  3099.  
  3100.       printf("        <File>    Configuration file name\n");
  3101.       printf("        -I[UR]    Recreate index files & check\n");
  3102.       printf("                  U=Kill unknown boards  R=Renumber\n");
  3103.       printf("        -P[KR]    Pack (compress) message base\n");
  3104.       printf("                  K=Purge  R=Renumber\n");
  3105.         printf("        -K        Purge messages from info in SYSMSG.DAT\n");
  3106.       printf("        -R        Renumber messages\n");
  3107.         printf("        -L        Link messages by subject\n");
  3108.       printf("        -X[FQSPG] Exclude message base\n");
  3109.       printf("                  F=Fido  Q=Quick  S=Squish  P=Pipbase  G=GoldBase\n\n");
  3110.  
  3111.       printf(" * Please refer to the documentation for a more complete command summary\n\n");
  3112.    }
  3113.    else {
  3114.       Get_Config_Info ();
  3115.  
  3116.       if (index) {
  3117.          if (!xfido) {
  3118.             if (renum)
  3119.                     Renum_Fido_Areas ();
  3120.             Create_Fido_Index ();
  3121.          }
  3122.          if (!xquick)
  3123.             Create_Quick_Index (xlink, unknow, renum);
  3124.          if (!xgold)
  3125.             Create_Gold_Index (xlink, unknow, renum);
  3126.          if (!xpip)
  3127.             Create_Pip_Index ();
  3128.       }
  3129.  
  3130.       if (purge) {
  3131.          if (!xfido)
  3132.             Purge_Fido_Areas (renum);
  3133.          if (!xquick)
  3134.                 Purge_Quick_Areas (renum);
  3135.             if (!xgold)
  3136.                 Purge_Gold_Areas (renum);
  3137.             if (!xsquish)
  3138.                 Purge_Squish_Areas ();
  3139.             if (!xpip)
  3140.                 Purge_Pip_Areas ();
  3141.         }
  3142.  
  3143.         if (pack) {
  3144.             if (!xquick)
  3145.                 Pack_Quick_Base (renum);
  3146.             if (!xgold)
  3147.                 Pack_Gold_Base (renum);
  3148.             if (!xsquish)
  3149.                 Pack_Squish_Areas ();
  3150.             if (!xpip)
  3151.                 Pack_Pip_Areas ();
  3152.         }
  3153.  
  3154.         if (renum && !purge && !index) {
  3155.             if (!xfido)
  3156.                 Renum_Fido_Areas ();
  3157.             if (!xquick)
  3158.                 Renum_Quick_Areas ();
  3159.         }
  3160.  
  3161.         if (link) {
  3162.             if (!xfido)
  3163.                 Link_Fido_Areas ();
  3164.             if (!xquick)
  3165.                 Link_Quick_Areas ();
  3166.             if (!xsquish)
  3167.                 Link_Squish_Areas ();
  3168.             if (!xpip)
  3169.                 Link_Pip_Areas ();
  3170.         }
  3171.  
  3172.         clreol ();
  3173.         printf(" * Done.\n\n");
  3174.     }
  3175. }
  3176.  
  3177.