home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / MNUM416D.SZH / MSGNUM.C < prev    next >
Text File  |  1991-04-16  |  41KB  |  1,429 lines

  1. /*
  2.                           Message Base Renumberer
  3.  
  4.               This module was originally written by Bob Hartman
  5.                        Sysop of FidoNet node 1:132/101
  6.  
  7.    Spark Software, 427-3 Amherst St, CS 2032, Suite 232, Nashua, NH 03061
  8.  
  9.  This program source code is being released with the following provisions:
  10.  
  11.  1.  You are  free to make  changes to this source  code for use on your own
  12.  machine,  however,  altered source files may not be distributed without the
  13.  consent of Spark Software.
  14.  
  15.  2.  You may distribute "patches"  or  "diff" files for any changes that you
  16.  have made, provided that the "patch" or "diff" files are also sent to Spark
  17.  Software for inclusion in future releases of the entire package.   A "diff"
  18.  file for the source archives may also contain a compiled version,  provided
  19.  it is  clearly marked as not  being created  from the original source code.
  20.  No other  executable  versions may be  distributed without  the  consent of
  21.  Spark Software.
  22.  
  23.  3.  You are free to include portions of this source code in any program you
  24.  develop, providing:  a) Credit is given to Spark Software for any code that
  25.  may is used, and  b) The resulting program is free to anyone wanting to use
  26.  it, including commercial and government users.
  27.  
  28.  4.  There is  NO  technical support  available for dealing with this source
  29.  code, or the accompanying executable files.  This source  code  is provided
  30.  as is, with no warranty expressed or implied (I hate legalease).   In other
  31.  words, if you don't know what to do with it,  don't use it,  and if you are
  32.  brave enough to use it, you're on your own.
  33.  
  34.  Spark Software may be contacted by modem at (603) 888-8179 (node 1:132/101)
  35.  on the public FidoNet network, or at the address given above.
  36.  
  37. */
  38.  
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <stdio.h>
  42. #include <ctype.h>
  43. #include <fcntl.h>
  44. #include <sys\types.h>
  45. #include <sys\stat.h>
  46. #include <io.h>
  47. #include <dos.h>
  48. #include <direct.h>
  49.  
  50. #ifdef OS_2
  51. #define DOS_INCL_DOSFILEMGR
  52. #include <os2.h>
  53. #endif
  54.  
  55. #include "bbsdev.h"
  56. #ifndef OS_2
  57. #include "diskio.h"
  58. #endif
  59.  
  60. char *REV="$Revision: 4.16d $";   /* Used in my code for my RCS program */
  61.  
  62. #define MSG_EXISTS       1
  63. #define MSG_DELETED      2
  64. #define MSG_LINK_CHANGED 4
  65.  
  66. #define YEAR(x)   ((((x)->date>>9)&0x7f))
  67. #define MONTH(x)  (((x)->date>>5)&0x0f)
  68. #define DAY(x)    ((x)->date&0x1f)
  69.  
  70. long days_to_month[12] = {
  71.    0L, 31L, 59L, 90L, 120L, 151L, 181L, 212L, 243L, 273L, 304L, 334L
  72. };
  73.  
  74. static char *_days[7] = {
  75.    "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
  76. };
  77.  
  78. static char *_months[12] = {
  79.         "JANUARY", "FEBRUARY", "MARCH",     "APRIL",   "MAY",      "JUNE",
  80.         "JULY",    "AUGUST",   "SEPTEMBER", "OCTOBER", "NOVEMBER", "DECEMBER"
  81. };
  82.  
  83. #ifndef OS_2
  84. #define MAX_PATH 80
  85. #else
  86. #define MAX_PATH 260
  87. #endif
  88. char dir_drive1[MAX_PATH];
  89. char dir_drive2[MAX_PATH];
  90. char dir_drive3[MAX_PATH];
  91.  
  92. typedef struct msgtyp {
  93.    int  msg_num;
  94.    int  msg_out_num;
  95.    long msg_time;
  96.    int  msg_up;
  97.    int  msg_down;
  98.    int  msg_attr;
  99.    int  msg_flags;
  100. } MSG_TYP;
  101.  
  102. #define MAXLASTREADS 16
  103. #define MAX_MSGS 2048
  104. #define MAX_USERS 32
  105. #define MAX_NAME 33
  106.  
  107. char areaname[MAX_PATH];
  108. char opus_sys_path[MAX_PATH];
  109.  
  110. MSG msg_tmp;
  111. MSG_TYP msgs[MAX_MSGS+1];
  112. SYS curr_system;
  113. USR users[MAX_USERS];
  114. _usr opus_user;
  115. _sys opus_sys;
  116.  
  117. int help;
  118. int max;
  119. int qmail;
  120. int n_msgs;
  121. int kills[10];
  122. int n_kills;
  123. int opus;
  124. int opus_120;
  125. int quiet;
  126. int renum;
  127.  
  128. int kill_n1, kill_n2;
  129. int kill_date;
  130. int kill_sent;
  131. int areanum = -1;
  132.  
  133. #define KILL_N    1
  134. #define KILL_DATE 2
  135. #define KILL_RCVD 4
  136. #define KILL_SENT 8
  137.  
  138. char tmpjunk2[MAX_PATH];
  139.  
  140. int total_reserved;
  141. char dta[128];
  142.  
  143. void main (int argc, char *argv[])
  144. {
  145.     register int i;
  146.     register MSG_TYP *mptr;
  147.     MSG_TYP *m;
  148.     int j;
  149.     char buff1[20], buff2[20]; /* Junk buffers */
  150.  
  151.     /* Process command line */
  152.     if (argc == 1)
  153.         help++;
  154.  
  155.     while (--argc)
  156.     {
  157.         ++argv;
  158.         if (argv[0][0] == '?')
  159.             help++;
  160.         if ((argv[0][0] == '-') || (argv[0][0] == '/'))
  161.         {
  162.             switch (tolower (argv[0][1]))
  163.             {
  164.                 case 'a':
  165.                     qmail++;
  166.                     break;
  167.  
  168.                 case 'd':
  169.                     kill_date = atoi (argv[1]);
  170.                     ++argv;
  171.                     --argc;
  172.                     kills[n_kills++] = KILL_DATE;
  173.                     break;
  174.  
  175.                 case 'k':
  176.                     kills[n_kills++] = KILL_RCVD;
  177.                     break;
  178.  
  179.                 case 'm':
  180.                     max++;
  181.                     break;
  182.  
  183.                 case 'n':
  184.                     kill_n1 = atoi (argv[1]);
  185.                     kill_n2 = atoi (argv[2]);
  186.                     argv += 2;
  187.                     argc -= 2;
  188.                     kills[n_kills++] = KILL_N;
  189.                     break;
  190.  
  191.                 case 'o':
  192.                     opus++;
  193.                     if (argv[0][2] == '1')
  194.                         opus_120++;
  195.                     break;
  196.  
  197.                 case 'q':
  198.                     quiet++;
  199.                     break;
  200.  
  201.                 case 'r':
  202.                     renum++;
  203.                     break;
  204.  
  205.                 case 's':
  206.                     kill_sent++;
  207.                     kills[n_kills++] = KILL_SENT;
  208.                     break;
  209.  
  210.                 case '?':
  211.                     help++;
  212.                     break;
  213.  
  214.                 default:
  215.                     printf ("Unknown option '%s'\n", argv[0]);
  216.                     help++;
  217.             }
  218.         }
  219.     }
  220.  
  221.     if (!quiet || help)
  222.     {
  223.         /* Say hello to the world */
  224.         sscanf (REV, "$%s %s", buff1, buff2);
  225. #ifdef OS_2
  226.         printf ("\nMsgNumOS2 - %s %s by Bill Andrus, FidoNet Node 1:109/301.0\n", buff1, buff2);
  227. #else
  228.         printf ("\nMsgNum - %s %s by Bill Andrus, FidoNet Node 1:109/301.0\n", buff1, buff2);
  229. #endif
  230.         printf ("Includes OPUS 1.20 mods from Graham Stair, FidoNet Node 3:711/409.\n");
  231.         printf ("Based on copyrighted source files from Bob Hartman.\n");
  232.         printf ("Copyright 1985-88 Spark Software, Inc.   All rights reserved.\n\n");
  233.     }
  234.  
  235.     if (help)
  236.         msgnum_usage();
  237.  
  238.     /* Get to proper directory, saving where we are */
  239.     getcwd (dir_drive1, MAX_PATH);
  240.     getcwd (dir_drive2, MAX_PATH);
  241.     if (opus)
  242.     {
  243.         if (get_opus (argv[0], &opus_sys) < 0)
  244.         {
  245.             printf ("Cannot make sense of '%s'\n", argv[0]);
  246.             (void) go_directory (dir_drive2, NULL);
  247.             (void) go_directory (dir_drive1, NULL);
  248.             exit (1);
  249.         }
  250.     }
  251.     else
  252.     {
  253.         if (get_system (argv[0], &curr_system) < 0)
  254.         {
  255.             printf ("Cannot make sense of '%s'\n", argv[0]);
  256.             (void) go_directory (dir_drive2, NULL);
  257.             (void) go_directory (dir_drive1, NULL);
  258.             exit (1);
  259.         }
  260.     }
  261.  
  262.     getcwd (dir_drive3, MAX_PATH);
  263.     if (!quiet)
  264.     {
  265.         if (areanum >= 0) {
  266.             if (opus) {
  267.                 if (opus_120) {
  268.                     printf ("Using Opus 1.2+ SYSTEM%02X.DAT file in '%s' ...\n", areanum, dir_drive1);
  269.                 } else {
  270.                     printf ("Using Opus 1.1+ SYSTEM%02X.DAT file in '%s' ...\n", areanum, dir_drive1);
  271.                 }
  272.             } else {
  273.                 printf ("Using Opus 1.0x SYSTEM%2d.BBS file in '%s' ...\n", areanum, dir_drive1);
  274.             }
  275.         } else {
  276.             printf ("Using Directory '%s' ...\n", dir_drive3);
  277.         }
  278.     }
  279.  
  280.     /* Read in all message data */
  281.     if (!quiet)
  282.         printf ("Reading in message data ...\n");
  283.     read_msg_data ();
  284.  
  285.     /* Process each kill function in order */
  286.     if (n_msgs)
  287.     {
  288.         if (!quiet)
  289.             printf ("Processing message data ...\n");
  290.         for (i = 0; i < n_kills; i++)
  291.         {
  292.             switch (kills[i])
  293.             {
  294.                 case KILL_N:
  295.                     kill_number ();
  296.                     break;
  297.  
  298.                 case KILL_DATE:
  299.                     kill_by_date ();
  300.                     break;
  301.  
  302.                 case KILL_RCVD:
  303.                     kill_attr (MSGREAD);
  304.                     break;
  305.  
  306.                 case KILL_SENT:
  307.                     kill_attr (MSGSENT);
  308.                     break;
  309.  
  310.                 default:
  311.                     break;
  312.             }
  313.         }
  314.     }
  315.  
  316.     /* Do any necessary renumbering */
  317.     if (renum && n_msgs)
  318.     {
  319.         if (!quiet)
  320.             printf ("Renumbering remaining message(s) ...\n");
  321.         for (mptr = &msgs[1], i = j = 1; i <= n_msgs; mptr++, i++)
  322.         {
  323.             if (mptr->msg_flags & MSG_EXISTS)
  324.                 mptr->msg_out_num = j++;
  325.         }
  326.     }
  327.  
  328.     if (n_msgs)
  329.     {
  330.         /* Update 1.MSG HWM */
  331.         if (!quiet)
  332.             printf ("Updating 1.MSG High Water Mark ...\n");
  333.         m = &msgs[1];
  334.         if (((i = m->msg_down) > 1) && (m->msg_down <= n_msgs))
  335.         {
  336.             mptr = &msgs[i];
  337.             if (mptr->msg_flags & MSG_EXISTS)
  338.             {
  339.                 if (m->msg_flags & MSG_EXISTS)
  340.                 {
  341.                     m->msg_down = mptr->msg_out_num;
  342.                     if (i != mptr->msg_out_num)
  343.                         m->msg_flags |= MSG_LINK_CHANGED;
  344.                 }
  345.                 else
  346.                 {
  347.                     for (m = &msgs[2], j = 2; j <= n_msgs; j++, m++)
  348.                     {
  349.                         if ((m->msg_flags & MSG_EXISTS) && (m->msg_out_num == 1))
  350.                         {
  351.                             m->msg_down = mptr->msg_out_num;
  352.                             m->msg_flags |= MSG_LINK_CHANGED;
  353.                             break;
  354.                         }
  355.                     }
  356.                 }
  357.             }
  358.             else    /* zap (new) 1.msg */
  359.             {
  360.                 if (!(m->msg_flags & MSG_EXISTS))
  361.                 {
  362.                     for (m = &msgs[2], j = 2; j <= n_msgs; j++, m++)
  363.                     {
  364.                         if ((m->msg_flags & MSG_EXISTS) && (m->msg_out_num == 1))
  365.                             break;
  366.                     }
  367.                 }
  368.                 m->msg_down = 0;
  369.                 m->msg_flags |= MSG_LINK_CHANGED;
  370.             }
  371.         }
  372.         else    /* summats wrong */
  373.         {
  374.             if (!(m->msg_flags & MSG_EXISTS))
  375.             {
  376.                 for (m = &msgs[2], j = 2; j <= n_msgs; j++, m++)
  377.                 {
  378.                     if ((m->msg_flags & MSG_EXISTS) && (m->msg_out_num == 1))
  379.                         break;
  380.                 }
  381.             }
  382.             m->msg_down = 0;
  383.             m->msg_flags |= MSG_LINK_CHANGED;
  384.         }
  385.     }
  386.  
  387.     /* Process message links */
  388.     if (n_msgs)
  389.     {
  390.         if (!quiet)
  391.             printf ("Relinking remaining message(s) ...\n");
  392.         for (mptr = &msgs[1], i = 1; i <= n_msgs; mptr++, i++)
  393.         {
  394.             if (mptr->msg_flags & MSG_DELETED)
  395.                 continue;
  396.  
  397.             if ((mptr->msg_up <= n_msgs) && ((j = mptr->msg_up) != 0))
  398.             {
  399.                 /* Follow the chain up to one that is good */
  400.                 while ((j <= n_msgs) && (j > 0) && (msgs[j].msg_flags & MSG_DELETED))
  401.                 {
  402.                     /* If we somehow go backwards, bag out because we won't recover */
  403.                     if ((j > n_msgs) || (j <= 0) || (msgs[j].msg_up <= j))
  404.                         break;
  405.                     j = msgs[j].msg_up;
  406.                 }
  407.                 if ((j <= n_msgs) && (j > 0) && (msgs[j].msg_flags & MSG_EXISTS))
  408.                 {
  409.                     if (msgs[j].msg_out_num != mptr->msg_up)
  410.                         mptr->msg_flags |= MSG_LINK_CHANGED;
  411.                     mptr->msg_up = msgs[j].msg_out_num;
  412.                 }
  413.                 else
  414.                 {
  415.                     mptr->msg_flags |= MSG_LINK_CHANGED;
  416.                     mptr->msg_up = 0;
  417.                 }
  418.             }
  419.  
  420.             if (((j = mptr->msg_down) != 0) && (mptr->msg_out_num > 1))
  421.             {
  422.                 /* Follow the chain up to one that is good */
  423.                 while ((j <= n_msgs) && (msgs[j].msg_flags & MSG_DELETED))
  424.                 {
  425.                     /* If we somehow go forwards, bag out because we won't recover */
  426.                     if ((msgs[j].msg_down >= j) || (msgs[j].msg_down > n_msgs))
  427.                         break;
  428.                     j = msgs[j].msg_down;
  429.                 }
  430.                 if ((j <= n_msgs) && (msgs[j].msg_flags & MSG_EXISTS))
  431.                 {
  432.                     if (msgs[j].msg_out_num != mptr->msg_down)
  433.                         mptr->msg_flags |= MSG_LINK_CHANGED;
  434.                     mptr->msg_down = msgs[j].msg_out_num;
  435.                 }
  436.                 else
  437.                 {
  438.                     mptr->msg_flags |= MSG_LINK_CHANGED;
  439.                     mptr->msg_down = 0;
  440.                 }
  441.             }
  442.         }
  443.     }
  444.  
  445.     if (n_msgs)
  446.     {
  447.         /* Update lastread pointer */
  448.         fix_lastread ();
  449.         if (max)
  450.             renum_max_lastread ();
  451.         if (opus_120)
  452.             renum_opus120_lastread ();
  453.     }
  454.  
  455.     /* Update user.bbs */
  456.     if ((areanum >= 0) && n_msgs)
  457.     {
  458.         if (!quiet)
  459.             printf ("Updating Opus %s user lastread pointers ...\n",(opus)?("1.1+"):("1.0x"));
  460.         if (go_directory (dir_drive1, NULL))
  461.         {
  462.             printf ("Cannot seem to change directories back to %s\n", dir_drive1);
  463.         }
  464.         if (opus)
  465.             renum_opus (areanum);
  466.         else
  467.             renum_users (areanum);
  468.         if (go_directory (dir_drive3, NULL))
  469.         {
  470.             printf ("Cannot seem to change directories back to %s\n", dir_drive3);
  471.         }
  472.     }
  473.  
  474.     /* Delete messages marked for deletion and perform any necessary renames */
  475.     if ((renum || n_kills) && (n_msgs))
  476.     {
  477.         if (!quiet)
  478.             printf ("Renaming %smessage(s) ...\n", n_kills ? "and deleting " : "");
  479.         write_msg_data ();
  480.     }
  481.  
  482.     if (n_msgs)
  483.         /* Re-link the reply chains */
  484.         if (!quiet)
  485.             printf ("Writing new message header links ...\n");
  486.         relink ();
  487.  
  488.     if (go_directory (dir_drive2, NULL))
  489.     {
  490.         printf ("Cannot seem to change directories back to %s\n", dir_drive2);
  491.     }
  492.  
  493.     if (go_directory (dir_drive1, NULL))
  494.     {
  495.         printf ("Cannot seem to change directories back to %s\n", dir_drive1);
  496.     }
  497.  
  498.     if (!quiet)
  499.         printf ("Done!\n");
  500. }
  501.  
  502. int compare (MSG_TYP *arg1,MSG_TYP *arg2)
  503. {
  504.       return (arg1->msg_num - arg2->msg_num);
  505. }
  506.  
  507. void get_date (char *fmt,char *d)
  508. {
  509. #ifndef OS_2
  510.     union REGS    inregs;
  511. #endif
  512.     union REGS    outregs;
  513.     char    temp[5];    /* To hold date so it can be processed again */
  514.  
  515. #ifndef OS_2
  516.     inregs.h.ah = 0x2a;
  517.     (void) intdos (&inregs, &outregs);
  518. #else
  519.     dosdate ((int *)&outregs.h.dh, (int *)&outregs.h.dl, (int *)&outregs.x.cx, (int *)&outregs.h.al);
  520. #endif
  521.     /* Now go through the format string */
  522.     while (*fmt != '\0')
  523.     {
  524.         if (*fmt != ESCAPE_CHAR)
  525.             *d++ = *fmt;
  526.         else
  527.         {
  528.             switch (*(++fmt))
  529.             {
  530.                 case 'n':
  531.                     sprintf (d, "%.3s",
  532.                     _months[outregs.h.dh - 1]);
  533.                     d += 3;
  534.                     break;
  535.  
  536.                 case 'N':
  537.                     sprintf (d, "%s",
  538.                        _months[outregs.h.dh - 1]);
  539.                     d += strlen (d);
  540.                     break;
  541.  
  542.                 case 'm':
  543.                     sprintf (d, "%02d", outregs.h.dh);
  544.                     d += 2;
  545.                     break;
  546.  
  547.                 case 'd':
  548.                     sprintf (d, "%02d", outregs.h.dl);
  549.                     d += 2;
  550.                     break;
  551.  
  552.                 case 'w':
  553.                     sprintf (d, "%.3s",
  554.                        _days[outregs.h.ah]);
  555.                     d += 3;
  556.                     break;
  557.  
  558.                 case 'W':
  559.                     sprintf (d, "%s",
  560.                        _days[outregs.h.ah]);
  561.                     d += strlen (d);
  562.                     break;
  563.  
  564.                 case 'y':
  565.                     sprintf (temp, "%04d", outregs.x.cx);
  566.                     sprintf (d, "%.2s", temp+2);
  567.                     d += 2;
  568.                     break;
  569.  
  570.                 case 'Y':
  571.                     sprintf (d, "%04d", outregs.x.cx);
  572.                     d += 4;
  573.                     break;
  574.  
  575.                 default:
  576.                     *d++ = *fmt;
  577.             }
  578.         }
  579.  
  580.         ++fmt;
  581.     }
  582.  
  583.     *d = '\0';      /* Just to be sure that it is null terminated */
  584. }
  585.  
  586. long days_from_1980 (MSG_PTR str)
  587. {
  588.     long ret_val, y, d;
  589.     int i;
  590.     char m[60], junk[60];
  591.  
  592.     if (((str->date[19])&0xff) != 0xff)
  593.     {
  594.         if (sscanf (str->date, "%ld %s %ld", &d, m, &y) != 3)
  595.             if (sscanf (str->date, "%s %ld %s %ld", junk, &d, m, &y) != 4)
  596.                 return (600000L);
  597.         for (i = 0; i < 12; ++i)
  598.         {
  599.             if (strnicmp (_months[i], m, 3) == 0)
  600.                 break;
  601.         }
  602.         if ((i == 12) && (strnicmp("MEI", m, 3) == 0))
  603.             i=4;
  604.         y -= 80;
  605.     }
  606.     else
  607.     {
  608.         y = (long) (YEAR (&(str->_date_arrived)));
  609.         d = (long) (DAY (&(str->_date_arrived)));
  610.         i = MONTH (&(str->_date_arrived)) - 1;
  611.     }
  612.     ret_val = y;
  613.     ret_val *= 365;
  614.     ret_val += d;
  615.  
  616.     if (i < 12)
  617.         ret_val += days_to_month[i];
  618.  
  619.     return (ret_val);
  620. }
  621.  
  622. void read_msg_data ()
  623. {
  624.     int i, f;
  625.     MSG     *m;
  626.     register MSG_TYP *mptr;
  627.     char junk[64], junk2[64];
  628.     char name[20];
  629.  
  630.     sprintf (junk, "*.MSG");
  631.     (void) filedir (junk, 0, name, 0);
  632.     while (name[0] != '\0')
  633.     {
  634.         i = 0;
  635.         sscanf (name, "%d.", &i);
  636.         if ((i > 0) && (i <= MAX_MSGS))
  637.         {
  638.             mptr = &msgs[i];
  639.             mptr->msg_out_num = mptr->msg_num = i;
  640.             mptr->msg_flags = MSG_EXISTS;
  641.  
  642.             /* Extract current message header fields */
  643.             m = &msg_tmp;
  644.             sprintf (junk2, "%d.MSG", mptr->msg_out_num);
  645.             if ((f = fast_open (junk2, O_RDONLY|O_BINARY)) == -1)
  646.             {
  647.                 printf ("Error opening '%s'\n", junk2);
  648.                 mptr->msg_out_num = 0;
  649.                 mptr->msg_flags = MSG_DELETED;
  650.             }
  651.             else
  652.             {
  653.                 if (fast_read (f, (char *) m, sizeof (MSG)) != sizeof (MSG))
  654.                 {
  655.                     printf ("Error reading '%s'\n", junk2);
  656.                     mptr->msg_out_num = 0;
  657.                     mptr->msg_flags = MSG_DELETED;
  658.                     (void) fast_close (f);
  659.                 }
  660.                 else
  661.                 {
  662.                     (void) fast_close (f);
  663.                     mptr->msg_up = m->up;
  664.                     mptr->msg_down = m->reply;
  665.                     mptr->msg_attr = m->attr;
  666.                     mptr->msg_time = days_from_1980 (m);
  667.                     n_msgs = max(n_msgs, i);
  668.                 }
  669.             }
  670.         }
  671.         (void) filedir (junk, 1, name, 0);
  672.     }
  673. }
  674.  
  675. void write_msg_data ()
  676. {
  677.     register int i;
  678.     register MSG_TYP *mptr;
  679.     int err;
  680.     char oldname[16], newname[16];
  681.  
  682.     (void) qsort ((char *) &msgs[1], n_msgs, sizeof (MSG_TYP), compare);
  683.     for (mptr = &msgs[1], i = 1; i <= n_msgs; mptr++, i++)
  684.     {
  685.         if (mptr->msg_flags & MSG_DELETED)
  686.         {
  687.             sprintf (oldname, "%d.MSG", mptr->msg_num);
  688.             unlink(oldname);
  689.             continue;
  690.         }
  691.         if ((mptr->msg_out_num != mptr->msg_num) && (mptr->msg_flags & MSG_EXISTS))
  692.         {
  693.             sprintf (oldname, "%d.MSG", mptr->msg_num);
  694.             sprintf (newname, "%d.MSG", mptr->msg_out_num);
  695.             err = rename (oldname, newname);
  696.             if (err)
  697.             {
  698.                 unlink (newname);
  699.                 err = rename (oldname, newname);
  700.                 if (err)
  701.                     printf ("Error %d renaming '%s' to '%s', continuing\n", err, oldname, newname);
  702.             }
  703.         }
  704.     }
  705. }
  706.  
  707. void kill_number ()
  708. {
  709.     register int i;
  710.     register MSG_TYP *mptr;
  711.     int j;
  712.     int nkill = 0;
  713.     int start, stop;
  714.  
  715.     start = 1;
  716.     for (mptr = &msgs[1], j = 0, i = 1; (j < kill_n1) && (i <= n_msgs) ; mptr++, i++)
  717.     {
  718.         if (mptr->msg_flags & MSG_EXISTS)
  719.         {
  720.             ++j;
  721.             start = i + 1;
  722.         }
  723.     }
  724.  
  725.     j = 0;
  726.     stop = n_msgs;
  727.     for (mptr = &msgs[n_msgs], i = n_msgs; (j < kill_n2) && (i >= start); mptr--, i--)
  728.     {
  729.         if (mptr->msg_flags & MSG_EXISTS)
  730.         {
  731.             ++j;
  732.             stop = i - 1;
  733.         }
  734.     }
  735.  
  736.     for (mptr = &msgs[start], i = start; i <= stop; mptr++, i++)
  737.     {
  738.         mptr->msg_flags = MSG_DELETED;
  739.         nkill++;
  740.     }
  741.     if (!quiet && nkill)
  742.         printf("Killing %d message%s after skipping %s%d message%s, keeping %d message%s ...\n",
  743.         nkill,
  744.         (nkill == 1) ? ("") : ("s"),
  745.         (kill_n1 > 1) ? ("first ") : (""),
  746.         kill_n1,
  747.         (kill_n1 == 1) ? ("") : ("s"),
  748.         kill_n2,
  749.         (kill_n2 > 1) ? ("s") : (""));
  750. }
  751.  
  752. void kill_attr (unsigned int attr)
  753. {
  754.     register int i;
  755.     register MSG_TYP *mptr;
  756.     int nkill = 0;
  757.  
  758.     for (mptr = &msgs[1], i = 1; i <= n_msgs; mptr++, i++)
  759.     {
  760.         if (mptr->msg_flags & MSG_EXISTS)
  761.         {
  762.             if (mptr->msg_attr & attr)
  763.             {
  764.                 mptr->msg_flags = MSG_DELETED;
  765.                 nkill++;
  766.             }
  767.         }
  768.     }
  769.     if (!quiet && nkill)
  770.         printf("Killing %d %s message%s ...\n",
  771.         nkill,
  772.         (attr == MSGREAD) ? ("RECEIVED") : ("SENT"),
  773.         (nkill == 1) ? ("") : ("s"));
  774. }
  775.  
  776. void kill_by_date ()
  777. {
  778.     register int i;
  779.     register MSG_TYP *mptr;
  780.     int nkill = 0;
  781.     long today;
  782.     MSG m;
  783.  
  784.     if (kill_date <= 0)
  785.         return;
  786.  
  787.     get_date ("%d %n %y  ", m.date);
  788.     m.date[19] = 0;
  789.     today = days_from_1980 (&m);
  790.  
  791.     for (mptr = &msgs[1], i = 1; i <= n_msgs; mptr++, i++)
  792.     {
  793.         if (mptr->msg_flags & MSG_EXISTS)
  794.         {
  795.             if ((today > mptr->msg_time)
  796.               && (today - mptr->msg_time > kill_date))
  797.                 mptr->msg_flags = MSG_DELETED;
  798.         }
  799.     }
  800.     if (!quiet && nkill)
  801.     {
  802.         printf("Killing %d message%s over %d day%s old ...\n",
  803.            nkill, (nkill == 1) ? ("") : ("s"),
  804.            kill_date, (kill_date == 1) ? ("") : ("s") );
  805.     }
  806. }
  807.  
  808. void fancy_str (char *value)
  809. {
  810.     register char *sptr;
  811.     int lower = 0;
  812.  
  813.     sptr = value;
  814.  
  815.     if (sptr) /* don't touch any NULL pointers */
  816.     {
  817.         while (*sptr)
  818.         {
  819.             if (lower)
  820.             {
  821.                 *sptr = (char) tolower (*sptr);
  822.             }
  823.             else
  824.             {
  825.                 *sptr = (char) toupper (*sptr);
  826.             }
  827.  
  828.             lower = isalnum(*sptr++);
  829.         }
  830.     }
  831. }
  832.  
  833. int get_system (char *where,SYS_PTR ret_system)
  834. {
  835.     char sys_file[64];
  836.     int sys_input;
  837.     int num;
  838.     int ret;
  839.     char *p;
  840.  
  841.     ret = ALL_OK;
  842.     sys_file[0] = '\0';
  843.     num = atoi (where);
  844.     if (!isdigit (where[0]))
  845.     {
  846.         strupr (where);
  847.         strcpy (ret_system->msgpath, where);
  848.     }
  849.     else if (num == 0)
  850.         {
  851.             sprintf (sys_file, "%s%s", SYSNAME, DEF_EXT);
  852.         }
  853.         else
  854.         {
  855.             sprintf (sys_file, "%s%d%s", SYSNAME, num, DEF_EXT);
  856.         }
  857.  
  858.     if (sys_file[0] != '\0')
  859.     {
  860.         if ((sys_input = fast_open (sys_file, O_RDONLY|O_BINARY)) == -1)
  861.         {
  862.             return (NO_SYSTEM);
  863.         }
  864.         else
  865.         {
  866.             fast_read (sys_input, (char *) ret_system, sizeof (SYS));
  867.             strupr (ret_system->msgpath);
  868.             fast_close (sys_input);
  869.             areanum = num;
  870.         }
  871.     }
  872.  
  873.     p = &(ret_system->msgpath[strlen (ret_system->msgpath) - 1]);
  874.     if ((*p == '\\') || (*p == '/'))
  875.     {
  876.         if ((p > ret_system->msgpath) && (*(p-1) != ':'))
  877.             *p = '\0';
  878.     }
  879.     fancy_str (ret_system->msgpath);
  880.     num = go_directory (ret_system->msgpath, dir_drive2);
  881.     if (num == 0)
  882.         return (ret);
  883.     return (NO_GO);
  884. }
  885.  
  886. int get_opus (char *where,_sys *ret_system)
  887. {
  888.     char sys_file[64];
  889.     int sys_input;
  890.     int num;
  891.     int ret;
  892.     char *p;
  893.  
  894.     ret = ALL_OK;
  895.     sys_file[0] = '\0';
  896.     num = atoi (where);
  897.     if (!isdigit (where[0]))
  898.     {
  899.         strupr (where);
  900.         strcpy (ret_system->msgpath, where);
  901.     }
  902.     else
  903.         sprintf (sys_file, "SYSTEM%02X.DAT", num);
  904.  
  905.     if (sys_file[0] != '\0')
  906.     {
  907.         if ((sys_input = fast_open (sys_file, O_RDONLY|O_BINARY)) == -1)
  908.         {
  909.             printf ("\nError %d openning '%s', aborting.\n", sys_input, sys_file);
  910.             return (NO_SYSTEM);
  911.         }
  912.         else
  913.         {
  914.             if ((fast_read (sys_input, (char *) ret_system, sizeof (_sys))) == -1)
  915.             {
  916.                 printf ("\nError -1 reading '%s', aborting.\n", sys_file);
  917.                 fast_close (sys_input);
  918.                 return (NO_SYSTEM);
  919.             }
  920.             strupr (ret_system->msgpath);
  921.             fast_close (sys_input);
  922.             areanum = num;
  923.         }
  924.     }
  925.  
  926.     p = &(ret_system->msgpath[strlen (ret_system->msgpath) - 1]);
  927.     if ((*p == '\\') || (*p == '/'))
  928.     {
  929.         if ((p > ret_system->msgpath) && (*(p-1) != ':'))
  930.             *p = '\0';
  931.     }
  932.     fancy_str (ret_system->msgpath);
  933.     num = go_directory (ret_system->msgpath, dir_drive2);
  934.     if (num == 0)
  935.         return (ret);
  936.     return (NO_GO);
  937. }
  938.  
  939. void fix_lastread ()
  940. {
  941.     register int j;
  942.     register MSG_TYP *mptr;
  943.     int i, k, lr, new, upd;
  944.     char buf[20], junk[64];
  945.     int lr_array[MAXLASTREADS];
  946.     int lrbytes, lrcount;
  947.  
  948.     /* Set up the filename for LASTREA? */
  949.     sprintf(junk, "LASTREA?");
  950.     (void) filedir (junk, 0, buf, 0);
  951.  
  952.     while (buf[0] != '\0')
  953. {
  954.         /* Can we open it? */
  955.         if ((lr = fast_open (buf, O_RDWR|O_BINARY)) != -1)
  956.     {
  957.             /* read in up to MAXLASTREADS elements */
  958.             if ((lrbytes = fast_read (lr, (char *) lr_array, sizeof(int)*MAXLASTREADS)) > 0)
  959.         {
  960.                 /* Rewind the file */
  961.                 (void) fast_lseek (lr, 0L, SEEK_SET);
  962.                 lrcount = lrbytes / sizeof(int);
  963.                 if (!quiet)
  964.             {
  965.                     printf("Checking ");
  966.                     if (lrcount > 1)
  967.                 {
  968.                         printf("%d ", lrcount);
  969.                 }
  970.                     printf("Sysop LASTREAD pointer%s in %s ...\n",
  971.                         (lrcount > 1) ? ("s") : (""), buf);
  972.             }
  973.  
  974.                 /* Check and update lastreads */
  975.                 for (new = -1, upd = i = 0; i < lrcount; i++)
  976.             {
  977.                     /* validity check this entry */
  978.                     if ((j = lr_array[i]) < 2)
  979.                     /* if not zero, zip it and schedule rewrite */
  980.                 {
  981.                         if (j)
  982.                     {
  983.                             upd++;
  984.                             new = 0;
  985.                     }
  986.                 }
  987.                     else
  988.                     /* run back up the entries with it */
  989.                 {
  990.                         for (mptr = &msgs[k = min(n_msgs, j)]; k > 1; k--, mptr--)
  991.                     {
  992.                             /* does this one persist? */
  993.                             if (!(mptr->msg_flags & MSG_EXISTS))
  994.                         {
  995.                                 continue;
  996.                         }
  997.                             /* will it require a rewrite? */
  998.                             if ((mptr->msg_out_num == j) && (k == j))
  999.                         {
  1000.                                 new = -2;
  1001.                                 break;
  1002.                         }
  1003.                             else
  1004.                         {
  1005.                                 new = mptr->msg_out_num;
  1006.                                 upd++;
  1007.                                 break;
  1008.                         }
  1009.                     }
  1010.                         if ((new > -2) && ((new < 2) || (k < 2)))
  1011.                     {
  1012.                             new = 0;
  1013.                             upd++;
  1014.                     }
  1015.                 }
  1016.  
  1017.                     if (new > -1)
  1018.                 {
  1019.                         if (!quiet)
  1020.                     {
  1021.                             printf("Changed %s lastread #%d from %d to %d ...\n",
  1022.                                 buf, i+1, j, new);
  1023.                     }
  1024.                         lr_array[i] = new;
  1025.                 }
  1026.                     new = -1;
  1027.             }
  1028.  
  1029.                 /* Write out lastreads */
  1030.                 if (upd)
  1031.             {
  1032.                     (void) fast_write (lr, (char *) lr_array, lrbytes);
  1033.             }
  1034.                 /* Now close up */
  1035.                 (void) fast_close (lr);
  1036.         }
  1037.             else
  1038.         {
  1039.                 printf ("It seems that the LASTREAD file '%s' is empty!\n", buf);
  1040.                 (void) fast_close (lr);
  1041.         }
  1042.     }
  1043.         else
  1044.     {
  1045.             printf ("Unable to open the LASTREAD file '%s'!\n", buf);
  1046.     }
  1047.         (void) filedir (junk, 1, buf, 0);
  1048. }
  1049. }
  1050.  
  1051. int renum_users (int area)
  1052. {
  1053.     char username[13];
  1054.     int user_bbs;
  1055.     int i, j, k, l;
  1056.     int read_size;
  1057.  
  1058.     sprintf (username, "%s%s", USERNAME, DEF_EXT);
  1059.     if ((user_bbs = fast_open (username, O_RDWR|O_BINARY)) == -1)
  1060.     {
  1061.         printf ("Cannot find Opus 1.0x user list\n");
  1062.         return (ALL_OK);
  1063.     }
  1064.  
  1065.     while ((read_size = fast_read (user_bbs, (char *) users, MAX_USERS * sizeof (USR))) > 0)
  1066.     {
  1067.         (void) fast_lseek (user_bbs, (long) (-read_size), SEEK_CUR);
  1068.         l = read_size / sizeof (USR);
  1069.         for (k = 0; k < l; k++)
  1070.         {
  1071.             for (i = 0; i < 10; i++)
  1072.             {
  1073.                 if (users[k].msgs_read[i].area == area)
  1074.                     break;
  1075.             }
  1076.  
  1077.             if (i != 10)
  1078.             {
  1079.                 for (j = users[k].msgs_read[i].last_read; j > 0; j--)
  1080.                 {
  1081.                     if (msgs[j].msg_flags & MSG_EXISTS)
  1082.                         break;
  1083.                 }
  1084.                 if (j == 0)
  1085.                     users[k].msgs_read[i].last_read = 0;
  1086.                 else
  1087.                     users[k].msgs_read[i].last_read = msgs[j].msg_out_num;
  1088.             }
  1089.         }
  1090.             (void) fast_write (user_bbs, (char *) users, read_size);
  1091.     }
  1092.     (void) fast_close (user_bbs);
  1093.     return (ALL_OK);
  1094. }
  1095.  
  1096. int renum_opus (int area)
  1097. {
  1098.     int user_bbs;
  1099.     int i;
  1100.     int read_size;
  1101.  
  1102.     if ((user_bbs = fast_open ("USER.DAT", O_RDONLY|O_BINARY)) == -1)
  1103.     {
  1104.         printf ("Cannot find Opus 1.1+ user list\n");
  1105.         return (ALL_OK);
  1106.     }
  1107.     (void) fast_close (user_bbs);
  1108.  
  1109.     user_bbs = fast_open ("USER.DAT", O_RDWR|O_BINARY);
  1110.  
  1111.     while ((read_size = fast_read (user_bbs, (char *) &opus_user,  sizeof (_usr))) > 0)
  1112.     {
  1113.         if ((i = opus_user.lastmsg[area]) <= 0)
  1114.              continue;
  1115.         (void) fast_lseek (user_bbs, (long) (-read_size), SEEK_CUR);
  1116.         opus_user.lastmsg[area] = 0;
  1117.         if ((i <= n_msgs) && (i > 0))
  1118.         {
  1119.             if (!(msgs[i].msg_flags & MSG_EXISTS))
  1120.             {
  1121.                 while(--i)
  1122.                 {
  1123.                     if (msgs[i].msg_flags & MSG_EXISTS)
  1124.                     {
  1125.                         opus_user.lastmsg[area] = msgs[i].msg_out_num;
  1126.                         break;
  1127.                     }
  1128.                 }
  1129.             }
  1130.             else
  1131.             {
  1132.                 opus_user.lastmsg[area] = msgs[i].msg_out_num;
  1133.             }
  1134.         }
  1135.         (void) fast_write (user_bbs, (char *) &opus_user, read_size);
  1136.     }
  1137.     (void) fast_close (user_bbs);
  1138.     return (ALL_OK);
  1139. }
  1140.  
  1141.  
  1142. void renum_opus120_lastread ()
  1143. {
  1144. register int j;
  1145. register MSG_TYP *mptr;
  1146. int i, k, lrb, new, upd;
  1147. LMR lr_array[MAXLASTREADS];
  1148. int lrbytes, lrcount;
  1149.  
  1150. /* Can we open it? */
  1151. if ((lrb = fast_open("LREAD.DAT", O_RDWR|O_BINARY)) != -1)
  1152.    {
  1153.    /* read in up to MAXLASTREADS elements */
  1154.    while ((lrbytes = fast_read (lrb, (char *)lr_array, sizeof(lr_array))) > 0)
  1155.       {
  1156.       lrcount = lrbytes / sizeof(struct _lmr);
  1157.       if (!quiet)
  1158.          {
  1159.          printf("Checking Opus 1.2x LREAD.DAT entries ...\n");
  1160.          }
  1161.  
  1162.       /* Check and update lastreads */
  1163.       for (new = -1, upd = i = 0; i < lrcount; i++)
  1164.          {
  1165.  
  1166.          /*
  1167.          ** Do the high_read pointer
  1168.          */
  1169.  
  1170.          /* validity check this entry */
  1171.          if ((j = lr_array[i].high_msg) < 2)
  1172.             /* if not zero, zip it and schedule rewrite */
  1173.             {
  1174.             if (j)
  1175.                {
  1176.                upd++;
  1177.                new = 0;
  1178.                }
  1179.             }
  1180.          else
  1181.             /* run back up the entries with it */
  1182.             {
  1183.             for (mptr = &msgs[k = min(n_msgs, j)]; k > 1; k--, mptr--)
  1184.                {
  1185.                /* does this one persist? */
  1186.                if (!(mptr->msg_flags & MSG_EXISTS))
  1187.                   {
  1188.                   continue;
  1189.                   }
  1190.  
  1191.                /* will it require a rewrite? */
  1192.                if ((mptr->msg_out_num == j) && (k == j))
  1193.                   {
  1194.                   new = -2;
  1195.                   break;
  1196.                   }
  1197.                else
  1198.                   {
  1199.                   new = mptr->msg_out_num;
  1200.                   upd++;
  1201.                   break;
  1202.                   }
  1203.                }
  1204.             if ((new > -2) && ((new < 2) || (k < 2)))
  1205.                {
  1206.                new = 0;
  1207.                upd++;
  1208.                }
  1209.             }
  1210.  
  1211.          if (new > -1)
  1212.             lr_array[i].high_msg = new;
  1213.          new = -1;
  1214.  
  1215.          /*
  1216.          ** Do the last_read pointer
  1217.          */
  1218.  
  1219.          /* validity check this entry */
  1220.          if ((j = lr_array[i].last_msg) < 2)
  1221.             /* if not zero, zip it and schedule rewrite */
  1222.             {
  1223.             if (j)
  1224.                {
  1225.                upd++;
  1226.                new = 0;
  1227.                }
  1228.             }
  1229.          else
  1230.             /* run back up the entries with it */
  1231.             {
  1232.             for (mptr = &msgs[k = min(n_msgs, j)]; k > 1; k--, mptr--)
  1233.                {
  1234.                /* does this one persist? */
  1235.                if (!(mptr->msg_flags & MSG_EXISTS))
  1236.                   {
  1237.                   continue;
  1238.                   }
  1239.  
  1240.                /* will it require a rewrite? */
  1241.                if ((mptr->msg_out_num == j) && (k == j))
  1242.                   {
  1243.                   new = -2;
  1244.                   break;
  1245.                   }
  1246.                else
  1247.                   {
  1248.                   new = mptr->msg_out_num;
  1249.                   upd++;
  1250.                   break;
  1251.                   }
  1252.                }
  1253.             if ((new > -2) && ((new < 2) || (k < 2)))
  1254.                {
  1255.                new = 0;
  1256.                upd++;
  1257.                }
  1258.             }
  1259.  
  1260.          if (new > -1)
  1261.             lr_array[i].last_msg = new;
  1262.          new = -1;
  1263.          }
  1264.  
  1265.       /* Write out lastreads */
  1266.       if (upd)
  1267.          {
  1268.          /* Rewind the file */
  1269.          (void) fast_lseek (lrb, (long) (-lrbytes), SEEK_CUR);
  1270.          (void) fast_write (lrb, (char *) lr_array, lrbytes);
  1271.          }
  1272.       }
  1273.    (void) fast_close (lrb);
  1274.    }
  1275. else
  1276.    {
  1277.    printf ("Unable to open the LREAD.DAT file!\n");
  1278.    }
  1279. }
  1280.  
  1281.  
  1282. void renum_max_lastread ()
  1283. {
  1284.     register int j;
  1285.     register MSG_TYP *mptr;
  1286.     int i, k, lrb, new, upd;
  1287.     int lr_array[MAXLASTREADS];
  1288.     int lrbytes, lrcount;
  1289.  
  1290.     /* Can we open it? */
  1291.     if ((lrb = fast_open("LASTREAD.BBS", O_RDWR|O_BINARY)) != -1)
  1292.     {
  1293.         if (!quiet)
  1294.         {
  1295.             printf("Checking Maximus LASTREAD.BBS entries ...\n");
  1296.         }
  1297.  
  1298.         /* read in up to MAXLASTREADS elements */
  1299.         while ((lrbytes = fast_read (lrb, (char *) lr_array, sizeof(int)*MAXLASTREADS)) > 0)
  1300.         {
  1301.             lrcount = lrbytes / sizeof(int);
  1302.  
  1303.             /* Check and update lastreads */
  1304.             for (new = -1, upd = i = 0; i < lrcount; i++)
  1305.             {
  1306.                 /* validity check this entry */
  1307.                 if ((j = lr_array[i]) < 2)
  1308.                 /* if not zero, zip it and schedule rewrite */
  1309.                 {
  1310.                     if (j)
  1311.                     {
  1312.                         upd++;
  1313.                         new = 0;
  1314.                     }
  1315.                 }
  1316.                 else
  1317.                 /* run back up the entries with it */
  1318.                 {
  1319.                     for (mptr = &msgs[k = min(n_msgs, j)]; k > 1; k--, mptr--)
  1320.                     {
  1321.                         /* does this one persist? */
  1322.                         if (!(mptr->msg_flags & MSG_EXISTS))
  1323.                         {
  1324.                             continue;
  1325.                         }
  1326.                         /* will it require a rewrite? */
  1327.                         if ((mptr->msg_out_num == j) && (k == j))
  1328.                         {
  1329.                             new = -2;
  1330.                             break;
  1331.                         }
  1332.                         else
  1333.                         {
  1334.                             new = mptr->msg_out_num;
  1335.                             upd++;
  1336.                             break;
  1337.                         }
  1338.                     }
  1339.                     if ((new > -2) && ((new < 2) || (k < 2)))
  1340.                     {
  1341.                         new = 0;
  1342.                         upd++;
  1343.                     }
  1344.                 }
  1345.  
  1346.                 if (new > -1)
  1347.                     lr_array[i] = new;
  1348.                 new = -1;
  1349.             }
  1350.  
  1351.             /* Write out lastreads */
  1352.             if (upd)
  1353.             {
  1354.                 /* Rewind the file */
  1355.                 (void) fast_lseek (lrb, (long) (-lrbytes), SEEK_CUR);
  1356.                 (void) fast_write (lrb, (char *) lr_array, lrbytes);
  1357.             }
  1358.         }
  1359.         (void) fast_close (lrb);
  1360.     }
  1361.     else
  1362.     {
  1363.         printf ("Unable to open the LASTREAD.BBS file!\n");
  1364.     }
  1365. }
  1366.  
  1367. void relink ()
  1368. {
  1369.     int i, f;
  1370.     MSG_TYP *mptr;
  1371.     MSG  *m1;
  1372.  
  1373.     m1 = &msg_tmp;
  1374.     for (mptr = &msgs[1],i = 1; i <= n_msgs; mptr++, i++)
  1375.     {
  1376.         if (mptr->msg_flags & MSG_LINK_CHANGED)
  1377.         {
  1378.             /* Create the name of this message */
  1379.             sprintf (tmpjunk2, "%d.msg", mptr->msg_out_num);
  1380.  
  1381.             f = fast_open (tmpjunk2, O_RDWR|O_BINARY);
  1382.             (void) fast_read (f, (char *) &msg_tmp, sizeof (MSG));
  1383.             (void) fast_lseek (f, 0L, SEEK_SET);
  1384.             m1->up = mptr->msg_up;
  1385.             m1->attr = mptr->msg_attr;
  1386.             m1->reply = mptr->msg_down;
  1387.             (void) fast_write (f, (char *) &msg_tmp, sizeof(MSG));
  1388.             (void) fast_close (f);
  1389.         }
  1390.     }
  1391. }
  1392.  
  1393. int go_directory (char *dir,char *save)
  1394. {
  1395. #ifndef OS_2
  1396.     unsigned num_drives;
  1397. #endif
  1398.  
  1399.     if (dir[1] == ':')
  1400.     {
  1401. #ifdef OS_2
  1402.         (void)DosSelectDisk(toupper(dir[0]) - 'A' + 1);
  1403. #else
  1404.         _dos_setdrive((unsigned)(toupper(dir[0]) - 'A' + 1), &num_drives);
  1405. #endif
  1406.         if (save != NULL)
  1407.         {
  1408.             getcwd (save, MAX_PATH);
  1409.         }
  1410.     }
  1411.  
  1412.     return (chdir (dir));
  1413. }
  1414.  
  1415.  
  1416. void msgnum_usage ()
  1417. {
  1418.    printf ("\n\n");
  1419. #ifndef OS_2
  1420.    printf ("Usage: MSGNUM [-D days] [-N save1 save2]\n        [-Q] [-K] [-S] [-M] [-O|O120] [-R] dir\n");
  1421. #else
  1422.    printf ("Usage: MSGNUMP [-D days] [-N save1 save2]\n        [-Q] [-K] [-S] [-M] [-O|O120] [-R] dir\n");
  1423. #endif
  1424.    printf ("Where: -Q = Quiet, -K = Kill received msgs, -S = Kill sent msgs,\n");
  1425.    printf ("       -M = Max 1.0x, -O = Opus 1.1x, -O120 = Opus 1.2x file structures,\n");
  1426.    printf ("       dir is the SYSTEMxx.BBS/DAT number or the message area path.\n\n");
  1427.    exit (1);
  1428. }
  1429.