home *** CD-ROM | disk | FTP | other *** search
/ Beijing Paradise BBS Backup / PARADISE.ISO / software / BBSDOORW / CNFIG218.ZIP / CONFIG.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-28  |  29.6 KB  |  926 lines

  1. PROGRAM Config;
  2.   {  CONFIG.C written in C by Mike Klein, CompuServe ID 73237,2531 }
  3.   {  version 1.6 published in LAN Technology magazine, 9/89 issue  }
  4.   {  The author's address then was: 10951 Sorrento Valley Rd. #1F  }
  5.   {                                 San Diego, CA 92121            }
  6.   {  The published source code did not claim to be copyrighted,    }
  7.   {  and could be downloaded from a bulletin board at 603/882-1599 }
  8.   {  which no longer appears to be in operation.                   }
  9.   {  To whatever extent I have the right to do so, I likewise      }
  10.   {  leave this Pascal version free of copyright, asking only that }
  11.   {  improved versions be likewise posted for the benefit of all.  }
  12.   {  Compiled with Turbo Pascal 6. Requires at least version 4.    }
  13.   {                                                                }
  14.   {  8/10/91 JFS v2.10 Altered to replace CONFIG.C                 }
  15.   { 10/11/91 JFS v2.11 Replace OS_VER with Novell-style OS_VERSION }
  16.   { 11/07/91 JFS v2.12 Limit PSTAT to 8 characters                 }
  17.   {              This allows it to be used as a DOS filename       }
  18.   { 10/18/92 JFS v2.16 Allow saving results to file on disk.       }
  19.   {              triggered by a new command line parameter /F path }
  20.   {              Also allow versions of DOS beyond 9.99, and only  }
  21.   {              truncate PSTAT as an EVAR, not to screen or disk. }
  22.   { 10/22/92 JFS v2.17 Shorten data items when stored to disk,     }
  23.   {         & MM especially if name is LAB or GUEST. Also replace  }
  24.   {              Novell routines that used a no-longer-free        }
  25.   {              library with netInfo unit by Mike McCall that is  }
  26.   {              freely-copyable.                                  }
  27.   { 10/28/92 JFS v2.18 Add station & socket numbers to netinfo, &  }
  28.   {         & MM optimize source code to shorten & cut units.      }
  29.   {              Don't use yet. Alters EVARs improperly.           }
  30.   {                                                                }
  31.   { The first command line parameter is /E                         }
  32.   { If present, several DOS environment variables are set          }
  33.   {             and the program generates no output to screen.     }
  34.   { An alternative command line parameter is /F                    }
  35.   { It works exactly like /E, but also saves its variables         }
  36.   { in a DOS text file in the path specified after /F, & includes  }
  37.   { the year & month in the file name in the form YYM, where       }
  38.   { YY is the 2 low-order digits of the year, & M is the month,    }
  39.   { letting A=October, B=November & C=December.                    }
  40.   { e.g. the command CONFIG /F Y:\SHARED\, if executed 10/17/92,   }
  41.   { creates or appends data to disk file Y:\SHARED\CFG92A.TXT      }
  42.   { In addition this option adds the system date & time & the      }
  43.   { user's login and full name to the data saved to disk.          }
  44.   { When no command line parameters are given, results appear      }
  45.   { only on screen, & are not written to either disk or EVARs.     }
  46.  
  47. {$B-,D-,F-,I-,L+,N-,R-,S-,V-}
  48. {$M 4096,0,0}
  49.  
  50. USES Adapter, NetInfo;
  51.  
  52. CONST
  53.   NetError : byte = 0;          { netInfo return value - if zero, all ok }
  54.  
  55. TYPE
  56.   Str1Type      = string [1];
  57.   Str2Type      = string [2];
  58.   Str3Type      = string [3];
  59.   Str4Type      = string [4];
  60.   Str5Type      = string [5];
  61.   Str6Type      = string [6];
  62.  
  63. VAR
  64.   F             : text;         { Optionally stores results to disk       }
  65.   fil_path,                     { Path along which to store file          }
  66.   fil_nam       : string;       { Full path & file name to use            }
  67.  
  68.  
  69.   {Variables used to find and change DOS environment}
  70.   UseCurrentEnv,                { True if current environment is accessed }
  71.   SecondCommand : boolean;      { True if secondary COMMAND.COM is loaded }
  72.   AL,                           { Register AL                             }
  73.   EnvTyp        : byte;         { Environment type                        }
  74.   EnvAddr,                      { Environment address                     }
  75.   AX,                           { Register AX                             }
  76.   RootEnvAddr   : word;         { Root environment address                }
  77.   EnvSize,                      { Environment size                        }
  78.   RootEnvSize,                  { Root environment size                   }
  79.   i             : integer;      { Temporary loop index                    }
  80.   EnvStr,
  81.   EnvVar        : string;
  82.  
  83.   {Variables used to find machine configuration}
  84.   exp,                          { Expanded memory? (T/F)         }
  85.   ext,                          { Extended memory? (T/F)         }
  86.   fpu,                          { FPU present? (T/F)             }
  87.   vtyp,                         { Video type code from Adapter   }
  88.   mouse         : Str1Type;     { Mouse present? (T/F)           }
  89.   ddr,                          { Current data drive for results }
  90.   dd,                           { Current day of month           }
  91.   class         : Str2Type;     { Like model, but only (PC/AT)   }
  92.   yym           : Str3Type;     { Current year & month           }
  93.   conv,                         { Conventional memory size       }
  94.   cpu,                          { CPU type (808x, 80286, 80386)  }
  95.   video         : Str4Type;     { Video adapter (MDA, HERC, CGA, }
  96.                                 {                EGA, PGA, VGA)  }
  97.   hhmm,                         { Current hour & minute          }
  98.   os_version    : Str5Type;     { DOS version number             }
  99.   mode,                         { Video mode (COLOR/MONO)        }
  100.   free          : Str6Type;     { Free conventional memory       }
  101.   netaddr,                      { LAN network address            }
  102.   pstat2,
  103.   pstat,                        { LAN physical node number       }
  104.   stn,                          { Connection # of station as str }
  105.   sock,                         { Socket as str                  }
  106.   name,                         { User's login name              }
  107.   fullname      : string;       { User's full name               }
  108.  
  109.   env_set,                      { Flags whether to set EVARs     }
  110.   fil_set       : boolean;      { Flags whether to write to file }
  111.   Major,                        { Major DOS version number       }
  112.   Minor,                        { Minor DOS version number       }
  113.   station,                      { Connection # of station        }
  114.   year,
  115.   month,
  116.   day,                          { System date                    }
  117.   hr,
  118.   min,                          { System time                    }
  119.   byt           : byte;
  120.   g_driver,                     { Graphic driver type found      }
  121.   g_mode        : integer;      { Current mode of graphic driver }
  122.   socket,                       { Socket number on network       }
  123.   memval,
  124.   CPUval,
  125.   far_ptr       : word;
  126.   have          : longint;
  127.  
  128. PROCEDURE GetEnvTyp(VAR EnvTyp : byte);
  129. {Which type of DOS and environment type is on this PC?}
  130.  
  131. begin {GetEnvTyp}
  132.   { Assign environment type according to DOS version }
  133.   inline ($B4/$30           (* mov ah, 30                     *)
  134.          /$CD/$21           (* int 21  Get DOS version number *)
  135.          /$A2/Major         (* mov Major, al                  *)
  136.          /$88/$26/Minor);   (* mov Minor, ah                  *)
  137.  
  138.   EnvTyp := 3;
  139.   case Major of
  140.     2 : EnvTyp := 1;
  141.     3 : case Minor of
  142.           0, 10 : EnvTyp := 1;
  143.           20    : EnvTyp := 2
  144.         end { case Minor }
  145.   end { case Major }
  146. end; { GetEnvTyp }
  147.  
  148. PROCEDURE SearchMemory(VAR RootEnvaddr : word; VAR RootEnvSize : integer);
  149. { Search memory for root environment }
  150.  
  151. VAR
  152.   ComMCB  : word;     { COMMAND.COM MCB }
  153.   EnvMCB  : word;     { environment MCB }
  154.   MCBsize : word;     { memory block size in paragraphs }
  155.   Found   : boolean;  { root COMMAND.COM found }
  156.  
  157.   PROCEDURE CheckMCBchain(ComMCB : word; VAR EnvMCB : word;
  158.                           VAR Found : boolean);
  159.   { Check for Memory Control Block chain }
  160.  
  161.   begin { CheckMCBchain }
  162.     Found   := false;
  163.     MCBsize := MemW[ComMCB : 3];
  164.     EnvMCB  := Succ(ComMCB + MCBsize);
  165.     if (Mem[EnvMCB : 0] = $4D) then
  166.       Found := true;
  167.   end; { CheckMCBchain }
  168.  
  169. begin { SearchMemory }
  170.   { Begin search for COMMAND.COM in low memory }
  171.   ComMCB := $500;
  172.   Found  := false;
  173.   while not Found do
  174.     begin {while}
  175.       { MCB begins with $4D }
  176.       if Mem[ComMCB:0] = $4D then
  177.         begin { if }
  178.           { check for matching PSP address }
  179.           if MemW[ComMCB : 1] = Succ(ComMCB) then
  180.             CheckMCBchain(ComMCB,EnvMCB,Found);
  181.         end; { if }
  182.  
  183.       { If not Found then continue search at next paragraph boundary }
  184.       Inc(ComMCB);
  185.     end; { while }
  186.  
  187.   { Check for environment type }
  188.   if MemW[ComMCB : $2C] = 0 then
  189.     { Root environment of DOS 2.0 - 3.2 }
  190.     begin { if }
  191.       RootEnvAddr := Succ(EnvMCB);
  192.       MCBsize := MemW[EnvMCB : 3];
  193.       RootEnvSize := MCBsize * $10
  194.     end { if }
  195.   else
  196.     { Root environment of DOS 3.3 and later }
  197.     begin { else }
  198.       RootEnvAddr := MemW[ComMCB : $2C];
  199.       EnvMCB := Pred(RootEnvaddr);
  200.       MCBsize := MemW[EnvMCB : 3];
  201.       RootEnvSize := MCBsize * $10
  202.     end { else }
  203. end;  { SearchMemory }
  204.  
  205. PROCEDURE GetActivEnv(VAR EnvAddr : word; VAR EnvSize : integer;
  206.                       VAR RootEnvAddr : word; VAR RootEnvSize : integer;
  207.                       EnvTyp : byte);
  208. { Get active environment }
  209.  
  210. VAR
  211.   PSPaddr,         { COMMAND.COM PSP address }
  212.   ComMCB,          { COMMAND.COM MCB }
  213.   EnvMCB,          { environment MCB }
  214.   MCBsize : word;  { memory block size in paragraphs }
  215.  
  216. begin { GetActivEnv }
  217.   RootEnvAddr := 0;
  218.  
  219.   { COMMAND.COM PSP address at offset $16 in program PSP }
  220.   PSPaddr := MemW[PrefixSeg : $16];
  221.  
  222.   { check for child process }
  223.   while (PSPaddr <> MemW[PSPaddr : $16]) do
  224.     PSPaddr := MemW[PSPaddr : $16];
  225.  
  226.   { COMMAND.COM MCB address }
  227.   ComMCB := Pred(PSPaddr);
  228.  
  229.   { Size of COMMAND.COM }
  230.   MCBsize := MemW[ComMCB : 3];
  231.  
  232.   { Environment MCB address }
  233.   EnvMCB := PSPaddr + MCBsize;
  234.  
  235.   { Assign environment address }
  236.   EnvAddr := Succ(EnvMCB);
  237.  
  238.   { Size of environment }
  239.   MCBsize := MemW[EnvMCB : 3];
  240.   EnvSize := MCBsize * $10;
  241.  
  242.   { Check for secondary COMMAND.COM }
  243.   case EnvTyp of
  244.     { $2C points to DOS environment in DOS 2.0 - 3.1 }
  245.     1 : if (MemW[PSPaddr : $2C] <> 0) then
  246.           begin { case 1 }
  247.             SearchMemory(RootEnvAddr,RootEnvSize);
  248.             { Re-assign environment address }
  249.             EnvAddr := MemW[PSPaddr : $2C];
  250.             EnvMCB := Pred(Envaddr);
  251.             MCBsize := MemW[EnvMCB : 3];
  252.             EnvSize := MCBsize * $10
  253.           end; { case 1 }
  254.         { $2C points to program environment in DOS 3.2 }
  255.     2 : if (MemW[PSPaddr : $2C] <> 0) then
  256.           SearchMemory(RootEnvAddr,RootEnvSize);
  257.         { $2C points to DOS environment in DOS 3.3 and later }
  258.     3 : if (MemW[PSPaddr : $2C] = EnvAddr) then
  259.           SearchMemory(RootEnvAddr,RootEnvSize)
  260.         else
  261.         { Re-assign environment address }
  262.           begin { case 3 else }
  263.             EnvAddr := MemW[PSPaddr : $2C];
  264.             EnvMCB := Pred(Envaddr);
  265.             MCBsize := MemW[EnvMCB : 3];
  266.             EnvSize := MCBsize * $10
  267.           end { case 3 else }
  268.   end { case }
  269. end;  { GetActivEnv }
  270.  
  271. FUNCTION UpStr(St : string) : string;
  272. { Convert a string to upper case }
  273.  
  274. VAR
  275.   i : byte;
  276.  
  277. begin { UpStr }
  278.   for i := 1 to Length(St) do
  279.     St[i] := UpCase(St[i]);
  280.   UpStr := St
  281. end;  { UpStr }
  282.  
  283. FUNCTION TrimLeft(St :string) : string;
  284. { Delete leading zeroes from numeric string }
  285.  
  286. VAR
  287.   i,
  288.   j : Integer;
  289.  
  290. begin { TrimLeft }
  291.   i := 1;
  292.   j := Length(St) + 1;
  293.   while (St[i] = '0') do
  294.     Inc(i);
  295.   TrimLeft := Copy(St, i, j - i);
  296. end; { trimLeft }
  297.  
  298. FUNCTION EnvStrLength (EnvAddr, EnvSize : word) : word;
  299. { Get length of a string in DOS environment }
  300.  
  301. var p : word;
  302.  
  303. begin { EnvStrLength }
  304.   p := 0;
  305.   while memW [EnvAddr : p] <> 0 do
  306.       inc (p);
  307.   if p > EnvSize then
  308.     begin { if }
  309.       Writeln('End of environment not found');
  310.       Halt
  311.     end; { if }
  312.   EnvStrLength := p;
  313. end;  { EnvStrLength }
  314.  
  315. FUNCTION Position(St : string; EnvAddr : word; ArrayLen : integer) : integer;
  316. { Find the position of a string in DOS environment }
  317.  
  318. VAR
  319.   p     : integer;
  320.   i     : integer;
  321.   match : boolean;
  322.  
  323. begin { Position }
  324.   St    := St + '=';
  325.   { Check for first string in environment space }
  326.   match := true;
  327.   for i := 1 to Length(St) do
  328.     if Mem[EnvAddr : i - 1] <> Ord(St[i]) then
  329.       begin  { if }
  330.         match := false;
  331.         i     := Length(St)
  332.       end;   { if }
  333.   if match then
  334.     begin  { if }
  335.       Position := 0;
  336.       exit
  337.     end;   { if }
  338.   p := 0;
  339.   while p < ArrayLen do
  340.     begin  { while }
  341.       while (Mem[EnvAddr : p] <> 0) do
  342.         inc (p);  { Skip to beginning of next environment entry }
  343.       inc (p);
  344.       match := true;
  345.       for i := 1 to Length(St) do
  346.         if Mem[EnvAddr : p + i - 1] <> Ord(St[i]) then
  347.           begin  { if }
  348.             match := false;
  349.             i := Length(St)
  350.           end; { if }
  351.       if match then
  352.         begin  { if }
  353.           Position := p;
  354.           exit
  355.         end; { if }
  356.     end; { while }
  357.   Position := -1
  358. end; { Position }
  359.  
  360. PROCEDURE WriteEnvVar(EnvParam, EnvVar : string);
  361. { Write an environment variable to DOS environment }
  362.  
  363. VAR
  364.   EnvStr   : string;   { Environment string        }
  365.   ArrayLen,            { Environment array length  }
  366.   StLen,               { Environment string length }
  367.   ParamPos,            { Parameter position        }
  368.   i        : integer;
  369.  
  370. begin { WriteEnvVar }
  371.   if EnvParam = '' then
  372.     Exit;
  373.   if not UseCurrentEnv then
  374.     begin { if }
  375.       EnvAddr := RootEnvAddr;
  376.       EnvSize := RootEnvSize;
  377.     end; { if }
  378.  
  379.   { Get the length of the environment string }
  380.   ArrayLen := EnvStrLength (EnvAddr, EnvSize);
  381.  
  382.   { Initialize variables }
  383.   EnvParam := UpStr(EnvParam);
  384.   EnvStr := EnvParam + '=' + EnvVar + #0#0;
  385.   StLen := Length(EnvStr);
  386.  
  387.   { Search for variable in environment }
  388.   ParamPos := Position(EnvParam,EnvAddr,ArrayLen);
  389.  
  390.   if ParamPos = -1 then
  391.     begin { if }
  392.       { Check for empty variable }
  393.       if EnvVar = '' then
  394.         Exit;
  395.  
  396.       { Environment parameter not found }
  397.       { Compare environment with string }
  398.       if (ArrayLen + StLen + 1) > EnvSize then
  399.         Writeln('Environment full')
  400.       else
  401.         { Add new variable string to end of array }
  402.         begin { else }
  403.           if ArrayLen = 0 then
  404.             Move(EnvStr[1], Mem[EnvAddr : 0], StLen)
  405.           else
  406.             Move(EnvStr[1], Mem[EnvAddr : ArrayLen+1], StLen)
  407.           end {else}
  408.     end {if}
  409.     { Environment parameter found }
  410.     { Get length of variable string }
  411.   else
  412.     begin {else}
  413.       { Start at =, skipping variable string }
  414.       i := ParamPos + Length(EnvParam);
  415.       while Mem[EnvAddr : i] <> 0 do
  416.         Inc(i);
  417.  
  418.       { Get beginning of next variable string }
  419.       Inc(i);
  420.  
  421.       { Delete variable from current position in array }
  422.       Move(Mem[EnvAddr: i], Mem[EnvAddr: ParamPos], (ArrayLen + 2) - i);
  423.       ArrayLen := ArrayLen - (i - ParamPos);
  424.  
  425.       { Check for empty variable }
  426.       if EnvVar = '' then
  427.         Exit;
  428.  
  429.       { Compare environment array length with environment size }
  430.       if (ArrayLen + StLen + 1) > EnvSize then
  431.         Writeln('Environment full')
  432.       else
  433.         { Add variable to end of array }
  434.         Move(EnvStr[1], Mem[EnvAddr : ArrayLen+1], StLen)
  435.     end { else }
  436. end; { WriteEnvVar }
  437.  
  438. FUNCTION CPUis : word;
  439. { Identify microprocessor currently in use - NOTE: calls a 486 a 386 }
  440.  
  441. begin { CPUis }
  442.   inline (
  443.   $9C/          {pushf           }
  444.   $31/$C0/      {xor  ax,ax      }
  445.   $50/          {push  ax        }
  446.   $9D/          {popf            }
  447.   $9C/          {pushf           }
  448.   $58/          {pop  ax         }
  449.   $25/$00/$F0/  {and  ax,0f000h  }
  450.   $3D/$00/$F0/  {cmp  ax,0f000h  }
  451.   $74/$16/      {jz    is_808x   }
  452.  
  453.   { If we can't set bits 12-14, CPU is a 286 }
  454.   $B8/$00/$70/  { mov  ax,07000h }
  455.   $50/          { push  ax       }
  456.   $9D/          { popf           }
  457.   $9C/          { pushf          }
  458.   $58/          { pop  ax        }
  459.   $25/$00/$70/  { and  ax,07000h }
  460.   $74/$05/      { jz    is_80286 }
  461.  
  462.   { is_80386 }
  463.   $B8/$86/$03/  { mov  ax,386h   }
  464.   $EB/$08/      { jmp  done      }
  465.   { is_80286 }
  466.   $B8/$86/$02/  { mov  ax,286h   }
  467.   $EB/$03/      { jmp  done      }
  468.   {is_808x}
  469.   $B8/$86/$00/  { mov  ax,86h    }
  470.   { done }
  471.   $9D/          { popf           }
  472.   $89/$46/$FE)  { mov  [bp-2],ax }
  473. end; { CPUis }
  474.  
  475. begin { Config }
  476.   env_set := false;
  477.   fil_set := false;
  478.   if ParamCount > 0 then
  479.     begin { if }
  480.       if ((ParamStr(1) = '/E') or  (ParamStr(1) = '/e')) then
  481.         env_set := true
  482.       else
  483.        if ((ParamStr(1) = '/F') or  (ParamStr(1) = '/f')) then
  484.          begin { if }
  485.            env_set := true;
  486.            fil_set := true;
  487.            { Default path is root of current drive }
  488.            fil_path := '\';
  489.            { Read path specified after /F, if one was specified }
  490.            if ParamCount > 1 then
  491.              fil_path := ParamStr(2);
  492.            { If specified path doesn't end with backslash, add one }
  493.            if (fil_path[Length(fil_path)] <> '\') then
  494.              fil_path := fil_path + '\'
  495.          end { if }
  496.        else
  497.          begin { else }
  498.            Writeln;
  499.            Writeln('ERROR: Bad parameter...');
  500.            Writeln(' Syntax is: CONFIG to display setup');
  501.            Writeln(' or CONFIG /E to fill DOS environment with setup');
  502.            Writeln(' or CONFIG /F [path] to file setup to disk file');
  503.            Halt
  504.          end {else}
  505.     end; { if }
  506.  
  507.   { Initialize environment address }
  508.   UseCurrentEnv := true;
  509.   SecondCommand := true;
  510.   GetEnvTyp(EnvTyp);
  511.   GetActivEnv(EnvAddr,EnvSize,RootEnvAddr,RootEnvSize,EnvTyp);
  512.   if RootEnvAddr = 0 then
  513.     begin { if }
  514.       RootEnvAddr := EnvAddr;
  515.       RootEnvSize := EnvSize;
  516.       SecondCommand := false
  517.     end; { if }
  518.  
  519.   if (env_set = false) then
  520.     begin { if }
  521.       Writeln;
  522.       Writeln;
  523.       Writeln('SYSTEM CONFIGURATION v2.18');
  524.       Writeln('==========================')
  525.     end; { if }
  526.  
  527.   {************************************************}
  528.   {* SYSTEM DATE & TIME - FROM DOS OR FILE SERVER *}
  529.   {************************************************}
  530.  
  531.   pstat    := 'N/A';
  532.   pstat2   := 'N/A';
  533.   netaddr  := 'N/A';
  534.   stn      := 'N/A';
  535.   sock     := 'N/A';
  536.   name     := 'N/A';
  537.   fullname := 'N/A';
  538.  
  539.   {First see which test to use}
  540.   inline ($B4/$DB    { mov ah, DB                 }
  541.          /$CD/$21    { int 21                     }
  542.          /$A2/AL);   { mov turbo_variable_AL, al  }
  543.  
  544.   if (AL = 0) then
  545.     {IPX is NOT loaded, so use DOS}
  546.     begin { if }
  547.       {Get system date from DOS: year=0..99, month=1..12, day=1..31}
  548.       inline ($B4/$2A          { mov ah, 2a        }
  549.              /$CD/$21          { int 21  get date  }
  550.              /$88/$36/month    { mov month, DH     }
  551.              /$88/$16/day      { mov day, DL       }
  552.              /$89/$C8          { mov AX, CX        }
  553.              /$BB/$64/$00      { mov BX, 64        }
  554.              /$31/$D2          { xor DX, DX        }
  555.              /$F7/$F3          { div BX            }
  556.              /$88/$16/year);   { mov year, DL      }
  557.  
  558.       { Get system time from DOS: hr=0..23, min=0..59 }
  559.       inline ($B4/$2C          { mov ah, 2C        }
  560.              /$CD/$21          { int 21  get time  }
  561.              /$88/$2E/hr       { mov hr, CH        }
  562.              /$88/$0E/min);    { mov min, CL       }
  563.     end { if }
  564.   else
  565.     begin { else }
  566.       {Get from file server, along with:}
  567.  
  568.       {********************************}
  569.       {* LAN ADDRESS, USER & FULLNAME *}
  570.       {********************************}
  571.  
  572.       { Call MM LAN code: first line is a byte and a word }
  573.       { line two line is all strings                      }
  574.       { third line & result are all bytes                 }
  575.       NetError := netInformation (station, socket,
  576.                                   pstat, netaddr, name, fullname,
  577.                                   year, month, day, hr, min      );
  578.  
  579.       if NetError = 0 then
  580.         begin { if }
  581.           pstat  := TrimLeft(UpStr(pstat));
  582.           pstat2 := pstat;
  583.           { Limit EVAR result to 8 low-order digits, for DOS filenames }
  584.           if Length(pstat) > 8 then pstat := Copy(pstat, 5, 8);
  585.           netaddr   := TrimLeft(UpStr(netaddr));
  586.           { Convert station & socket to strings }
  587.           Str(socket, sock);
  588.           Str(station, stn)
  589.         end { if }
  590.     end; { else }
  591.  
  592.   { Convert Date to YYM & DD form }
  593.   yym       := '000';
  594.   dd        := '00';
  595.   yym[1]    := Chr((year div 10) + 48);
  596.   yym[2]    := Chr((year mod 10) + 48);
  597.   if month > 9 then Inc(month, 7);
  598.   yym[3]    := Chr(month + 48);
  599.   dd[1]     := Chr((day div 10) + 48);
  600.   dd[2]     := Chr((day mod 10) + 48);
  601.   dd        := TrimLeft(dd);
  602.  
  603.   { Convert time to hh:mm form }
  604.   hhmm      := '00:00';
  605.   hhmm[1]   := Chr((hr  div 10) + 48);
  606.   hhmm[2]   := Chr((hr  mod 10) + 48);
  607.   hhmm[4]   := Chr((min div 10) + 48);
  608.   hhmm[5]   := Chr((min mod 10) + 48);
  609.   hhmm      := TrimLeft(hhmm);
  610.   { Leave at least one character before the colon }
  611.   if hhmm[1] = ':' then
  612.     hhmm := '0' + hhmm;
  613.  
  614.   if (env_set) then
  615.     begin { if }
  616.       WriteEnvVar('NETADDR', netaddr);
  617.       WriteEnvVar('PSTAT', pstat);
  618.       WriteEnvVar('STATION', stn);
  619.       { NOTE: un-REM next line to store socket as an EVAR }
  620.     { WriteEnvVar('SOCKET', sock); }
  621.       WriteEnvVar('NAME', name);
  622.       { NOTE: un-REM next line to store fullname as an EVAR }
  623.     { WriteEnvVar('FULLNAM', fullname); }
  624.  
  625.       if (fil_set) then
  626.         begin { if }
  627.  
  628.           {***********************}
  629.           {* OPEN OR CREATE FILE *}
  630.           {***********************}
  631.  
  632.           fil_nam := fil_path + 'CFG' + yym + '.TXT';
  633.           Assign(F, fil_nam);
  634.           Append(F);
  635.           if (IOResult <> 0) then
  636.             { If file doesn't already exist, create it }
  637.             Rewrite(F);
  638.           Write(F,dd,',',hhmm);
  639.           { Store N/A answers as empty fields }
  640.           if netaddr = 'N/A' then
  641.             Write(F,',')
  642.           else
  643.             Write(F,',',netaddr);
  644.           if pstat2 = 'N/A' then
  645.             Write(F,',')
  646.           else
  647.             Write(F,',',pstat2);
  648.           Write(F,',',stn);
  649.           { NOTE: un-REM next line if you want to file socket# }
  650.         { Write(F,',',sock); }
  651.           { NOTE: THE NEXT TEST IS SPECIFIC TO WIU. OTHERS MAY OMIT! }
  652.           { It files anonymous usernames as 1 character to save disk space }
  653.           if ((name = 'LAB') or (name = 'GUEST')) then
  654.             Write(F,',',name[1],',""')
  655.           else
  656.             begin { else }
  657.               if name = 'N/A' then
  658.                 Write(F,',')
  659.               else
  660.                 Write(F,',',name);
  661.               if fullname = 'N/A' then
  662.                 Write(F,',""')
  663.               else
  664.                 Write(F,',"',fullname,'"')
  665.             end { else }
  666.         end { if }
  667.     end { if }
  668.   else
  669.     begin { else }
  670.       Writeln('NETADDR.....', netaddr);
  671.       Writeln('PSTAT.......', pstat2);
  672.       Writeln('STATION.....', stn);
  673.       Writeln('SOCKET......', sock);
  674.       Writeln('NAME........', name);
  675.       Writeln('FULLNAM.....', fullname)
  676.     end; { else }
  677.  
  678.   {**************}
  679.   {* OS VERSION *}
  680.   {**************}
  681.  
  682.   if Major <= $0A then
  683.     os_version := Chr(Major + $30) + '.'
  684.                 + Chr((Minor DIV $0A) + $30)
  685.                 + Chr((Minor MOD $0A) + $30)
  686.   else
  687.     os_version := Chr((Major DIV $0A) + $30)
  688.                 + Chr((Major MOD $0A) + $30) + '.'
  689.                 + Chr((Minor DIV $0A) + $30)
  690.                 + Chr((Minor MOD $0A) + $30);
  691.  
  692.   if (env_set) then
  693.     begin { if }
  694.       WriteEnvVar('OS_VERSION', 'V'+os_version);
  695.       if (fil_set) then
  696.         Write(F,',',os_version)
  697.     end { if }
  698.   else
  699.     Writeln('OS_VERSION..', 'V'+os_version);
  700.  
  701.   {************}
  702.   {* CPU TYPE *}
  703.   {************}
  704.  
  705.   CPUval := CPUis;
  706.  
  707.   case (CPUval) of
  708.       $386 :
  709.         begin { case 386 }
  710.           cpu   := '386';
  711.           class := 'AT'
  712.         end; { case 386 }
  713.       $286 :
  714.         begin { case 286 }
  715.           cpu   := '286';
  716.           class := 'AT';
  717.         end; { case 286 }
  718.       $86 :
  719.         begin { case 86 }
  720.           cpu   := '808x';
  721.           class := 'PC'
  722.         end { case 86 }
  723.       else
  724.         begin { case else }
  725.           cpu   := 'N/A';
  726.           class := 'N/A'
  727.         end { case else }
  728.     end; { case }
  729.  
  730.   if (env_set) then
  731.     begin { if }
  732.       WriteEnvVar('CPU', cpu);
  733.       WriteEnvVar('CLASS', class);
  734.       if (fil_set) then
  735.         Write(F,',',cpu[1]) { No need to file CLASS - obvious from CPU }
  736.     end { if }
  737.   else
  738.     begin { else }
  739.       Writeln('CPU.........', cpu);
  740.       Writeln('CLASS.......', class)
  741.     end; { else }
  742.  
  743.    {**************}
  744.    {* MATH CHIP? *}
  745.    {**************}
  746.  
  747.   inline ($CD/$11   {interrupt 11h, Get BIOS equip word for FPU}
  748.          /$A3/AX);  {mov turbo_variable_ax, AX                 }
  749.   if ((AX AND $02) <> $00) then
  750.     fpu := 'T'
  751.   else
  752.     fpu := 'F';
  753.  
  754.   if (env_set) then
  755.     begin { if }
  756.       WriteEnvVar('FPU', fpu);
  757.       if (fil_set) then
  758.         Write(F,',',fpu)
  759.     end { if }
  760.   else
  761.     Writeln('FPU.........', fpu);
  762.  
  763.   {***********************}
  764.   {* CONVENTIONAL MEMORY *}
  765.   {***********************}
  766.  
  767.   inline ($CD/$12                   { int 12                        }
  768.          /$A3/memval);              { mov memval, AX                }
  769.   if ((memval AND $0001) <> 0) then { Some systems report 1K less   }
  770.     Inc(memval);                    { than actual, so we compensate }
  771.   Str(memval, conv);
  772.  
  773.   if (env_set) then
  774.     begin { if }
  775.       WriteEnvVar('CONV', conv);
  776.       if (fil_set) then
  777.         Write(F,',',conv)
  778.     end { if }
  779.   else
  780.     Writeln('CONV........', conv);
  781.  
  782.   {********************}
  783.   {* FREE CONV MEMORY *}
  784.   {********************}
  785.  
  786.   inline ($B4/$48             { mov AH, 48     }
  787.          /$BB/$FF/$FF         { mov BX, FFFF   }
  788.          /$CD/$21             { int 21         }
  789.          /$89/$1E/memval);    { mov memval, BX }
  790.  
  791.   {We change 16 byte paragraphs to decimal bytes and add 33 because}
  792.   {Config uses 33K of RAM itself}
  793.   {Result is conservative - there may be 1-4K more RAM free than claimed}
  794.   Str(memval SHR 6 + 33, free);
  795.  
  796.   if (env_set) then
  797.     begin { if }
  798.       WriteEnvVar('FREE', free);
  799.       if (fil_set) then
  800.         Write(F,',',free)
  801.     end { if }
  802.   else
  803.     Writeln('FREE........', free);
  804.  
  805.   {*******************}
  806.   {* EXPANDED MEMORY *}
  807.   {*******************}
  808.  
  809.   inline ($B8/$67/$35        { mov AX, 3567    }
  810.          /$CD/$21            { int 21          }
  811.          /$8C/$06/far_ptr);  { mov far_ptr, ES }
  812.   exp := 'T';
  813.   {Look for EMMXXXX0 ID string}
  814.   if Mem[far_ptr : 10] <> $45 then exp := 'F';
  815.   if Mem[far_ptr : 11] <> $4D then exp := 'F';
  816.   if Mem[far_ptr : 12] <> $4D then exp := 'F';
  817.   if Mem[far_ptr : 13] <> $58 then exp := 'F';
  818.   if Mem[far_ptr : 14] <> $58 then exp := 'F';
  819.   if Mem[far_ptr : 15] <> $58 then exp := 'F';
  820.   if Mem[far_ptr : 16] <> $58 then exp := 'F';
  821.   if Mem[far_ptr : 17] <> $30 then exp := 'F';
  822.  
  823.   if (env_set) then
  824.     begin { if }
  825.       WriteEnvVar('EXP', exp);
  826.       if (fil_set) then
  827.         Write(F,',',exp)
  828.     end { if }
  829.   else
  830.     Writeln('EXP.........', exp);
  831.  
  832.   {*******************}
  833.   {* EXTENDED MEMORY *}
  834.   {*******************}
  835.  
  836.   { This code must follow the CPU code  }
  837.   ext := 'F';
  838.   if (class = 'AT') then
  839.     begin { if }
  840.       inline ($B8/$00/$88    { mov AX, 8800    }
  841.              /$CD/$15        { int 15          }
  842.              /$A3/memval);   { mov memval, AX  }
  843.       if ((memval <> $8800) AND (memval <> $0000)) then
  844.         ext := 'T'
  845.     end; { if }
  846.  
  847.   if (env_set) then
  848.     begin { if }
  849.       WriteEnvVar('EXT', ext);
  850.       if (fil_set) then
  851.         Write(F,',',ext)
  852.     end { if }
  853.   else
  854.     Writeln('EXT.........', ext);
  855.  
  856.    {**********}
  857.    {* MOUSE? *}
  858.    {**********}
  859.  
  860.   inline ($B8/$00/$00     { mov AX, 0                               }
  861.          /$CD/$33         { int 33   Mouse function 0 - initialize  }
  862.          /$A3/AX);        { mov turbo_variable_ax, AX               }
  863.   if (AX <> $0000) then
  864.     mouse := 'T'
  865.   else
  866.     mouse := 'F';
  867.  
  868.   if (env_set) then
  869.     begin { if }
  870.       WriteEnvVar('MOUSE', mouse);
  871.       if (fil_set) then
  872.         Write(F,',',mouse)
  873.     end { if }
  874.   else
  875.     Writeln('MOUSE.......', mouse);
  876.  
  877.   {**************}
  878.   {* VIDEO MODE *}
  879.   {**************}
  880.  
  881.   inline ($B8/$00/$0F    { mov AX, 0f00               }
  882.          /$CD/$10        { int 10 - Video interrupt   }
  883.          /$A2/al);       { mov turbo_variable_al, AL  }
  884.   case (AL) of
  885.      $00,
  886.      $02,
  887.      $07  : mode := 'MONO'
  888.   else
  889.     mode  := 'COLOR'
  890.   end; { case }
  891.  
  892.   if (env_set) then
  893.     begin { if }
  894.       WriteEnvVar('MODE', mode);
  895.       if (fil_set) then
  896.         Write(F,',',mode[1])
  897.     end { if }
  898.   else
  899.     Writeln('MODE........', mode);
  900.  
  901.    {*****************}
  902.    {* VIDEO ADAPTER *}
  903.    {*****************}
  904.  
  905.   vtyp := videoType; { From MM's Adapter unit }
  906.  
  907.   video := 'N/A';
  908.   if vtyp = 'V' then video := 'VGA';
  909.   if vtyp = 'E' then video := 'EGA';
  910.   if (vtyp = 'C') or (vtyp = 'M') then video := 'CGA';
  911.   if vtyp = 'H' then video := 'HERC';
  912.   if vtyp = 'M' then video := 'MDA';
  913.  
  914.   if (env_set) then
  915.     begin { if }
  916.       WriteEnvVar('VIDEO', video);
  917.       if (fil_set) then
  918.         Writeln(F,',',video[1]);
  919.         { All data sent - close file }
  920.         Close(F)
  921.     end { if }
  922.   else
  923.     Writeln('VIDEO.......', video)
  924.  
  925. end. { Config }
  926.