[0001]
[0002]
[0003]
[0004]
[0005]
[0006]
[0007]
[0008]
[0009]
[0010]
[0011]
[0012]
[0013]
[0014]
[0015]
[0016]
[0017]
[0018]
[0019]
[0020]
[0021]
[0022]
[0023]
[0024]
[0025]
[0026]
[0027]
[0028]
[0029]
[0030]
[0031]
[0032]
[0033]
[0034]
[0035]
[0036]
[0037]
[0038]
[0039]
[0040]
[0041]
[0042]
[0043]
[0044]
[0045]
[0046]
[0047]
[0048]
[0049]
[0050]
[0051]
[0052]
[0053]
[0054]
[0055]
[0056]
[0057]
[0058]
[0059]
[0060]
[0061]
[0062]
[0063]
[0064]
[0065]
[0066]
[0067]
[0068]
[0069]
[0070]
[0071]
[0072]
[0073]
[0074]
[0075]
[0076]
[0077]
[0078]
[0079]
[0080]
[0081]
[0082]
[0083]
[0084]
[0085]
[0086]
[0087]
[0088]
[0089]
[0090]
[0091]
[0092]
[0093]
[0094]
[0095]
[0096]
[0097]
[0098]
[0099]
[0100]
[0101]
[0102]
[0103]
[0104]
[0105]
[0106]
[0107]
[0108]
[0109]
[0110]
[0111]
[0112]
[0113]
[0114]
[0115]
[0116]
[0117]
[0118]
[0119]
[0120]
[0121]
[0122]
[0123]
[0124]
[0125]
[0126]
[0127]
[0128]
[0129]
[0130]
[0131]
[0132]
[0133]
[0134]
[0135]
[0136]
[0137]
[0138]
[0139]
[0140]
[0141]
[0142]
[0143]
[0144]
[0145]
[0146]
[0147]
[0148]
[0149]
[0150]
[0151]
[0152]
[0153]
[0154]
[0155]
[0156]
[0157]
[0158]
[0159]
[0160]
[0161]
[0162]
[0163]
[0164]
[0165]
[0166]
[0167]
[0168]
[0169]
[0170]
[0171]
[0172]
[0173]
[0174]
[0175]
[0176]
[0177]
[0178]
[0179]
[0180]
[0181]
[0182]
[0183]
[0184]
[0185]
[0186]
[0187]
[0188]
[0189]
[0190]
[0191]
[0192]
[0193]
[0194]
[0195]
[0196]
[0197]
[0198]
[0199]
[0200]
[0201]
[0202]
[0203]
[0204]
[0205]
[0206]
[0207]
[0208]
[0209]
[0210]
[0211]
[0212]
[0213]
[0214]
[0215]
[0216]
[0217]
[0218]
[0219]
[0220]
[0221]
[0222]
[0223]
[0224]
[0225]
[0226]
[0227]
[0228]
[0229]
[0230]
[0231]
[0232]
[0233]
[0234]
[0235]
[0236]
[0237]
[0238]
[0239]
[0240]
[0241]
[0242]
[0243]
[0244]
[0245]
[0246]
[0247]
[0248]
[0249]
[0250]
[0251]
[0252]
[0253]
[0254]
[0255]
[0256]
[0257]
[0258]
[0259]
[0260]
[0261]
[0262]
[0263]
[0264]
[0265]
[0266]
[0267]
[0268]
[0269]
[0270]
[0271]
[0272]
[0273]
[0274]
[0275]
[0276]
[0277]
[0278]
[0279]
[0280]
[0281]
[0282]
[0283]
[0284]
[0285]
[0286]
[0287]
[0288]
[0289]
[0290]
[0291]
[0292]
[0293]
[0294]
[0295]
[0296]
[0297]
[0298]
[0299]
[0300]
[0301]
[0302]
[0303]
[0304]
[0305]
[0306]
[0307]
[0308]
[0309]
[0310]
[0311]
[0312]
[0313]
[0314]
[0315]
[0316]
[0317]
[0318]
[0319]
[0320]
[0321]
[0322]
[0323]
[0324]
[0325]
[0326]
[0327]
[0328]
[0329]
[0330]
[0331]
[0332]
[0333]
[0334]
[0335]
[0336]
[0337]
[0338]
[0339]
[0340]
[0341]
[0342]
[0343]
[0344]
[0345]
[0346]
[0347]
[0348]
[0349]
[0350]
[0351]
[0352]
[0353]
[0354]
[0355]
[0356]
[0357]
[0358]
[0359]
[0360]
[0361]
[0362]
[0363]
[0364]
[0365]
[0366]
[0367]
[0368]
[0369]
[0370]
[0371]
[0372]
[0373]
[0374]
[0375]
[0376]
[0377]
[0378]
[0379]
[0380]
[0381]
[0382]
[0383]
[0384]
[0385]
[0386]
[0387]
[0388]
[0389]
[0390]
[0391]
[0392]
[0393]
[0394]
[0395]
[0396]
[0397]
[0398]
[0399]
[0400]
[0401]
[0402]
[0403]
[0404]
[0405]
[0406]
[0407]
[0408]
[0409]
[0410]
[0411]
[0412]
[0413]
[0414]
[0415]
[0416]
[0417]
[0418]
[0419]
[0420]
[0421]
[0422]
[0423]
[0424]
[0425]
[0426]
[0427]
[0428]
[0429]
[0430]
[0431]
[0432]
[0433]
[0434]
[0435]
[0436]
[0437]
[0438]
[0439]
[0440]
[0441]
[0442]
[0443]
[0444]
[0445]
[0446]
[0447]
[0448]
[0449]
[0450]
[0451]
[0452]
[0453]
[0454]
[0455]
[0456]
[0457]
[0458]
[0459]
[0460]
[0461]
[0462]
[0463]
[0464]
[0465]
[0466]
[0467]
[0468]
[0469]
[0470]
[0471]
[0472]
[0473]
[0474]
[0475]
[0476]
[0477]
[0478]
[0479]
[0480]
[0481]
[0482]
[0483]
[0484]
[0485]
[0486]
[0487]
[0488]
[0489]
[0490]
[0491]
[0492]
[0493]
[0494]
[0495]
[0496]
[0497]
[0498]
[0499]
[0500]
[0501]
[0502]
[0503]
[0504]
[0505]
[0506]
[0507]
[0508]
[0509]
[0510]
[0511]
[0512]
[0513]
[0514]
[0515]
[0516]
[0517]
[0518]
[0519]
[0520]
[0521]
[0522]
[0523]
[0524]
[0525]
[0526]
[0527]
[0528]
[0529]
[0530]
[0531]
[0532]
[0533]
[0534]
[0535]
[0536]
[0537]
[0538]
[0539]
[0540]
[0541]
[0542]
[0543]
[0544]
[0545]
[0546]
[0547]
[0548]
[0549]
[0550]
[0551]
[0552]
[0553]
[0554]
[0555]
[0556]
[0557]
[0558]
[0559]
[0560]
[0561]
[0562]
[0563]
[0564]
[0565]
[0566]
[0567]
[0568]
[0569]
[0570]
[0571]
[0572]
[0573]
[0574]
[0575]
[0576]
[0577]
[0578]
[0579]
[0580]
[0581]
[0582]
[0583]
[0584]
[0585]
[0586]
[0587]
[0588]
[0589]
[0590]
[0591]
[0592]
[0593]
[0594]
[0595]
[0596]
[0597]
[0598]
[0599]
[0600]
[0601]
[0602]
[0603]
[0604]
[0605]
[0606]
[0607]
[0608]
[0609]
[0610]
[0611]
[0612]
[0613]
[0614]
[0615]
[0616]
[0617]
[0618]
[0619]
[0620]
[0621]
[0622]
[0623]
[0624]
[0625]
[0626]
[0627]
[0628]
[0629]
[0630]
[0631]
[0632]
[0633]
[0634]
[0635]
[0636]
[0637]
[0638]
[0639]
[0640]
[0641]
[0642]
[0643]
[0644]
[0645]
[0646]
[0647]
[0648]
[0649]
[0650]
[0651]
[0652]
[0653]
[0654]
[0655]
[0656]
[0657]
[0658]
[0659]
[0660]
[0661]
[0662]
[0663]
[0664]
[0665]
[0666]
[0667]
[0668]
[0669]
[0670]
[0671]
[0672]
[0673]
[0674]
[0675]
[0676]
[0677]
[0678]
[0679]
[0680]
[0681]
[0682]
[0683]
[0684]
[0685]
[0686]
[0687]
[0688]
[0689]
[0690]
[0691]
[0692]
[0693]
[0694]
[0695]
[0696]
[0697]
[0698]
[0699]
[0700]
[0701]
[0702]
[0703]
[0704]
[0705]
[0706]
[0707]
[0708]
[0709]
[0710]
[0711]
[0712]
[0713]
[0714]
[0715]
[0716]
[0717]
[0718]
[0719]
[0720]
[0721]
[0722]
[0723]
[0724]
[0725]
[0726]
[0727]
[0728]
[0729]
[0730]
[0731]
[0732]
[0733]
[0734]
[0735]
[0736]
[0737]
[0738]
[0739]
[0740]
[0741]
[0742]
[0743]
[0744]
[0745]
[0746]
[0747]
[0748]
[0749]
[0750]
[0751]
[0752]
[0753]
[0754]
[0755]
[0756]
[0757]
[0758]
[0759]
[0760]
[0761]
[0762]
[0763]
[0764]
[0765]
[0766]
[0767]
[0768]
[0769]
[0770]
[0771]
[0772]
[0773]
[0774]
[0775]
[0776]
[0777]
[0778]
[0779]
[0780]
[0781]
[0782]
[0783]
[0784]
[0785]
[0786]
[0787]
[0788]
[0789]
[0790]
[0791]
[0792]
[0793]
[0794]
[0795]
[0796]
[0797]
[0798]
[0799]
[0800]
[0801]
[0802]
[0803]
[0804]
[0805]
[0806]
[0807]
[0808]
[0809]
[0810]
[0811]
[0812]
[0813]
[0814]
[0815]
[0816]
[0817]
[0818]
[0819]
[0820]
[0821]
[0822]
[0823]
[0824]
[0825]
[0826]
[0827]
[0828]
[0829]
[0830]
[0831]
[0832]
[0833]
[0834]
[0835]
[0836]
[0837]
[0838]
[0839]
[0840]
[0841]
[0842]
[0843]
[0844]
[0845]
[0846]
[0847]
[0848]
[0849]
[0850]
[0851]
[0852]
[0853]
[0854]
[0855]
[0856]
[0857]
[0858]
[0859]
[0860]
[0861]
[0862]
[0863]
[0864]
[0865]
[0866]
[0867]
[0868]
[0869]
[0870]
[0871]
[0872]
[0873]
[0874]
[0875]
[0876]
[0877]
[0878]
[0879]
[0880]
[0881]
[0882]
[0883]
[0884]
[0885]
[0886]
[0887]
[0888]
[0889]
[0890]
[0891]
[0892]
[0893]
[0894]
[0895]
[0896]
[0897]
[0898]
[0899]
[0900]
[0901]
[0902]
[0903]
[0904]
[0905]
[0906]
[0907]
[0908]
[0909]
[0910]
[0911]
[0912]
[0913]
[0914]
[0915]
[0916]
[0917]
[0918]
[0919]
[0920]
[0921]
[0922]
[0923]
[0924]
[0925]
[0926]
[0927]
[0928]
[0929]
[0930]
[0931]
[0932]
[0933]
[0934]
[0935]
[0936]
[0937]
[0938]
[0939]
[0940]
[0941]
[0942]
[0943]
[0944]
[0945]
[0946]
[0947]
[0948]
[0949]
[0950]
[0951]
[0952]
[0953]
[0954]
[0955]
[0956]
[0957]
[0958]
[0959]
[0960]
[0961]
[0962]
[0963]
[0964]
[0965]
[0966]
[0967]
[0968]
[0969]
[0970]
[0971]
[0972]
[0973]
[0974]
[0975]
[0976]
[0977]
[0978]
[0979]
[0980]
[0981]
[0982]
[0983]
[0984]
[0985]
[0986]
[0987]
[0988]
[0989]
[0990]
[0991]
[0992]
[0993]
[0994]
[0995]
[0996]
[0997]
[0998]
[0999]
[1000]
[1001]
[1002]
[1003]
[1004]
[1005]
[1006]
[1007]
[1008]
[1009]
[1010]
[1011]
[1012]
[1013]
[1014]
[1015]
[1016]
[1017]
[1018]
[1019]
[1020]
[1021]
[1022]
[1023]
[1024]
[1025]
[1026]
[1027]
[1028]
[1029]
[1030]
[1031]
[1032]
[1033]
[1034]
[1035]
[1036]
[1037]
[1038]
[1039]
[1040]
[1041]
[1042]
[1043]
[1044]
[1045]
[1046]
[1047]
[1048]
[1049]
[1050]
[1051]
[1052]
[1053]
[1054]
[1055]
[1056]
[1057]
[1058]
[1059]
[1060]
[1061]
[1062]
[1063]
[1064]
[1065]
[1066]
[1067]
[1068]
[1069]
[1070]
[1071]
[1072]
[1073]
[1074]
[1075]
[1076]
[1077]
[1078]
[1079]
[1080]
[1081]
[1082]
[1083]
[1084]
[1085]
[1086]
[1087]
[1088]
[1089]
[1090]
[1091]
[1092]
[1093]
[1094]
[1095]
[1096]
[1097]
[1098]
[1099]
[1100]
[1101]
[1102]
[1103]
[1104]
[1105]
[1106]
[1107]
[1108]
[1109]
[1110]
[1111]
[1112]
[1113]
[1114]
[1115]
[1116]
[1117]
[1118]
[1119]
[1120]
[1121]
[1122]
[1123]
[1124]
[1125]
[1126]
[1127]
[1128]
[1129]
[1130]
[1131]
[1132]
[1133]
[1134]
[1135]
[1136]
[1137]
[1138]
[1139]
[1140]
[1141]
[1142]
[1143]
[1144]
[1145]
[1146]
[1147]
[1148]
[1149]
[1150]
[1151]
[1152]
[1153]
[1154]
[1155]
[1156]
[1157]
[1158]
[1159]
[1160]
[1161]
[1162]
[1163]
[1164]
[1165]
[1166]
[1167]
[1168]
[1169]
[1170]
[1171]
[1172]
[1173]
[1174]
[1175]
[1176]
[1177]
[1178]
[1179]
[1180]
[1181]
[1182]
[1183]
[1184]
[1185]
[1186]
[1187]
[1188]
[1189]
[1190]
[1191]
[1192]
[1193]
[1194]
[1195]
[1196]
[1197]
[1198]
[1199]
[1200]
[1201]
[1202]
[1203]
[1204]
[1205]
[1206]
[1207]
[1208]
[1209]
[1210]
[1211]
[1212]
[1213]
[1214]
[1215]
[1216]
[1217]
[1218]
[1219]
[1220]
[1221]
[1222]
[1223]
[1224]
[1225]
[1226]
[1227]
[1228]
[1229]
[1230]
[1231]
[1232]
[1233]
[1234]
[1235]
[1236]
[1237]
[1238]
[1239]
[1240]
[1241]
[1242]
[1243]
[1244]
[1245]
[1246]
[1247]
[1248]
[1249]
[1250]
[1251]
[1252]
[1253]
[1254]
[1255]
[1256]
[1257]
[1258]
[1259]
[1260]
[1261]
[1262]
[1263]
[1264]
[1265]
[1266]
[1267]
[1268]
[1269]
[1270]
[1271]
[1272]
[1273]
[1274]
[1275]
[1276]
[1277]
[1278]
[1279]
[1280]
[1281]
[1282]
[1283]
[1284]
[1285]
[1286]
[1287]
[1288]
[1289]
[1290]
[1291]
[1292]
[1293]
[1294]
[1295]
[1296]
[1297]
[1298]
[1299]
[1300]
[1301]
[1302]
[1303]
[1304]
[1305]
[1306]
[1307]
[1308]
[1309]
[1310]
[1311]
[1312]
[1313]
[1314]
[1315]
[1316]
[1317]
[1318]
[1319]
[1320]
[1321]
[1322]
[1323]
[1324]
[1325]
[1326]
[1327]
[1328]
[1329]
[1330]
[1331]
[1332]
[1333]
[1334]
[1335]
[1336]
[1337]
[1338]
[1339]
[1340]
[1341]
[1342]
[1343]
[1344]
[1345]
[1346]
[1347]
[1348]
[1349]
[1350]
[1351]
[1352]
[1353]
[1354]
[1355]
[1356]
[1357]
[1358]
[1359]
[1360]
[1361]
[1362]
[1363]
[1364]
[1365]
[1366]
[1367]
[1368]
[1369]
[1370]
[1371]
[1372]
[1373]
[1374]
[1375]
[1376]
[1377]
[1378]
[1379]
[1380]
[1381]
[1382]
[1383]
[1384]
[1385]
[1386]
[1387]
[1388]
[1389]
[1390]
[1391]
[1392]
[1393]
[1394]
[1395]
[1396]
[1397]
[1398]
[1399]
[1400]
[1401]
[1402]
[1403]
[1404]
[1405]
[1406]
[1407]
[1408]
[1409]
[1410]
[1411]
[1412]
[1413]
[1414]
[1415]
[1416]
[1417]
[1418]
[1419]
[1420]
[1421]
[1422]
[1423]
[1424]
[1425]
[1426]
[1427]
[1428]
[1429]
[1430]
[1431]
[1432]
[1433]
[1434]
[1435]
[1436]
[1437]
[1438]
[1439]
[1440]
[1441]
[1442]
[1443]
[1444]
[1445]
[1446]
[1447]
[1448]
[1449]
[1450]
[1451]
[1452]
[1453]
[1454]
[1455]
[1456]
[1457]
[1458]
[1459]
[1460]
[1461]
[1462]
[1463]
[1464]
[1465]
[1466]
[1467]
[1468]
[1469]
[1470]
[1471]
[1472]
[1473]
[1474]
[1475]
[1476]
[1477]
[1478]
[1479]
[1480]
[1481]
[1482]
[1483]
[1484]
[1485]
[1486]
[1487]
[1488]
[1489]
[1490]
[1491]
[1492]
[1493]
[1494]
[1495]
[1496]
[1497]
[1498]
[1499]
[1500]
[1501]
[1502]
[1503]
[1504]
[1505]
[1506]
[1507]
[1508]
[1509]
[1510]
[1511]
[1512]
[1513]
[1514]
[1515]
[1516]
[1517]
[1518]
[1519]
[1520]
[1521]
[1522]
[1523]
[1524]
[1525]
[1526]
[1527]
[1528]
[1529]
[1530]
[1531]
[1532]
[1533]
[1534]
[1535]
[1536]
[1537]
[1538]
[1539]
[1540]
[1541]
[1542]
[1543]
[1544]
[1545]
[1546]
[1547]
[1548]
[1549]
[1550]
[1551]
[1552]
[1553]
[1554]
[1555]
[1556]
[1557]
[1558]
[1559]
[1560]
[1561]
[1562]
[1563]
[1564]
[1565]
[1566]
[1567]
[1568]
[1569]
[1570]
[1571]
[1572]
[1573]
[1574]
[1575]
[1576]
[1577]
[1578]
[1579]
[1580]
[1581]
[1582]
[1583]
[1584]
[1585]
[1586]
[1587]
[1588]
[1589]
[1590]
[1591]
[1592]
[1593]
[1594]
[1595]
[1596]
[1597]
[1598]
[1599]
[1600]
[1601]
[1602]
[1603]
[1604]
[1605]
[1606]
[1607]
[1608]
[1609]
[1610]
[1611]
[1612]
[1613]
[1614]
[1615]
[1616]
[1617]
[1618]
[1619]
[1620]
[1621]
[1622]
[1623]
[1624]
[1625]
[1626]
[1627]
[1628]
[1629]
[1630]
[1631]
[1632]
[1633]
[1634]
[1635]
[1636]
[1637]
[1638]
[1639]
[1640]
[1641]
[1642]
[1643]
[1644]
[1645]
[1646]
[1647]
[1648]
[1649]
[1650]
[1651]
[1652]
[1653]
[1654]
[1655]
[1656]
[1657]
[1658]
[1659]
[1660]
[1661]
[1662]
[1663]
[1664]
[1665]
[1666]
[1667]
[1668]
[1669]
[1670]
[1671]
[1672]
[1673]
[1674]
[1675]
[1676]
[1677]
[1678]
[1679]
[1680]
[1681]
[1682]
[1683]
[1684]
[1685]
[1686]
[1687]
[1688]
[1689]
[1690]
[1691]
[1692]
[1693]
[1694]
[1695]
[1696]
[1697]
[1698]
[1699]
[1700]
[1701]
[1702]
[1703]
[1704]
[1705]
[1706]
[1707]
[1708]
[1709]
[1710]
[1711]
[1712]
[1713]
[1714]
[1715]
[1716]
[1717]
[1718]
[1719]
[1720]
[1721]
[1722]
[1723]
[1724]
[1725]
[1726]
[1727]
[1728]
[1729]
[1730]
[1731]
[1732]
[1733]
[1734]
[1735]
[1736]
[1737]
[1738]
[1739]
[1740]
[1741]
[1742]
[1743]
[1744]
[1745]
[1746]
[1747]
[1748]
[1749]
[1750]
[1751]
[1752]
[1753]
[1754]
[1755]
[1756]
[1757]
[1758]
[1759]
[1760]
[1761]
[1762]
[1763]
[1764]
[1765]
[1766]
[1767]
[1768]
[1769]
[1770]
[1771]
[1772]
[1773]
[1774]
[1775]
[1776]
[1777]
[1778]
[1779]
[1780]
[1781]
[1782]
[1783]
[1784]
[1785]
[1786]
[1787]
[1788]
[1789]
[1790]
[1791]
[1792]
[1793]
[1794]
[1795]
[1796]
[1797]
[1798]
[1799]
[1800]
[1801]
[1802]
[1803]
[1804]
[1805]
[1806]
[1807]
[1808]
[1809]
[1810]
[1811]
[1812]
[1813]
[1814]
[1815]
[1816]
[1817]
[1818]
[1819]
[1820]
[1821]
[1822]
[1823]
[1824]
[1825]
[1826]
[1827]
[1828]
[1829]
[1830]
[1831]
[1832]
[1833]
[1834]
[1835]
[1836]
[1837]
[1838]
[1839]
[1840]
[1841]
[1842]
[1843]
[1844]
[1845]
[1846]
[1847]
[1848]
[1849]
[1850]
[1851]
[1852]
[1853]
[1854]
[1855]
[1856]
[1857]
[1858]
[1859]
[1860]
[1861]
[1862]
[1863]
[1864]
[1865]
[1866]
[1867]
[1868]
[1869]
[1870]
[1871]
[1872]
[1873]
[1874]
[1875]
[1876]
[1877]
[1878]
[1879]
[1880]
[1881]
[1882]
[1883]
[1884]
[1885]
[1886]
[1887]
[1888]
[1889]
[1890]
[1891]
[1892]
[1893]
[1894]
[1895]
[1896]
[1897]
[1898]
[1899]
[1900]
[1901]
[1902]
[1903]
[1904]
[1905]
[1906]
[1907]
[1908]
[1909]
[1910]
[1911]
[1912]
[1913]
[1914]
[1915]
[1916]
[1917]
[1918]
[1919]
[1920]
[1921]
[1922]
[1923]
[1924]
[1925]
[1926]
[1927]
[1928]
[1929]
[1930]
[1931]
[1932]
[1933]
[1934]
[1935]
[1936]
[1937]
[1938]
[1939]
[1940]
[1941]
[1942]
[1943]
[1944]
[1945]
[1946]
[1947]
[1948]
[1949]
[1950]
[1951]
[1952]
[1953]
[1954]
[1955]
[1956]
[1957]
[1958]
[1959]
[1960]
[1961]
[1962]
[1963]
[1964]
[1965]
[1966]
[1967]
[1968]
[1969]
[1970]
[1971]
[1972]
[1973]
[1974]
[1975]
[1976]
[1977]
[1978]
[1979]
[1980]
[1981]
[1982]
[1983]
[1984]
[1985]
[1986]
[1987]
[1988]
[1989]
[1990]
[1991]
[1992]
[1993]
[1994]
[1995]
[1996]
[1997]
[1998]
[1999]
[2000]
[2001]
[2002]
[2003]
[2004]
[2005]
/*****************************************************************************/
/*
                                  sysPLUS.c

Show essential system data without using a scripting process as does
WatchShowSystem().  It is intended as a fallback should the creation of a
scripting process fail (for example; no remaining process slot, insufficient
paged dynamic memory), providing essential data useful for trouble-shooting. 
It can also be activated using the URI /httpd/-/admin/report/system+.  And also
via the CLI with |rqptr| NULL which FaoToEither() handles.  I have experienced
both.

See sysPlusNet() for usage of logical name WASD_SYSPLUS_NI.


EXE$GETSPI
----------
What a dog's breakfast $GETRMI seems to be.  With MonDeSi it just seemed too
difficult to get consistent results across versions and platforms so I went
back to EXE$GETSPI and have arrived at the same conclusion again this time.

RMI$_SCS on Alpha VMS V8.3 and IA64 VSI V8.4 returns %X00000014
(%SYSTEM-F-BADPARAM, bad parameter value) when using this item.  (Same on VAX
V7.3 - but absolutely anything that works on VAX too is a bonus).  Using this
item with $GETSPI no problems.


VERSION HISTORY
---------------
20-JUL-2019  MGD  expand to include network, MSCP and SCS data
                  dignified with a module of its very own
                  adapt to allow use via CLI /SYSPLUS
25-AUG-2018  MGD  initial as WatchSystemPlus() et.al.
*/
/*****************************************************************************/

#ifdef WASD_VMS_V7
#undef _VMS__V6__SOURCE
#define _VMS__V6__SOURCE
#undef __VMS_VER
#define __VMS_VER 70000000
#undef __CRTL_VER
#define __CRTL_VER 70000000
#endif

/* standard C header files */
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

/* VMS related header files */
#include <descrip.h>
#include <dvidef.h>
#include <dvsdef.h>
#include <iodef.h>
#include <jpidef.h>
#include <libdef.h>
#include <libdtdef.h>
#include <lnmdef.h>
#include <rmidef.h>
#include <ssdef.h>
#include <stsdef.h>
#include <syidef.h>

/* application related header files */
#include "wasd.h"

#define WASD_MODULE "SYSPLUS"

#define DBUG 0

/* last <whatever> for selected data */
#define NUM_MINS 10

/* 96 is (still) the SPD cluster node limit (we had 70+ in the '90s :-) */
#define SCS_NODES_MAX 16

#ifndef WASD_GETSPI
#define WASD_GETSPI 0
#endif

/******************/
/* global storage */
/******************/

static ulong  sysPlusRmiMemErrs;

/********************/
/* external storage */
/********************/

extern int  EfnWait,
            HttpdTickSecond;

extern ulong  MailboxMask[];

extern SYS_INFO  SysInfo;
extern WATCH_STRUCT  Watch;

/*****************************************************************************/
/*
Report wrapper.
*/

void sysPlusReport (REQUEST_STRUCT *rqptr)

{
   static $DESCRIPTOR (SystemFaoDsc,
"!AZ, a !AZ with !UL CPU and !AZ running VMS !AZ");

   static char UnderFao [] =
"!AZ\n!#*-\nCurrent: !20%D  Boot: !20%D  Up: !%D\n\n";

   static int64  SyiBootTime64,
                 Time64,
                 UpTime64;

   static VMS_ITEM_LIST3  SyiItem [] =
   {
     { sizeof(SyiBootTime64), SYI$_BOOTTIME, &SyiBootTime64, 0 },
     { 0,0,0,0 }
   };

   BOOL  Not200;
   int  status;
   ushort  slen;
   char  SystemBuffer [256];
   IO_SB  IOsb;
   $DESCRIPTOR (SystemBufferDsc, SystemBuffer);

   /*********/
   /* begin */
   /*********/

   Not200 = true;
   if (rqptr)
   {
      if (Not200 = (rqptr->rqResponse.HttpStatus != 200))
      {
         rqptr->rqResponse.PreExpired = PRE_EXPIRE_ADMIN;
         ResponseHeader200 (rqptr, "text/plain", NULL);
      }
   }

   status = sys$getsyiw (EfnWait, 0, 0, &SyiItem, &IOsb, 0, 0);
   if (VMSok (status)) status = IOsb.Status;
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "$GETSYI() !&S\n",  status);
      return;
   }

   sys$gettim (&Time64);
   UpTime64 = SyiBootTime64 - Time64;

   status = sys$fao (&SystemFaoDsc, &slen, &SystemBufferDsc,
                     SysInfo.NodeName,
                     SysInfo.HwName,
                     SysInfo.AvailCpuCnt,
                     SysInfo.MemoryMBGB,
                     SysInfo.Version);
   SystemBuffer[slen] = '\0';
   if (VMSnok (status)) FaoToEither (rqptr, "$FAO() !&S\n",  status);

   status = FaoToEither (rqptr, &UnderFao, SystemBuffer, slen,
                         &Time64, &SyiBootTime64, &UpTime64);
   if (VMSnok (status)) FaoToEither (rqptr, "$FAO() !&S\n",  status);

   if (!rqptr)
   {
      /* at the command-line take a ten second sample of CPU consumption */
      sysPlusRmi ((REQUEST_STRUCT*)-1);
      sleep (10);
      /* force that sample up into the first "minute" buffer */
      sysPlusRmi ((REQUEST_STRUCT*)-1);
   }

   sysPlusRmi (rqptr);
   sysPlusSyi (rqptr);
   sysPlusScs (rqptr);
   sysPlusMscp (rqptr);
   sysPlusDvi (rqptr);
   sysPlusNet (rqptr);
   sysPlusJpi (rqptr);

   if (Not200)
   {
      FaoToEither (rqptr, "!77*-\n\n", SystemBuffer, slen);
      if (rqptr) AdminEnd (rqptr);
   }
}

/*****************************************************************************/
/*
Provide device data.
*/

void sysPlusDvi (REQUEST_STRUCT *rqptr)

{
#define DC$_DISK 1
#define DEV$V_NET 0x2000

   static char  DviHeader [] =
"Device Name      Errs  Refs        Ops Status\n\
~~~~~~~~~~~~~~~ ~~~~~ ~~~~~ ~~~~~~~~~~ ~~~~~~\n";

   static char  DeviceFao [] =
"!#AZ !5UL !5UL !10UL !AZ\n\
!#*  !5AZ!17*  !AZ\n";

   static char  NetSpeedFao [] = "!#* !AZ !AZ !ULMbpS\n",
                NetNoSpeedFao [] = "!#* !AZ !AZ\n";

   static char  DiskFao [] = "!#* \"!AZ\" !AZ free of !AZ (!UL%)\n";

   static $DESCRIPTOR (SearchDeviceDsc, "*");

   static ulong  DviDevClass,
                 DviDevChar,
                 DviDevChar2,
                 DviErrCnt,
                 DviFreeBlocks,
                 DviLanLinkStateValid,
                 DviLanLinkUp,
                 DviLanSpeed,
                 DviMaxBlock,
                 DviOpCnt,
                 DviPid,
                 DviRefCnt,
                 DviSts;

   static ushort  DviDevTypeNameLen,
                  DviVolNamLen;

   static char  DviDevTypeName [64+1],
                DviVolNam [15+1];

   static struct
   {
      ushort  buf_len;
      ushort  item;
      uchar   *buf_addr;
      ushort  *short_ret_len;
   }
      DviItems [] =
   {
      { sizeof(DviDevClass), DVI$_DEVCLASS, &DviDevClass, 0 },
      { sizeof(DviDevChar), DVI$_DEVCHAR, &DviDevChar, 0 },
      { sizeof(DviDevChar2), DVI$_DEVCHAR2, &DviDevChar2, 0 },
      { sizeof(DviErrCnt), DVI$_ERRCNT, &DviErrCnt, 0 },
      { sizeof(DviFreeBlocks), DVI$_FREEBLOCKS, &DviFreeBlocks, 0 },
#if(__VMS_VER >= 80000000))
      { sizeof(DviLanLinkStateValid), DVI$_LAN_LINK_STATE_VALID,
        &DviLanLinkStateValid, 0 },
      { sizeof(DviLanLinkUp), DVI$_LAN_LINK_UP, &DviLanLinkUp, 0 },
      { sizeof(DviLanSpeed), DVI$_LAN_SPEED, &DviLanSpeed, 0 },
#endif
      { sizeof(DviMaxBlock), DVI$_MAXBLOCK, &DviMaxBlock, 0 },
      { sizeof(DviDevTypeName)-1, DVI$_DEVICE_TYPE_NAME, &DviDevTypeName,
        &DviDevTypeNameLen},
      { sizeof(DviOpCnt), DVI$_OPCNT, &DviOpCnt, 0 },
      { sizeof(DviPid), DVI$_PID, &DviPid, 0 },
      { sizeof(DviRefCnt), DVI$_REFCNT, &DviRefCnt, 0 },
      { sizeof(DviSts), DVI$_STS, &DviSts, 0 },
      { sizeof(DviVolNam)-1, DVI$_VOLNAM, &DviVolNam, &DviVolNamLen },
      { 0,0,0,0 }
   };

   int  status;
   uint64  context64;
   ushort  slen;
   double  freefp, sizefp;
   char  DevCharBuf [256],
         DevName [64+1],
         DevStsBuf [256],
         FreeBuf [32],
         SizeBuf [32];
   $DESCRIPTOR (DevNameDsc, DevName);
   $DESCRIPTOR (ScanNameDsc, DevName);
   IO_SB  IOsb;
   
   /*********/
   /* begin */
   /*********/

   FaoToEither (rqptr, DviHeader);

   context64 = 0;

   for (;;)
   {
      status = sys$device_scan (&ScanNameDsc, &slen,
                                &SearchDeviceDsc, 0, &context64);
      if (VMSnok (status))
      {
         if (status != SS$_NOMOREDEV)
            FaoToEither (rqptr, "$DEVICE_SCAN() !&S\n", status);
         break;
      }

      DevName[slen] = '\0';
      DevNameDsc.dsc$w_length = slen;

      if (MATCH3 (DevName, "_BG") && !MATCH5 (DevName, "_BG0:")) continue;
      if (strstr (DevName, "$BG")) continue;

      if (MATCH3 (DevName, "_MB")) continue;
      if (strstr (DevName, "$MB")) continue;

      status = sys$getdviw (EfnWait, 0, &DevNameDsc,
                            &DviItems, &IOsb, 0, 0, 0, 0);
      if (VMSok (status)) status = IOsb.Status;
      if (VMSnok (status))
      {
         if (status != SS$_NOMOREDEV)
            FaoToEither (rqptr, "$GETDVI() !&S\n", status);
         break;
      }

      DevStsBuf[0] = '\0';

      if (DviSts & 0x1) strcat (DevStsBuf, " tim");
      if (DviSts & 0x2) strcat (DevStsBuf, " int");
      if (DviSts & 0x4) strcat (DevStsBuf, " erlogip");
      if (DviSts & 0x8) strcat (DevStsBuf, " cancel");
      if (DviSts & 0x10) strcat (DevStsBuf, " ONLINE");
                    else strcat (DevStsBuf, " OFFLINE");
      if (DviSts & 0x20) strcat (DevStsBuf, " power");
      if (DviSts & 0x40) strcat (DevStsBuf, " TIMEOUT");
      if (DviSts & 0x80) strcat (DevStsBuf, " inttype");
      if (DviSts & 0x100) strcat (DevStsBuf, " busy");
      if (DviSts & 0x200) strcat (DevStsBuf, " mounting");
      if (DviSts & 0x400) strcat (DevStsBuf, " deadmo");
      if (DviSts & 0x800) strcat (DevStsBuf, " valid");
      if (DviSts & 0x1000) strcat (DevStsBuf, " unload");
      if (DviSts & 0x2000) strcat (DevStsBuf, " template");
      if (DviSts & 0x4000) strcat (DevStsBuf, " MNTVERIP");
      if (DviSts & 0x8000) strcat (DevStsBuf, " WRONGVOL");
      if (DviSts & 0x10000) strcat (DevStsBuf, " deleteucb");
      if (DviSts & 0x20000) strcat (DevStsBuf, " lclvalid");
      if (DviSts & 0x40000) strcat (DevStsBuf, " supmvmsg");
      if (DviSts & 0x80000) strcat (DevStsBuf, " MNTVERPND");
      if (DviSts & 0x100000) strcat (DevStsBuf, " dismount");
      if (DviSts & 0x200000) strcat (DevStsBuf, " clutran");
      if (DviSts & 0x400000) strcat (DevStsBuf, " wrtlockmv");
      if (DviSts & 0x800000) strcat (DevStsBuf, " svpnend");
      if (DviSts & 0x1000000) strcat (DevStsBuf, " altbsy");
      if (DviSts & 0x2000000) strcat (DevStsBuf, " snapshot");
      if (DviSts & 0x4000000) strcat (DevStsBuf, " noassign");
      if (DviSts & 0x8000000) strcat (DevStsBuf, " exfuncsupp");
      if (DviSts & 0x1000000) strcat (DevStsBuf, " fastpath");
      if (DviSts & 0x2000000) strcat (DevStsBuf, " pathverip");
      if (DviSts & 0x4000000) strcat (DevStsBuf, " fphwint");
      if (DviSts & 0x8000000) strcat (DevStsBuf, " iopostlocal");

      strncpy (DevCharBuf, DviDevTypeName, DviDevTypeNameLen);
      DevCharBuf[DviDevTypeNameLen] = ':';
      DevCharBuf[DviDevTypeNameLen+1] = '\0';

      if (DviDevChar & 0x1) strcat (DevCharBuf, " rec");
      if (DviDevChar & 0x2) strcat (DevCharBuf, " ccl");
      if (DviDevChar & 0x4) strcat (DevCharBuf, " TERMINAL");
      if (DviDevChar & 0x8) strcat (DevCharBuf, " dir");
      if (DviDevChar & 0x10) strcat (DevCharBuf, " sdi");
      if (DviDevChar & 0x20) strcat (DevCharBuf, " sqd");
      if (DviDevChar & 0x40) strcat (DevCharBuf, " spl");
      if (DviDevChar & 0x80) strcat (DevCharBuf, " opr");
      if (DviDevChar & 0x100) strcat (DevCharBuf, " rct");
      if (DviDevChar & 0x200) strcat (DevCharBuf, " qsvd");
      if (DviDevChar & 0x400) strcat (DevCharBuf, " qsvbl");
      if (DviDevChar & 0x800) strcat (DevCharBuf, " mpdev_sec");
      if (DviDevChar & 0x1000) strcat (DevCharBuf, " mpdev_mem");
      if (DviDevChar & 0x2000) strcat (DevCharBuf, " NETWORK");
      if (DviDevChar & 0x4000) strcat (DevCharBuf, " fod");
      if (DviDevChar & 0x8000) strcat (DevCharBuf, " dua");
      if (DviDevChar & 0x10000) strcat (DevCharBuf, " shr");
      if (DviDevChar & 0x20000) strcat (DevCharBuf, " gen");
      if (DviDevChar & 0x40000) strcat (DevCharBuf, " avl");
      if (DviDevChar & 0x80000) strcat (DevCharBuf, " MOUNTED");
      if (DviDevChar & 0x100000) strcat (DevCharBuf, " mbx");
      if (DviDevChar & 0x200000) strcat (DevCharBuf, " DMT");
      if (DviDevChar & 0x400000) strcat (DevCharBuf, " elg");
      if (DviDevChar & 0x800000) strcat (DevCharBuf, " all");
      if (DviDevChar & 0x1000000) strcat (DevCharBuf, " for");
      if (DviDevChar & 0x2000000) strcat (DevCharBuf, " swl");
      if (DviDevChar & 0x4000000) strcat (DevCharBuf, " idv");
      if (DviDevChar & 0x8000000) strcat (DevCharBuf, " odv");
      if (DviDevChar & 0x1000000) strcat (DevCharBuf, " rnd");
      if (DviDevChar & 0x2000000) strcat (DevCharBuf, " rtm");
      if (DviDevChar & 0x4000000) strcat (DevCharBuf, " rck");
      if (DviDevChar & 0x8000000) strcat (DevCharBuf, " wck");

      if (DviDevChar2 & 0x1) strcat (DevCharBuf, " clu");
      if (DviDevChar2 & 0x2) strcat (DevCharBuf, " det");
      if (DviDevChar2 & 0x4) strcat (DevCharBuf, " rtt");
      if (DviDevChar2 & 0x8) strcat (DevCharBuf, " cdp");
      if (DviDevChar2 & 0x10) strcat (DevCharBuf, " 2p");
      if (DviDevChar2 & 0x20) strcat (DevCharBuf, " mscp");
      if (DviDevChar2 & 0x40) strcat (DevCharBuf, " ssm");
      if (DviDevChar2 & 0x80) strcat (DevCharBuf, " srv");
      if (DviDevChar2 & 0x100) strcat (DevCharBuf, " red");
      if (DviDevChar2 & 0x200) strcat (DevCharBuf, " nnm");
      if (DviDevChar2 & 0x400) strcat (DevCharBuf, " wbc");
      if (DviDevChar2 & 0x800) strcat (DevCharBuf, " wtc");
      if (DviDevChar2 & 0x1000) strcat (DevCharBuf, " hoc");
      if (DviDevChar2 & 0x2000) strcat (DevCharBuf, " loc");
      if (DviDevChar2 & 0x4000) strcat (DevCharBuf, " dfs");
      if (DviDevChar2 & 0x8000) strcat (DevCharBuf, " dap");
      if (DviDevChar2 & 0x10000) strcat (DevCharBuf, " nlt");
      if (DviDevChar2 & 0x20000) strcat (DevCharBuf, " sex");
      if (DviDevChar2 & 0x40000) strcat (DevCharBuf, " shd");
      if (DviDevChar2 & 0x80000) strcat (DevCharBuf, " vrt");
      if (DviDevChar2 & 0x100000) strcat (DevCharBuf, " ldr");
      if (DviDevChar2 & 0x200000) strcat (DevCharBuf, " nolb");
      if (DviDevChar2 & 0x400000) strcat (DevCharBuf, " noclu");
      if (DviDevChar2 & 0x800000) strcat (DevCharBuf, " vmem");
      if (DviDevChar2 & 0x1000000) strcat (DevCharBuf, " scsi");
      if (DviDevChar2 & 0x2000000) strcat (DevCharBuf, " wlg");
      if (DviDevChar2 & 0x4000000) strcat (DevCharBuf, " nofe");
      if (DviDevChar2 & 0x8000000) strcat (DevCharBuf, " 0x8000000");
      if (DviDevChar2 & 0x1000000) strcat (DevCharBuf, " cramio");
      if (DviDevChar2 & 0x2000000) strcat (DevCharBuf, " dtn");
      if (DviDevChar2 & 0x4000000) strcat (DevCharBuf, " 0x40000000");
      if (DviDevChar2 & 0x8000000) strcat (DevCharBuf, " pool_mbr");

      FaoToEither (rqptr, DeviceFao,
                slen > 15 ? slen : 15,
                DevName+1,
                DviErrCnt,
                DviRefCnt,
                DviOpCnt,
                DevStsBuf+1,
                slen > 15 ? slen : 15,
                DviErrCnt ? "^^^^^" : "     ",
                DevCharBuf);

      if (DviDevClass == DC$_DISK)
      {
         if (DviVolNamLen)
         {
            DviVolNam[DviVolNamLen] = '\0';
            sizefp = (double)DviMaxBlock * 512.0 / 1073741824.0;
            freefp = (double)DviFreeBlocks * 512.0 / 1073741824.0;
            sprintf (SizeBuf, "%.2fGB", sizefp);
            sprintf (FreeBuf, "%.2fGB", freefp);

            FaoToEither (rqptr, DiskFao,
                      slen > 39 ? slen+20 : 39,
                      DviVolNam, FreeBuf, SizeBuf,
                      (int)(freefp * 100.0 / sizefp));
         }
      }
      else
      if (DviDevChar & DEV$V_NET)
      {
         if (DviLanSpeed)
            FaoToEither (rqptr, NetSpeedFao,
                      slen > 39 ? slen+20 : 39,
                      DviLanLinkStateValid ? "valid" : "invalid",
                      DviLanLinkUp ? "UP" : "DOWN",
                      DviLanSpeed);
         else
            FaoToEither (rqptr, NetNoSpeedFao,
                      slen > 39 ? slen+20 : 39,
                      DviLanLinkStateValid ? "valid" : "invalid",
                      DviLanLinkUp ? "UP" : "DOWN");
      }
   }

   FaoToEither (rqptr, "\n");
}

/*****************************************************************************/
/*
Provide process data.
*/

#define PSCAN$_GETJPI_BUFFER_SIZE 24

void sysPlusJpi (REQUEST_STRUCT *rqptr)

{
/* e.g. U-S-E-K- U+S-E-K- U^S-E-K- */
#define ASTFLG(bit,idx) { if (JpiAstEn & bit) if (JpiAstAct & bit) \
                          AstFlags[idx] = '^'; else AstFlags[idx] = '+'; \
                          else AstFlags[idx] = '-'; }

   static char  JpiHeader [] =
"PID      Process Name    Prior       I/O             CPU \
Page flts file State\n\
~~~~~~~~ Username ~~~~~~ Image !46*~\n";

   static char  ProcessFao [] =
"!8XL !15AZ !5<!2UL/!UL!> !9UL !3UL !2ZL:!2ZL:!2ZL.!2ZL !9UL !3UL% !AZ\n\\
         !15AZ !AZ\n";

   static ulong  GetJpiControlFlags = JPI$M_IGNORE_TARGET_STATUS;

   static ulong  JpiAstAct,
                 JpiAstEn,
                 JpiBufIo,
                 JpiCpuTim,
                 JpiDirIo,
                 JpiJobType,
                 JpiMode,
                 JpiPagFilCnt,
                 JpiPageFlts,
                 JpiPgFlQuota,
                 JpiPid,
                 JpiPri,
                 JpiPrib,
                 JpiState,
                 JpiSts,
                 JpiSts2;

   static char  JpiImagName [256],
                JpiNodeName [32],
                JpiPrcNam [16],
                JpiUserName [13];

   static struct
   {
      ushort  buf_len;
      ushort  item;
      uchar   *buf_addr;
      ushort  *short_ret_len;
   }
      JpiItems [] =
   {
      { sizeof(GetJpiControlFlags), JPI$_GETJPI_CONTROL_FLAGS,
        &GetJpiControlFlags, 0 },
      { sizeof(JpiAstAct), JPI$_ASTACT, &JpiAstAct, 0 },
      { sizeof(JpiAstEn),  JPI$_ASTEN,  &JpiAstEn, 0 },
      { sizeof(JpiBufIo), JPI$_BUFIO, &JpiBufIo, 0 },
      { sizeof(JpiCpuTim), JPI$_CPUTIM, &JpiCpuTim, 0 },
      { sizeof(JpiDirIo), JPI$_DIRIO, &JpiDirIo, 0 },
      { sizeof(JpiImagName), JPI$_IMAGNAME, &JpiImagName, 0 },
      { sizeof(JpiJobType), JPI$_JOBTYPE, &JpiJobType, 0 },
      { sizeof(JpiMode), JPI$_MODE, &JpiMode, 0 },
      { sizeof(JpiPageFlts), JPI$_PAGEFLTS, &JpiPageFlts, 0 },
      { sizeof(JpiPgFlQuota), JPI$_PGFLQUOTA, &JpiPgFlQuota, 0 },
      { sizeof(JpiPagFilCnt), JPI$_PAGFILCNT, &JpiPagFilCnt, 0 },
      { sizeof(JpiPrcNam), JPI$_PRCNAM, &JpiPrcNam, 0 },
      { sizeof(JpiPid), JPI$_PID, &JpiPid, 0 },
      { sizeof(JpiPri), JPI$_PRI, &JpiPri, 0 },
      { sizeof(JpiPrib), JPI$_PRIB, &JpiPrib, 0 },
      { sizeof(JpiState), JPI$_STATE, &JpiState, 0 },
      { sizeof(JpiSts), JPI$_STS, &JpiSts, 0 },
      { sizeof(JpiSts2), JPI$_STS, &JpiSts2, 0 },
      { sizeof(JpiUserName), JPI$_USERNAME, &JpiUserName, 0 },
      { 0,0,0,0 }
   },
   ScanItems [] =
   {
      { 0, PSCAN$_GETJPI_BUFFER_SIZE, 2048, 0},
      { 0,0,0,0 }
   };

   int  idx, status,
        IdentCount,
        ProcessCount,
        SetPrvStatus;
   ulong  *vecptr;
   ulong  ProcessContext;
   ulong  FaoVector [32];
   char  *cptr, *sptr;
   char  AstFlags [16],
         ProcFlags [512];
   IO_SB  IOsb;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD__OTHER))
      WatchThis (WATCHALL, WATCH_MOD__OTHER, "sysPlusJpi()");

   ProcessContext = 0;
   status = sys$process_scan (&ProcessContext, &ScanItems);
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "$PROCESS_SCAN() !&S\n", status);
      return;
   }

   if (VMSnok (SetPrvStatus = sys$setprv (1, &MailboxMask, 0, 0)))
      ErrorExitVmsStatus (SetPrvStatus, "sys$setprv()", FI_LI);

   ProcessCount = 0;

   FaoToEither (rqptr, JpiHeader);

   for (;;)
   {
      status = sys$getjpiw (EfnWait, &ProcessContext, 0,
                            &JpiItems, &IOsb, 0, 0);
      if (VMSok (status)) status = IOsb.Status;
      if (VMSnok (status))
      {
         if (status != SS$_NOMOREPROC)
            FaoToEither (rqptr, "$GETJPI() !&S\n", status);
         break;
      }

      JpiPrcNam[15] = '\0';
      for (cptr = JpiPrcNam; *cptr && *cptr != ' '; cptr++);
      *cptr = '\0';

      JpiUserName[12] = '\0';
      for (cptr = JpiUserName; *cptr && *cptr != ' '; cptr++);
      *cptr = '\0';

      ProcFlags[0] = '\0';

      switch (JpiState)
      {
         case  1 : strcat (ProcFlags, "COLPG"); break;
         case  2 : strcat (ProcFlags, "MWAIT"); break;
         case  3 : strcat (ProcFlags, "CEF"); break;
         case  4 : strcat (ProcFlags, "PFW"); break;
         case  5 : strcat (ProcFlags, "LEF"); break;
         case  6 : strcat (ProcFlags, "LEFO"); break;
         case  7 : strcat (ProcFlags, "HIB"); break;
         case  8 : strcat (ProcFlags, "HIBO"); break;
         case  9 : strcat (ProcFlags, "SUSP"); break;
         case 10 : strcat (ProcFlags, "SUSPO"); break;
         case 11 : strcat (ProcFlags, "FPG"); break;
         case 12 : strcat (ProcFlags, "COM"); break;
         case 13 : strcat (ProcFlags, "COMO"); break;
         case 14 : strcat (ProcFlags, "CUR"); break;
         default : strcat (ProcFlags, "?");
      }

      strcat (ProcFlags, "\n         ");

      switch (JpiMode)
      {
         case  0 : strcat (ProcFlags, "other"); break;
         case  1 : strcat (ProcFlags, "network"); break;
         case  2 : strcat (ProcFlags, "batch"); break;
         case  3 : strcat (ProcFlags, "interactive"); break;
         default : strcat (ProcFlags, "?");
      }

      switch (JpiJobType)
      {
         case 0 : strcat (ProcFlags, ":detached"); break;
         case 1 : strcat (ProcFlags, ":network"); break;
         case 2 : strcat (ProcFlags, ":batch"); break;
         case 3 : strcat (ProcFlags, ":local"); break;
         case 4 : strcat (ProcFlags, ":dialup"); break;
         case 5 : strcat (ProcFlags, ":remote"); break;
         default : strcat (ProcFlags, ":?");
      }

      /* AST flags */
      AstFlags[0] = ' ';
      AstFlags[1] = 'U'; ASTFLG(1,2)
      AstFlags[3] = 'S'; ASTFLG(2,4)
      AstFlags[5] = 'E'; ASTFLG(4,6)
      AstFlags[7] = 'K'; ASTFLG(8,8)
      AstFlags[9] = '\0';
      strcat (ProcFlags, AstFlags);

      if (JpiSts & 0x1) strcat (ProcFlags, " res");
      if (JpiSts & 0x2) strcat (ProcFlags, " delpen");
      if (JpiSts & 0x4) strcat (ProcFlags, " forcpen");
      if (JpiSts & 0x8) strcat (ProcFlags, " inquan");
      if (JpiSts & 0x10) strcat (ProcFlags, " pswapm");
      if (JpiSts & 0x20) strcat (ProcFlags, " respen");
      if (JpiSts & 0x40) strcat (ProcFlags, " ssfexc");
      if (JpiSts & 0x80) strcat (ProcFlags, " ssfexce");
      if (JpiSts & 0x100) strcat (ProcFlags, " ssfexcs");
      if (JpiSts & 0x200) strcat (ProcFlags, " ssfexcu");
      if (JpiSts & 0x400) strcat (ProcFlags, " ssrwait");
      if (JpiSts & 0x800) strcat (ProcFlags, " suspen");
      if (JpiSts & 0x2000) strcat (ProcFlags, " wall");
      if (JpiSts & 0x4000) strcat (ProcFlags, " batch");
      if (JpiSts & 0x8000) strcat (ProcFlags, " noacnt");
      if (JpiSts & 0x10000) strcat (ProcFlags, " nosuspend");
      if (JpiSts & 0x20000) strcat (ProcFlags, " astpen");
      if (JpiSts & 0x40000) strcat (ProcFlags, " phdres");
      if (JpiSts & 0x80000) strcat (ProcFlags, " hiber");
      if (JpiSts & 0x100000) strcat (ProcFlags, " login");
      if (JpiSts & 0x200000) strcat (ProcFlags, " netwrk");
      if (JpiSts & 0x400000) strcat (ProcFlags, " pwrast");
      if (JpiSts & 0x800000) strcat (ProcFlags, " nodelet");
      if (JpiSts & 0x1000000) strcat (ProcFlags, " disaws");
      if (JpiSts & 0x2000000) strcat (ProcFlags, " inter");
      if (JpiSts & 0x4000000) strcat (ProcFlags, " recover");
      if (JpiSts & 0x8000000) strcat (ProcFlags, " 0x8000000");
      if (JpiSts & 0x1000000) strcat (ProcFlags, " hardaff");
      if (JpiSts & 0x2000000) strcat (ProcFlags, " erdact");
      if (JpiSts & 0x4000000) strcat (ProcFlags, " softsusp");
      if (JpiSts & 0x8000000) strcat (ProcFlags, " preempted");

      strcat (ProcFlags, "\n        ");

      if (JpiSts2 & 0x1) strcat (ProcFlags, " qresched");
      if (JpiSts2 & 0x2) strcat (ProcFlags, " deplock");
      if (JpiSts2 & 0x3) strcat (ProcFlags, " fredlock");
      if (JpiSts2 & 0x4) strcat (ProcFlags, " phdlock");
      if (JpiSts2 & 0x10) strcat (ProcFlags, " tcb");
      if (JpiSts2 & 0x20) strcat (ProcFlags, " tbspend");
      if (JpiSts2 & 0x40) strcat (ProcFlags, " sslogenab");
      if (JpiSts2 & 0x80) strcat (ProcFlags, " sslogperm");
      if (JpiSts2 & 0x100) strcat (ProcFlags, " brkrunload");
      if (JpiSts2 & 0x8000) strcat (ProcFlags, " classschedperm");
      if (JpiSts2 & 0x10000) strcat (ProcFlags, " termnotify");
      if (JpiSts2 & 0x20000) strcat (ProcFlags, " bytlmloan");
      if (JpiSts2 & 0x40000) strcat (ProcFlags, " dispreempt");
      if (JpiSts2 & 0x80000) strcat (ProcFlags, " nounshelv");
      if (JpiSts2 & 0x100000) strcat (ProcFlags, " shelvres");
      if (JpiSts2 & 0x200000) strcat (ProcFlags, " classched");
      if (JpiSts2 & 0x400000) strcat (ProcFlags, " classupp");
      if (JpiSts2 & 0x800000) strcat (ProcFlags, " intbsstate");
      if (JpiSts2 & 0x1000000) strcat (ProcFlags, " windfall");
      if (JpiSts2 & 0x2000000) strcat (ProcFlags, " notify");
      if (JpiSts2 & 0x3C000000) strcat (ProcFlags, " sinthread");
      if (JpiSts2 & 0x40000000) strcat (ProcFlags, " rwast");
      if (JpiSts2 & 0x80000000) strcat (ProcFlags, " softsinthr");

      ProcessCount++;

      vecptr = FaoVector;

      *vecptr++ = JpiPid;
      *vecptr++ = JpiPrcNam;
      *vecptr++ = JpiPri;
      *vecptr++ = JpiPrib;
      *vecptr++ = JpiBufIo + JpiDirIo;
      *vecptr++ = JpiCpuTim / 8640000;             /* CPU day */
      *vecptr++ = (JpiCpuTim % 8640000) / 360000;  /* CPU hour */
      *vecptr++ = (JpiCpuTim % 360000) / 6000;     /* CPU minute */
      *vecptr++ = (JpiCpuTim % 6000 ) / 100;       /* CPU second */
      *vecptr++ = JpiCpuTim % 100;                 /* CPU 10 milliseconds */
      *vecptr++ = JpiPageFlts;
      if (JpiPagFilCnt)
         *vecptr++ = 100 - PercentOf32 (JpiPagFilCnt,JpiPgFlQuota);
      else
         *vecptr++ = 0;
      *vecptr++ = ProcFlags;
      *vecptr++ = JpiUserName;
      if (JpiImagName[0])
         *vecptr++ = JpiImagName;
      else
         *vecptr++ = "[none]";

      if (rqptr)
         status = FaolToNet (rqptr, ProcessFao, &FaoVector);
      else
      {
         char  Buffer [32767];
         status = FaolToBuffer (Buffer, sizeof(Buffer), NULL,
                                ProcessFao, &FaoVector);
         fputs (Buffer, stdout);
      }
      if (VMSnok (status)) FaoToEither (rqptr, "$FAO() !&S\n",  status);
   }

   if (VMSnok (SetPrvStatus = sys$setprv (0, &MailboxMask, 0, 0)))
      ErrorExitVmsStatus (SetPrvStatus, "sys$setprv()", FI_LI);
}

/*****************************************************************************/
/*
Provide resource consumption data.  This called with |rqptr| non-NULL to report
the data.  It is also called by HttpdTick() once a minute to update the
per-minute and buffered data.
*/

void sysPlusRmi (REQUEST_STRUCT *rqptr)

{
#define CPU_KERNEL   1
#define CPU_EXEC     2
#define CPU_SUPER    3
#define CPU_USER     4
#define CPU_IDLE     5
#define CPU_int_mps  6
#define CPU_INTSTK   7
#define CPU_MPSYNCH  8
#define CPU_total    9

#define NUM_STATE 9

#define STATE_CEF    1
#define STATE_COLPG  2
#define STATE_COM    3
#define STATE_COMO   4
#define STATE_CUR    5
#define STATE_FPG    6
#define STATE_HIB    7
#define STATE_HIBO   8
#define STATE_LEF    9
#define STATE_LEFO  10
#define STATE_SUSP  11
#define STATE_MWAIT 12
#define STATE_SUSPO 13
#define STATE_total 14
#define MEM_ERRS    15
#define RESMASK     16
#define ULONG_LAST  17

   /* CPU modes ([0]..[6]) by minutes ([1]..) plus current read ([0]) */
   static  uint64  RmiCpu [NUM_MINS+2][NUM_STATE+1];

   /* various unsigned longs by minutes ([1]..) plus current read [0] */
   static ulong  RmiUlong [NUM_MINS+2][ULONG_LAST+1];

   static VMS_ITEM_LIST3  RmiItem [] =
   {
     { sizeof(RmiCpu[0][CPU_EXEC]),   RMI$_CPUEXEC, &RmiCpu[0][CPU_EXEC], 0 },
     { sizeof(RmiCpu[0][CPU_IDLE]),   RMI$_CPUIDLE, &RmiCpu[0][CPU_IDLE], 0 },
     { sizeof(RmiCpu[0][CPU_INTSTK]), RMI$_CPUINTSTK, &RmiCpu[0][CPU_INTSTK], 0 },
     { sizeof(RmiCpu[0][CPU_KERNEL]), RMI$_CPUKERNEL, &RmiCpu[0][CPU_KERNEL], 0 },
     { sizeof(RmiCpu[0][CPU_MPSYNCH]), RMI$_CPUMPSYNCH, &RmiCpu[0][CPU_MPSYNCH], 0 },
     { sizeof(RmiCpu[0][CPU_SUPER]),  RMI$_CPUSUPER, &RmiCpu[0][CPU_SUPER], 0 },
     { sizeof(RmiCpu[0][CPU_USER]),   RMI$_CPUUSER, &RmiCpu[0][CPU_USER], 0 },
     { sizeof(RmiUlong[0][MEM_ERRS]), RMI$_MEMERRS, &RmiUlong[0][MEM_ERRS], 0 },
     { sizeof(RmiUlong[0][RESMASK]),  RMI$_RESMASK, &RmiUlong[0][RESMASK], 0 },
     { sizeof(RmiUlong[0][STATE_CEF]),  RMI$_CEF, &RmiUlong[0][STATE_CEF], 0 },
     { sizeof(RmiUlong[0][STATE_COLPG]), RMI$_COLPG, &RmiUlong[0][STATE_COLPG], 0 },
     { sizeof(RmiUlong[0][STATE_COM]),  RMI$_COM, &RmiUlong[0][STATE_COM], 0 },
     { sizeof(RmiUlong[0][STATE_COMO]), RMI$_COMO, &RmiUlong[0][STATE_COMO], 0 },
     { sizeof(RmiUlong[0][STATE_CUR]),  RMI$_CUR, &RmiUlong[0][STATE_CUR], 0 },
     { sizeof(RmiUlong[0][STATE_FPG]),  RMI$_FPG, &RmiUlong[0][STATE_FPG], 0 },
     { sizeof(RmiUlong[0][STATE_HIB]),  RMI$_HIB, &RmiUlong[0][STATE_HIB], 0 },
     { sizeof(RmiUlong[0][STATE_HIBO]), RMI$_HIBO, &RmiUlong[0][STATE_HIBO], 0 },
     { sizeof(RmiUlong[0][STATE_LEF]),  RMI$_LEF, &RmiUlong[0][STATE_LEF], 0 },
     { sizeof(RmiUlong[0][STATE_LEFO]), RMI$_LEFO, &RmiUlong[0][STATE_LEFO], 0 },
     { sizeof(RmiUlong[0][STATE_MWAIT]), RMI$_MWAIT, &RmiUlong[0][STATE_MWAIT], 0 },
     { sizeof(RmiUlong[0][STATE_SUSP]), RMI$_SUSP, &RmiUlong[0][STATE_SUSP], 0 },
     { sizeof(RmiUlong[0][STATE_SUSPO]), RMI$_SUSPO, &RmiUlong[0][STATE_SUSPO], 0 },
     { 0,0,0,0 }
   };

   int  min, mode, status;
   ulong  cpuTotal,
          modeTotal;
   ulong  PercentCpu [NUM_STATE+1];
   char  when [16];
   IO_SB  IOsb;

   /*********/
   /* begin */
   /*********/

   if (rqptr == (REQUEST_STRUCT*)-1)
   {
      /*******************/
      /* per-minute data */
      /*******************/

      /* move all values into one minute further in the past */
      for (min = NUM_MINS+1; min > 0; min--)
      {
         memcpy (RmiCpu[min], RmiCpu[min-1], sizeof(RmiCpu[min]));
         memcpy (RmiUlong[min], RmiUlong[min-1], sizeof(RmiUlong[min]));
      }
   }

   /* collect System Performance Information */
   status = sys$getrmi (EfnWait, 0, 0, &RmiItem, &IOsb, 0, 0);
   if (VMSok (status)) sys$synch (EfnWait, &IOsb);
   if (VMSok (status)) status = IOsb.Status;
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "$GETRMI() !&S\n",  status);
      return;
   }

   sysPlusRmiMemErrs = RmiUlong[0][MEM_ERRS];

   RmiCpu[0][CPU_total] = RmiCpu[0][CPU_INTSTK] +
                          RmiCpu[0][CPU_MPSYNCH] +
                          RmiCpu[0][CPU_KERNEL] +
                          RmiCpu[0][CPU_EXEC] +
                          RmiCpu[0][CPU_SUPER] +
                          RmiCpu[0][CPU_USER] +
                          RmiCpu[0][CPU_IDLE];

   RmiCpu[0][CPU_int_mps] = RmiCpu[0][CPU_INTSTK] +
                            RmiCpu[0][CPU_MPSYNCH];

   RmiUlong[0][STATE_total] = RmiUlong[0][STATE_CEF] +
                              RmiUlong[0][STATE_COLPG] +
                              RmiUlong[0][STATE_COM] +
                              RmiUlong[0][STATE_COMO] +
                              RmiUlong[0][STATE_CUR] +
                              RmiUlong[0][STATE_FPG] +
                              RmiUlong[0][STATE_HIB] +
                              RmiUlong[0][STATE_HIBO] +
                              RmiUlong[0][STATE_LEF] +
                              RmiUlong[0][STATE_LEFO] +
                              RmiUlong[0][STATE_MWAIT] +
                              RmiUlong[0][STATE_SUSP] +
                              RmiUlong[0][STATE_SUSPO];

   if (rqptr == (REQUEST_STRUCT*)-1) return;

   /**********/
   /* report */
   /**********/

   FaoToEither (rqptr,
"CPU%     Kern  Exec  Supr  User  Idle  Othr\n\
         ~~~~  ~~~~  ~~~~  ~~~~  ~~~~  ~~~~\n");

   for (min = 0; min <= NUM_MINS; min++)
   {
      if (!RmiCpu[min+1][CPU_total]) break;

      if (min)
         sprintf (when, "%d min", min);
      else
         strcpy (when, "now");

      for (mode = CPU_KERNEL; mode <= CPU_int_mps; mode++)
      {
         if (RmiCpu[min+1][CPU_total])
            cpuTotal = (ulong)(RmiCpu[min][CPU_total] -
                               RmiCpu[min+1][CPU_total]);
         else
            cpuTotal = 0;

         if (RmiCpu[min+1][mode])
            modeTotal = (ulong)(RmiCpu[min][mode] -
                                RmiCpu[min+1][mode]);
         else
            modeTotal = 0;

         PercentCpu[mode] = PercentOf32 (modeTotal, cpuTotal);
      }

      FaoToEither (rqptr,
"!6&>AZ    !3UL   !3UL   !3UL   !3UL   !3UL   !3UL\n",
                when,
                PercentCpu[CPU_KERNEL], PercentCpu[CPU_EXEC],
                PercentCpu[CPU_SUPER], PercentCpu[CPU_USER],
                PercentCpu[CPU_IDLE], PercentCpu[CPU_int_mps]);
   }

   FaoToEither (rqptr,
"\nStates    CEF COLPG   COM  COMO   CUR   FPG   HIB  HIBO   \
LEF  LEFO MWAIT resource  SUSP SUSPO Total\n\
        ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ ~~~~~ \
~~~~~ ~~~~~ ~~~~~~~~~~~~~~ ~~~~~ ~~~~~ ~~~~~\n");

   for (min = 0; min <= NUM_MINS; min++)
   {
      if (!RmiUlong[min+1][STATE_total]) break;

      if (min)
         sprintf (when, "%d min", min);
      else
         strcpy (when, "now");

      FaoToEither (rqptr,
"!6&>AZ  !5UL !5UL !5UL !5UL !5UL !5UL !5UL !5UL \
!5UL !5UL !5UL !8XL !5UL !5UL !5UL\n",
                when,
                RmiUlong[min][STATE_CEF],
                RmiUlong[min][STATE_COLPG],
                RmiUlong[min][STATE_COM],
                RmiUlong[min][STATE_COMO],
                RmiUlong[min][STATE_CUR],
                RmiUlong[min][STATE_FPG],
                RmiUlong[min][STATE_HIB],
                RmiUlong[min][STATE_HIBO],
                RmiUlong[min][STATE_LEF],
                RmiUlong[min][STATE_LEFO],
                RmiUlong[min][STATE_MWAIT],
                RmiUlong[min][RESMASK],
                RmiUlong[min][STATE_SUSP],
                RmiUlong[min][STATE_SUSPO],
                RmiUlong[min][STATE_total]);
   }

   FaoToEither (rqptr, "\n");
}

/*****************************************************************************/
/*
Provide Mass Storage Control Protocol (MSCP) data.
*/

void sysPlusMscp (REQUEST_STRUCT *rqptr)

{
#define MSCP_ALL 0

   static BOOL  nope;
   static int  status;
   static ulong  MscpData [35];

   /* by minutes ([1]..) plus current read ([0]) */
   static ulong  MscpBufAvail [NUM_MINS+2],
                 MscpBufWait [NUM_MINS+2],
                 MscpOpCount [NUM_MINS+2],
                 MscpRead [NUM_MINS+2],
                 MscpSplitXfer [NUM_MINS+2],
                 MscpVcFail [NUM_MINS+2],
                 MscpWrite [NUM_MINS+2];

   static VMS_ITEM_LIST3  RmiItem [] =
   {
#if MSCP_ALL
       { sizeof(MscpData), RMI$_MSCP_ALL, &MscpData, 0 },
#else
       { sizeof(MscpData), RMI$_MSCP_EVERYTHING, &MscpData, 0 },
#endif
       {0,0,0,0}
   };

   int  min;
   ulong  ThisMscpBufAvail,
          ThisMscpBufWait,
          ThisMscpOpCount,
          ThisMscpRead,
          ThisMscpSplitXfer,
          ThisMscpVcFail,
          ThisMscpWrite;
   char  when [16];
   IO_SB  IOsb;

   /*********/
   /* begin */
   /*********/

   if (nope)
   {
      FaoToEither (rqptr, "MSCP data not available !&S\n\n", status);
      return;
   }

   if (rqptr == (REQUEST_STRUCT*)-1)
   {
      /*******************/
      /* per-minute data */
      /*******************/

      /* move all values into one minute into the past */
      for (min = NUM_MINS+1; min > 0; min--)
      {
         MscpBufAvail[min] = MscpBufAvail[min-1];
         MscpOpCount[min] = MscpOpCount[min-1];
         MscpRead[min] = MscpRead[min-1];
         MscpWrite[min] = MscpWrite[min-1];
         MscpVcFail[min] = MscpVcFail[min-1];
         MscpSplitXfer[min] = MscpSplitXfer[min-1];
         MscpBufWait[min] = MscpBufWait[min-1];
      }
   }

   status = sys$getrmi (EfnWait, 0, 0, &RmiItem, &IOsb, 0, 0);
   if (VMSok (status)) sys$synch (EfnWait, &IOsb);
   if (VMSok (status)) status = IOsb.Status;
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "MSCP data not available !&S\n\n",  status);
      nope = true;
      return;
   }

#if MSCP_ALL
   MscpBufAvail[0] = 0;
   MscpOpCount[0] = MscpData[0];
   MscpVcFail[0] = 0;
   MscpRead[0] = MscpData[1];
   MscpWrite[0] = MscpData[2];
   MscpSplitXfer[0] = MscpData[3];
   MscpBufWait[0] = MscpData[4];
#else
   MscpBufAvail[0] = MscpData[0];
   MscpOpCount[0] = MscpData[21];
   MscpVcFail[0] = MscpData[22];
   MscpRead[0] = MscpData[23];
   MscpWrite[0] = MscpData[24];
   MscpSplitXfer[0] = MscpData[25];
   MscpBufWait[0] = MscpData[26];
#endif

   if (rqptr == (REQUEST_STRUCT*)-1) return;

   /***********/
   /* report */
   /**********/

#if MSCP_ALL
   FaoToEither (rqptr, "\
MSCP          Op Cnt          Read         Write  \
       Split          Wait\n\
        ~~~~~~~~~~~~  ~~~~~~~~~~~~  ~~~~~~~~~~~~  \
~~~~~~~~~~~~  ~~~~~~~~~~~~\n");
#else
   FaoToEither (rqptr, "\
MSCP         Buf Avl        Op Cnt          Read         Write  \
     VC Fail         Split          Wait\n\
        ~~~~~~~~~~~~  ~~~~~~~~~~~~  ~~~~~~~~~~~~  ~~~~~~~~~~~~  \
~~~~~~~~~~~~  ~~~~~~~~~~~~  ~~~~~~~~~~~~\n");
#endif

   for (min = 0; min <= NUM_MINS; min++)
   {
      if (min)
      {
         if (!MscpOpCount[min+1]) continue;
         ThisMscpBufAvail = MscpBufAvail[min];
         ThisMscpOpCount = MscpOpCount[min] - MscpOpCount[min+1];
         ThisMscpRead = MscpRead[min] - MscpRead[min+1];
         ThisMscpWrite = MscpWrite[min] - MscpWrite[min+1];
         ThisMscpVcFail = MscpVcFail[min] - MscpVcFail[min+1];
         ThisMscpSplitXfer = MscpSplitXfer[min] - MscpSplitXfer[min+1];
         ThisMscpBufWait = MscpBufWait[min] - MscpBufWait[min+1];
         sprintf (when, "%d min", min);
      }
      else
      {
         ThisMscpBufAvail = MscpBufAvail[0];
         ThisMscpOpCount = MscpOpCount[0];
         ThisMscpRead = MscpRead[0];
         ThisMscpWrite = MscpWrite[0];
         ThisMscpVcFail = MscpVcFail[0];
         ThisMscpSplitXfer = MscpSplitXfer[0];
         ThisMscpBufWait = MscpBufWait[0];
         strcpy (when, "total");
      }

#if MSCP_ALL
      FaoToEither (rqptr,
"!6&>AZ  !12UL  !12UL  !12UL  !12UL  !12UL\n",
                   when,
                   ThisMscpOpCount,
                   ThisMscpRead, ThisMscpWrite,
                   ThisMscpSplitXfer, ThisMscpBufWait);
#else
      FaoToEither (rqptr,
"!6&>AZ  !12UL  !12UL  !12UL  !12UL  !12UL  !12UL  !12UL\n",
                   when,
                   ThisMscpBufAvail, ThisMscpOpCount,
                   ThisMscpRead, ThisMscpWrite,
                   ThisMscpVcFail, ThisMscpSplitXfer, ThisMscpBufWait);
#endif
   }

   FaoToEither (rqptr, "\n");
}

/*****************************************************************************/
/*
This function uses undocumented sense-mode functionality to load counters from
the network interface (commonly ethernet device).  Multiple devices are
supported using a multi-valued logical name WASD_SYSPLUS_NI and the frame-rate
and byte-rate and soft/hard error-rate statistics are accumlated to represent
total system data.

Essential concepts have come from "EMON: moniteur ethernet (V2.1-2) Gerard
Guillaume" and found in DECUSLIB freeware, and from some peeks at the T4 source
code.  The implementation is mine.
*/

void sysPlusNet (REQUEST_STRUCT *rqptr)

{
#define NI_DEVICE_MAX 16
#define NI_DEVNAM_MAX 31
/* the ACCUM index is used to accumulate the current device counters */
#define ACCUM (NUM_MINS+2)

   static int  NetIntCount,
               IoClrCount;
   static ushort  NetIntChan [NI_DEVICE_MAX];
   static ulong  DcSCOM = 32,  /* DC$_SCOM */
                 DtNI = 13;    /* DT$_NI */
   static uint64  NetIntBlocksRx64   [NI_DEVICE_MAX][NUM_MINS+3],
                  NetIntBlocksTx64   [NI_DEVICE_MAX][NUM_MINS+3],
                  NetIntBytesRx64    [NI_DEVICE_MAX][NUM_MINS+3],
                  NetIntBytesTx64    [NI_DEVICE_MAX][NUM_MINS+3],
                  NetIntErrorsHard64 [NI_DEVICE_MAX][NUM_MINS+3],
                  NetIntErrorsSoft64 [NI_DEVICE_MAX][NUM_MINS+3];
   static long  DeviceCount = -1,
                DviUnit,
                LnmIndex = -1,
                LnmAttributes;
   static ushort  LogValueLen;
   static char  under [] = "~~~~~~~~~~~~~~~~~~~~";
   static char  LogValue [64];
   static char  NetIntDevName [NI_DEVICE_MAX][NI_DEVNAM_MAX+1];
   static struct {
      short  BufferLength;
      short  ItemCode;
      void  *BufferPtr;
      void  *LengthPtr;
   }
   LnmItems [] =
   {
      { sizeof(LnmIndex), LNM$_INDEX, &LnmIndex, 0 },
      { sizeof(LnmAttributes), LNM$_ATTRIBUTES, &LnmAttributes, 0 },
      { sizeof(LogValue)-1, LNM$_STRING, &LogValue, &LogValueLen },
      { 0,0,0,0 }
   },
   DevScanItems [] =
   {
      { sizeof(DcSCOM), DVS$_DEVCLASS, &DcSCOM, 0 },
      { 0,0,0,0 }
   },
   GetDviItems [] =
   {
      { sizeof(DviUnit), DVI$_UNIT, &DviUnit, 0 },
      { 0,0,0,0 }
   };
   static $DESCRIPTOR (NetIntDsc, "");
   static $DESCRIPTOR (LogNameDsc, WASD_SYSPLUS_NI);
   static $DESCRIPTOR (LnmFileDevDsc, "LNM$FILE_DEV");

   int  ecnt, min, status;
   ushort  pword,
           retlen;
   ulong  LnmCount;
   uint64  value64,
           BlocksRx64,
           BlocksTx64,
           BytesRx64,
           BytesTx64,
           DevScanContext64,
           ErrorsHard64,
           ErrorsSoft64;
   char  *vptr;
   char  byrx [16],
         bytx [16],
         when [16],
         DevScanBuffer [64],
         CountBuffer [512];
   IO_SB  IOsb;
   $DESCRIPTOR (CountDsc, CountBuffer);
   $DESCRIPTOR (DevScanDsc, DevScanBuffer);

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD__OTHER))
      WatchThis (WATCHALL, WATCH_MOD__OTHER, "sysPlusNet()");

   if (LnmIndex < 0)
   {
      /* first call, check for logical name defined network devices */
      for (LnmIndex = 0; LnmIndex < NI_DEVICE_MAX; LnmIndex++)
      {
         status = sys$trnlnm (0, &LnmFileDevDsc, &LogNameDsc, 0, &LnmItems);
         if (VMSnok (status) || !(LnmAttributes & LNM$M_EXISTS)) break;
         LogValue[LogValueLen] = '\0';

         NetIntDsc.dsc$a_pointer = LogValue;
         NetIntDsc.dsc$w_length = LogValueLen;

         status = sys$assign (&NetIntDsc, &NetIntChan[LnmIndex], 0, 0);
         if (VMSnok (status))
         {
            FaoToEither (rqptr, "$ASSIGN() !AZ !&S\n", LogValue, status);
            continue;
         }

         strncpy (NetIntDevName[NetIntCount], LogValue, NI_DEVNAM_MAX);
         NetIntDevName[NetIntCount][NI_DEVNAM_MAX] = '\0';
         NetIntCount++;
      }
   }

   if (!NetIntCount && DeviceCount < 0)
   {
      /* first call */
      DeviceCount = 0;

      /* scan system for network devices */
      DevScanContext64 = 0;
      while (NetIntCount < NI_DEVICE_MAX)
      {
         status = sys$device_scan (&DevScanDsc, &retlen, 0,
                                   &DevScanItems, &DevScanContext64);
         if (VMSnok (status))
         {
            if (status == SS$_NOMOREDEV || status == SS$_NOSUCHDEV) break;
            if (VMSnok (status))
               FaoToEither (rqptr, "$DEVICE_SCAN() !&S\n", status);
         }

         status = sys$getdviw (0, 0, &DevScanDsc, &GetDviItems, &IOsb, 
                               0, 0, 0, 0);
         if (VMSok (status)) status = IOsb.Status;
         if (VMSnok (status)) FaoToEither (rqptr, "$GETDVIW() !&S\n", status);

         /* if not a template device then continue */
         if (DviUnit != 0) continue;

         DevScanBuffer[retlen] = '\0';

         /* RMDRIVER gives %SYSTEM-F-SYSVERDIF */
         if (!strcmp (DevScanBuffer, "_RMA0:")) continue;

         status = sys$assign (&DevScanDsc, &NetIntChan[DeviceCount++], 0, 0);
         if (VMSnok (status)) FaoToEither (rqptr, "$ASSIGN() !&S\n", status);

         strncpy (NetIntDevName[NetIntCount], DevScanBuffer+1, NI_DEVNAM_MAX);
         NetIntDevName[NetIntCount][NI_DEVNAM_MAX] = '\0';
         NetIntCount++;
      }
   }

   /* if no devices then just return from here */
   if (!NetIntCount) return;

   if (rqptr == (REQUEST_STRUCT*)-1)
   {
      /* once a minute store previous minute's accumulated data */
      for (ecnt = 0; ecnt < NetIntCount; ecnt++)
      {
         for (min = NUM_MINS+1; min > 0; min--)
         {
            NetIntBlocksRx64[ecnt][min] = NetIntBlocksRx64[ecnt][min-1];
            NetIntBlocksTx64[ecnt][min] = NetIntBlocksTx64[ecnt][min-1];
            NetIntBytesRx64[ecnt][min] = NetIntBytesRx64[ecnt][min-1];
            NetIntBytesTx64[ecnt][min] = NetIntBytesTx64[ecnt][min-1];
            NetIntErrorsHard64[ecnt][min] = NetIntErrorsHard64[ecnt][min-1];
            NetIntErrorsSoft64[ecnt][min] = NetIntErrorsSoft64[ecnt][min-1];
         }
      }
   }

   /****************/
   /* collect data */
   /****************/

   IoClrCount = 0;

   /* accumulate counts from each device */
   for (ecnt = 0; ecnt < NetIntCount; ecnt++)
   {
      NetIntBlocksRx64[ecnt][ACCUM] = 0;
      NetIntBlocksTx64[ecnt][ACCUM] = 0;
      NetIntBytesRx64[ecnt][ACCUM] = 0;
      NetIntBytesTx64[ecnt][ACCUM] = 0;
      NetIntErrorsHard64[ecnt][ACCUM] = 0;
      NetIntErrorsSoft64[ecnt][ACCUM] = 0;
      memset (CountBuffer, 0, sizeof(CountBuffer));

      status = sys$qiow (0, NetIntChan[ecnt],
                         IO$_SENSEMODE | IO$M_RD_COUNT | IoClrCount |
#define IO$M_RD_64COUNT 0x4000
                         IO$M_RD_64COUNT | 
                         IO$M_CTRL,
                         &IOsb, 0, 0,
                         0, &CountDsc, 0, 0, 0, 0);

      if (VMSok (status)) status = IOsb.Status;
      if (VMSnok (status)) FaoToEither (rqptr, "$QIOW() !AZ !&S\n",
                                        NetIntDevName[ecnt], status);

      vptr = CountBuffer;
      while (vptr < CountBuffer + IOsb.Count)
      {
         pword = *(ushort*)vptr;
         vptr += 2;

         /* end of list */
         if (!pword) break;

         /* MSB should be set! */
         if (!(pword & 0x8000)) break;

         value64 = 0;
         if ((pword & 0x0fff) < 200)
         {
            /* quadword value (item number less than 200) */
            value64 = *(INT64PTR)vptr;
            vptr += 8;
         }
         else
         if ((pword & 0x6000) == 0x6000)
         {
            /* longword value */
            value64 = *(ULONGPTR)vptr;
            vptr += 4;
         } 
         else
         if ((pword & 0x6000) == 0x4000)
         {
            /* word value */
            value64 = *(USHORTPTR)vptr;
            vptr += 2;
         } 
         else
         if ((pword & 0x6000) == 0x2000)
         {
            /* byte value */
            value64 = *(uchar*)vptr;
            vptr++;
         } 

         if (pword & 0x1000)
         {
            /* hw map (?) */
            value64 = *(ushort*)vptr;
            vptr += 2;
            continue;
         } 

         switch (pword & 0x0fff)
         {
            /* these look suspiciously like "LANCP SHOW DEVICE /COUNT"! */

            case 1 :
                 /* seconds since last zeroed */
                 break;

            case 2 :
            case 6 :
                 NetIntBytesRx64[ecnt][ACCUM] += value64;
                 break;

            case 3 :
            case 7 :
                 NetIntBytesTx64[ecnt][ACCUM] += value64;
                 break;

            case 4 :
            case 8 :
                 NetIntBlocksRx64[ecnt][ACCUM] += value64;
                 break;

            case 5 :
            case 9 :
                 NetIntBlocksTx64[ecnt][ACCUM] += value64;
                 break;

            case 12 :
            case 13 :
            case 14 :
            case 15 :
            case 16 :
            case 17 :
            case 18 :
            case 19 :
            case 30 :
            case 21 :
            case 22 :
            case 23 :
            case 24 :
            case 27 :
            case 28 :
            case 29 :
                 NetIntErrorsSoft64[ecnt][ACCUM] += value64;
                 break;

            case 25 :
            case 26 :
            case 33 :
            case 34 :
                 NetIntErrorsHard64[ecnt][ACCUM] += value64;
                 break;

            /* more "traditional" counters */

            case 1000 /* NMA$C_CTLIN_BRC bytes received */ :
            case 1002 /* NMA$C_CTLIN_MBY multicast bytes received */ :
                 NetIntBytesRx64[ecnt][ACCUM] += value64;
                 break;

            case 1001 /* NMA$C_CTLIN_BSN bytes sent */ :
                 NetIntBytesTx64[ecnt][ACCUM] += value64;
                 break;

            case 1010 /* NMA$C_CTLIN_DBR data blocks received */ :
            case 1012 /* NMA$C_CTLIN_MBL multicast blocks received */ :
                 NetIntBlocksRx64[ecnt][ACCUM] += value64;
                 break;

            case 1011 /* NMA$C_CTLIN_DBS data blocks sent */ :
                 NetIntBlocksTx64[ecnt][ACCUM] += value64;
                 break;

            case 1013 /* NMA$C_CTLIN_BID */ :
            case 1014 /* NMA$C_CTLIN_BS1 */ :
            case 1015 /* NMA$C_CTLIN_BSM */ :
            case 1040 /* NMA$C_CTLIN_RBE */ :
            case 1041 /* NMA$C_CTLIN_LBE */ :
            case 1064 /* NMA$C_CTLIN_OVR */ :
            case 1066 /* NMA$C_CTLIN_UBU */ :

                 NetIntErrorsSoft64[ecnt][ACCUM] += value64;
                 break;

            case 1060 /* NMA$C_CTLIN_SFL */ :
            case 1061 /* NMA$C_CTLIN_CDC */ :
            case 1063 /* NMA$C_CTLIN_UFD */ :
            case 1062 /* NMA$C_CTLIN_RFL */ :
            case 1065 /* NMA$C_CTLIN_SBU */ :

                 NetIntErrorsHard64[ecnt][ACCUM] += value64;
                 break;

            default :
         }
      }

      NetIntBlocksRx64[ecnt][0] = NetIntBlocksRx64[ecnt][ACCUM];
      NetIntBlocksTx64[ecnt][0] = NetIntBlocksTx64[ecnt][ACCUM];
      NetIntBytesRx64[ecnt][0] = NetIntBytesRx64[ecnt][ACCUM];
      NetIntBytesTx64[ecnt][0] = NetIntBytesTx64[ecnt][ACCUM];
      NetIntErrorsHard64[ecnt][0] = NetIntErrorsHard64[ecnt][ACCUM];
      NetIntErrorsSoft64[ecnt][0] = NetIntErrorsSoft64[ecnt][ACCUM];
   }

   if (rqptr == (REQUEST_STRUCT*)-1) return;

   /**********/
   /* report */
   /**********/

   for (ecnt = 0; ecnt < NetIntCount; ecnt++)
   {
      status = FaoToEither (rqptr,
"!AZ\
!8AZ!13&>AZ  !13&>AZ  !18&>AZ !8&>AZ  !18&>AZ !8&>AZ  !6&>AZ  !6&>AZ\n\
!6AZ  !13AZ  !13AZ  !18AZ !8AZ  !18AZ !8AZ  !6AZ  !6AZ\n",
               ecnt ? "\n" : "", NetIntDevName[ecnt],
"Packet Rx", "Packet Tx", "Bytes Rx", "", "Bytes Tx", "", "Hard", "Soft",
"", under, under, under, "", under, "", under, under);

      if (VMSnok (status)) FaoToEither (rqptr, "$FAO() !&S\n", status);

      for (min = 0; min <= NUM_MINS; min++)
      {
         if (min)
         {
            if (!NetIntBlocksRx64[ecnt][min+1]) continue;

            BlocksRx64 = NetIntBlocksRx64[ecnt][min] -
                         NetIntBlocksRx64[ecnt][min+1];
            BlocksTx64 = NetIntBlocksTx64[ecnt][min] -
                         NetIntBlocksTx64[ecnt][min+1];
            BytesRx64 = NetIntBytesRx64[ecnt][min] -
                        NetIntBytesRx64[ecnt][min+1];
            BytesTx64 = NetIntBytesTx64[ecnt][min] -
                        NetIntBytesTx64[ecnt][min+1];
            ErrorsHard64 = NetIntErrorsHard64[ecnt][min] -
                           NetIntErrorsHard64[ecnt][min+1];
            ErrorsSoft64 = NetIntErrorsSoft64[ecnt][min] -
                           NetIntErrorsSoft64[ecnt][min+1];
            sprintf (when, "%d min", min);
         }
         else
         {
            BlocksRx64 = NetIntBlocksRx64[ecnt][ACCUM];
            BlocksTx64 = NetIntBlocksTx64[ecnt][ACCUM];
            BytesRx64 = NetIntBytesRx64[ecnt][ACCUM];
            BytesTx64 = NetIntBytesTx64[ecnt][ACCUM];
            ErrorsHard64 = NetIntErrorsHard64[ecnt][ACCUM];
            ErrorsSoft64 = NetIntErrorsSoft64[ecnt][ACCUM];
            strcpy (when, "total");
         }

         status = FaoToEither (rqptr,
"!6&>AZ  !13@SQ  !13@SQ  !18@SQ !8AZ  !18@SQ !8AZ  !6@SQ  !6@SQ\n",
                               when,
                               &BlocksRx64, &BlocksTx64,
                               &BytesRx64, sysPlusNetVal(BytesRx64,byrx),
                               &BytesTx64, sysPlusNetVal(BytesTx64,bytx),
                               &ErrorsHard64, &ErrorsSoft64);
      }
   }

   FaoToEither (rqptr, "\n");
}

/*****************************************************************************/
/*
64 bit accumulator to real number Tbytes, Gbytes, Mbytes or kbytes.
*/

char* sysPlusNetVal
(
int64 bytes64,
char *buf
)
{
#define AT_ONCE_MAX 2

   char  tmp [32];
   float  qfloat;

   /*********/
   /* begin */
   /*********/

   qfloat = (float)bytes64;
   if (qfloat >= 1024.0 * 1024.0 * 1024.0 * 1024.0)
      sprintf (tmp, "%3.2fTB", qfloat / (1024.0 * 1024.0 * 1024.0 * 1024.0));
   else
   if (qfloat >= 1024.0 * 1024.0 * 1024.0)
      sprintf (tmp, "%3.2fGB", qfloat / (1024.0 * 1024.0 * 1024.0));
   else
   if (qfloat >= 1024.0 * 1024.0)
      sprintf (tmp, "%3.2fMB", qfloat / (1024.0 * 1024.0));
   else
   if (qfloat >= 1024.0)
      sprintf (tmp, "%3.2fkB", qfloat / 1024.0);
   else
      tmp[0] = '\0';
   /* right justify */
   sprintf (buf, "%8.8s", tmp);
   return (buf);
}

/*****************************************************************************/
/*
Provide cluster resource consumption data.  This called with |rqptr| non-NULL
to report the data.  It is also called by HttpdTick() once a minute to update
the per-minute and buffered data.
*/

void sysPlusScs (REQUEST_STRUCT *rqptr)

{
   static ulong  ScsRead [1+(SCS_NODES_MAX*14)];
   static ulong  ScsData [NUM_MINS+2][SCS_NODES_MAX][14];
   static VMS_ITEM_LIST3  RmiItem [] =
   {
      { sizeof(ScsRead), RMI$_SCS, &ScsRead, 0 },
      {0,0,0,0}
   };

   /* hmmm; on VAX V7.3 this gets clobbered if placed before ScsRead[] !! */
   static int  status;

   int  cnt, min, node;
   ulong DgramDisc,
         DgramRcvd,
         DgramSent,
         KbyteMap,
         KbyteSent,
         KbyteRcvd,
         MsgSent,
         MsgRcvd,
         QcrCnt,
         QbdtCnt,
         ReqDats,
         SendDats;
   ulong  *data;
   char *cptr, *sptr;
   char  name [16],
         when [16];
   IO_SB  IOsb;

   /*********/
   /* begin */
   /*********/

   if (status)
   {
      FaoToEither (rqptr, "SCS data not available !&S\n\n", status);
      return;
   }

   if (rqptr == (REQUEST_STRUCT*)-1)
   {
      /*******************/
      /* per-minute data */
      /*******************/

      /* move all values into one minute into the past */
      for (min = NUM_MINS+1; min > 0; min--)
         /* first node is always this one */
         for (node = 1; node < SCS_NODES_MAX; node++)
            if (ScsData[min-1][node][0])
               memcpy (&ScsData[min][node],
                       &ScsData[min-1][node],
                       sizeof(ScsData[0][0]));
   }

#if WASD_GETSPI
   status = exe$getspi (EfnWait, 0, 0, &RmiItem, &IOsb, 0, 0);
#else
   status = sys$getrmi (EfnWait, 0, 0, &RmiItem, &IOsb, 0, 0);
#endif
   if (VMSok (status)) sys$synch (EfnWait, &IOsb);
   if (VMSok (status)) status = IOsb.Status;
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "SCS data not available !&S\n\n",  status);
      return;
   }
   status = 0;

   memcpy (&ScsData[0], &ScsRead[1], sizeof(ScsData[0]));

   if (rqptr == (REQUEST_STRUCT*)-1) return;

   /**********/
   /* report */
   /**********/

   FaoToEither (rqptr, "\
SCS    Node    dTx dRx dDp       kB Map        kB Rx        kB Tx \
       Msg Rx        Msg Tx   Qbdt     Qcr    Req Dats    Snd Dats\n\
       ~~~~~~~ ~~~ ~~~ ~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ ~~~~~~~~~~~~ \
~~~~~~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~ ~~~~~~~ ~~~~~~~~~~~ ~~~~~~~~~~~\n");

   for (min = 0; min <= NUM_MINS; min++)
   {
      if (min)
         sprintf (when, "%d min", min);
      else
         strcpy (when, "total");

      /* first node is always this one */
      for (node = 1; node < SCS_NODES_MAX; node++)
      {
         /* node name is a counted string */
         cptr = (char*)&ScsData[min][node][0];
         cnt = *cptr++ & 0x7;
         /* zero-length node name */
         if (!cnt) continue;
         for (sptr = name; cnt--; *sptr++ = *cptr++);
         *sptr = '\0';
         
         DgramSent = ScsData[min][node][2];
         DgramRcvd = ScsData[min][node][3];
         DgramDisc = ScsData[min][node][4];
         MsgSent   = ScsData[min][node][5];
         MsgRcvd   = ScsData[min][node][6];
         SendDats  = ScsData[min][node][7];
         KbyteSent = ScsData[min][node][8];
         ReqDats   = ScsData[min][node][9];
         KbyteRcvd = ScsData[min][node][10];
         KbyteMap  = ScsData[min][node][11];
         QcrCnt    = ScsData[min][node][12];
         QbdtCnt   = ScsData[min][node][13];

         if (min)
         {
            /* if no previous minute data */
            if (!ScsData[min+1][node][0]) continue;
            /* otherwise delta with previous minute */
            DgramSent -= ScsData[min+1][node][2];
            DgramRcvd -= ScsData[min+1][node][3];
            DgramDisc -= ScsData[min+1][node][4];
            MsgSent   -= ScsData[min+1][node][5];
            MsgRcvd   -= ScsData[min+1][node][6];  
            SendDats  -= ScsData[min+1][node][7];  
            KbyteSent -= ScsData[min+1][node][8];
            ReqDats   -= ScsData[min+1][node][9];  
            KbyteRcvd -= ScsData[min+1][node][10];
            KbyteMap  -= ScsData[min+1][node][11];
            QcrCnt    -= ScsData[min+1][node][12];  
            QbdtCnt   -= ScsData[min+1][node][13];  
         }

         FaoToEither (rqptr,
"!6&>AZ !7AZ !3UL !3UL !3UL !12UL !12UL !12UL !13UL !13UL \
!6UL !7UL !11UL !11UL\n",
                      when, name,
                      DgramSent, DgramRcvd, DgramDisc,
                      KbyteMap, KbyteSent, KbyteRcvd,
                      MsgSent, MsgRcvd,
                      QbdtCnt, QcrCnt,
                      ReqDats, SendDats);  
          when[0] = '\0';
      }
   }

   FaoToEither (rqptr, "\n");
}

/*****************************************************************************/
/*
Supports sysPlusPlus().  Provide system data.
*/

void sysPlusSyi (REQUEST_STRUCT *rqptr)

{
   static ushort  SyiClusterEVotes,
                  SyiClusterQuorum,
                  SyiNodeVotes,
                  SyiClusterVotes,
                  SyiNodeQuorum;

   static ulong  SyiClusterNodes,
                 SyiContigGblPages,
                 SyiFreeGblPages,
                 SyiMaxProcessCnt,
                 SyiPageFileFree,
                 SyiPageFilePage,
                 SyiSwapFileFree,
                 SyiSwapFilePage;

   static ulong  SyiBalSlots [4],
                 SyiMainMemory [4],
                 SyiNPagedPool [4],
                 SyiNPageVir [4],
                 SyiPagedPool [4],
                 SyiProcSlots [4];

   static VMS_ITEM_LIST3  SyiItem [] =
   {
     { sizeof(SyiBalSlots), SYI$_BAL_SLOTS, &SyiBalSlots, 0 },
     { sizeof(SyiContigGblPages), SYI$_CONTIG_GBLPAGES, &SyiContigGblPages, 0 },
     { sizeof(SyiClusterEVotes), SYI$_CLUSTER_EVOTES, &SyiClusterEVotes, 0 },
     { sizeof(SyiClusterNodes), SYI$_CLUSTER_NODES, &SyiClusterNodes, 0 },
     { sizeof(SyiClusterQuorum), SYI$_CLUSTER_QUORUM, &SyiClusterQuorum, 0 },
     { sizeof(SyiClusterVotes), SYI$_CLUSTER_VOTES, &SyiClusterVotes, 0 },
     { sizeof(SyiFreeGblPages), SYI$_FREE_GBLPAGES, &SyiFreeGblPages, 0 },
     { sizeof(SyiMaxProcessCnt), SYI$_MAXPROCESSCNT, &SyiMaxProcessCnt, 0 },
     { sizeof(SyiMainMemory), SYI$_MAIN_MEMORY, &SyiMainMemory, 0 },
     { sizeof(SyiNodeVotes), SYI$_NODE_VOTES, &SyiNodeVotes, 0 },
     { sizeof(SyiNPagedPool), SYI$_NPAGED_POOL, &SyiNPagedPool, 0 },
     { sizeof(SyiNPageVir), SYI$_NPAGEVIR, &SyiNPageVir, 0 },
     { sizeof(SyiNodeQuorum), SYI$_NODE_QUORUM, &SyiNodeQuorum, 0 },
     { sizeof(SyiPagedPool), SYI$_PAGED_POOL, &SyiPagedPool, 0 },
     { sizeof(SyiPageFileFree), SYI$_PAGEFILE_FREE, &SyiPageFileFree, 0 },
     { sizeof(SyiPageFilePage), SYI$_PAGEFILE_PAGE, &SyiPageFilePage, 0 },
     { sizeof(SyiProcSlots), SYI$_PROC_SLOTS, &SyiProcSlots, 0 },
     { sizeof(SyiSwapFileFree), SYI$_SWAPFILE_FREE, &SyiSwapFileFree, 0 },
     { sizeof(SyiSwapFilePage), SYI$_SWAPFILE_PAGE, &SyiSwapFilePage, 0 },
     { 0,0,0,0 }
   };

   static double  factor, fGB, fMB, fkB, fPS = 0.0;

   int  status;
   char  *cptr, *mmptr, *npptr, *pptr;
   char  MainMemErrBuf [32],
         PageFileBuf [256],
         SwapFileBuf [256];
   char  MainMemBuf [4][32],
         NonPagedPoolBuf [4][32],
         PagedPoolBuf [4][32];
   IO_SB  IOsb;

   /*********/
   /* begin */
   /*********/

   if (WATCH_MODULE(WATCH_MOD__OTHER))
      WatchThis (WATCHALL, WATCH_MOD__OTHER, "sysPlusSyi()");

   status = sys$getsyiw (EfnWait, 0, 0, &SyiItem, &IOsb, 0, 0);
   if (VMSok (status)) status = IOsb.Status;
   if (VMSnok (status))
   {
      FaoToEither (rqptr, "$GETSYI() !&S\n",  status);
      return;
   }

   if (fGB < 0.1)
   {
      fPS = (double)SysInfo.PageSize;
      fGB = 1073741824.0;
      fMB = 1048576.0;
      fkB = 1024.0;
   }

   if ((double)SyiMainMemory[0] * fPS / fGB < 1.0)
   {
      mmptr = "MB";
      factor = fMB;
   }
   else
   {
      mmptr = "GB";
      factor = fGB;
   }

   sprintf (MainMemBuf[0], "%6.2f", (double)SyiMainMemory[0] * fPS / factor);
   sprintf (MainMemBuf[1], "%6.2f", (double)SyiMainMemory[1] * fPS / factor);
   sprintf (MainMemBuf[2], "%6.2f", (double)SyiMainMemory[2] * fPS / factor);
   sprintf (MainMemBuf[3], "%6.2f", (double)SyiMainMemory[3] * fPS / factor);

   if ((double)SyiNPagedPool[0] / fGB < 1.0)
   {
      npptr = "MB";
      factor = fMB;
   }
   else
   {
      npptr = "GB";
      factor = fGB;
   }

   sprintf (NonPagedPoolBuf[0], "%6.2f", (double)SyiNPagedPool[0] / factor);
   sprintf (NonPagedPoolBuf[1], "%6.2f", (double)SyiNPagedPool[1] / factor);
   sprintf (NonPagedPoolBuf[2], "%6.2f", (double)SyiNPagedPool[2] / factor);
   sprintf (NonPagedPoolBuf[3], "%6.2f", (double)SyiNPagedPool[3] / factor);

   if ((double)SyiPagedPool[0] / fGB < 1.0)
   {
      pptr = "MB";
      factor = fMB;
   }
   else
   {
      pptr = "GB";
      factor = fGB;
   }

   sprintf (PagedPoolBuf[0], "%6.2f", (double)SyiPagedPool[0] / factor);
   sprintf (PagedPoolBuf[1], "%6.2f", (double)SyiPagedPool[1] / factor);
   sprintf (PagedPoolBuf[2], "%6.2f", (double)SyiPagedPool[2] / factor);
   sprintf (PagedPoolBuf[3], "%6.2f", (double)SyiPagedPool[3] / factor);

   if (SyiSwapFilePage)
   {
      if ((double)SyiSwapFilePage * fPS / fGB < 1.0)
      {
         cptr = "MB";
         factor = fMB;
      }
      else
      {
         cptr = "GB";
         factor = fGB;
      }
      sprintf (SwapFileBuf,
"Swap File Usage (bytes):                        Free        Size      In use\n\
                                    (%s)      %6.2f      %6.2f        %3d%%\n\n",
               cptr,
               (double)SyiSwapFileFree * fPS / factor,
               (double)SyiSwapFilePage * fPS / factor,
               PercentOf32 (SyiSwapFilePage - SyiSwapFileFree, SyiSwapFilePage));
   }
   else
      SwapFileBuf[0] = '\0';

   if (SyiPageFilePage)
   {
      if ((double)SyiPageFilePage * fPS / fGB < 1.0)
      {
         cptr = "MB";
         factor = fMB;
      }
      else
      {
         cptr = "GB";
         factor = fGB;
      }
      sprintf (PageFileBuf,
"Paging File Usage (bytes):                      Free        Size      In use\n\
                                    (%s)      %6.2f      %6.2f        %3d%%\n\n",
               cptr,
               (double)SyiPageFileFree * fPS / factor,
               (double)SyiPageFilePage * fPS / factor,
               PercentOf32 (SyiPageFilePage - SyiPageFileFree, SyiPageFilePage));
   }
   else
      PageFileBuf[0] = '\0';

   sprintf (MainMemErrBuf, "  Errors: %u\n", sysPlusRmiMemErrs);

   status = FaoToEither (rqptr,
"Physical Memory Usage (bytes):     Total        Free      In Use    Modified\n\
  Main Memory             (!AZ)    !9AZ   !9AZ   !9AZ   !9AZ\n\
!AZ\
\n\
Slot Usage (slots):                Total        Free    Resident     Swapped\n\
  Process Entry Slots               !4UL        !4UL        !4UL        !4UL\n\
  Balance Set Slots                 !4UL        !4UL        !4UL        !4UL\n\
\n\
Dynamic Memory Usage:              Total        Free      In Use     Largest\n\
  Nonpaged Dynamic Memory (!AZ)    !9AZ   !9AZ   !9AZ   !9AZ\n\
  Paged Dynamic Memory    (!AZ)    !9AZ   !9AZ   !9AZ   !9AZ\n\
\n\
!AZ\
!AZ\
Cluster      Nodes    Member  Expected     Votes    Quorum\n"
#if WASD_GETSPI
"(SPI)"
#else
"(RMI)"
#endif
"         !4UL      !4UL      !4UL      !4UL      !4UL\n\
\n",
      mmptr,
      MainMemBuf[0], MainMemBuf[1], MainMemBuf[2], MainMemBuf[3],
      MainMemErrBuf,
      SyiProcSlots[0], SyiProcSlots[1], SyiProcSlots[2], SyiProcSlots[3],
      SyiBalSlots[0], SyiBalSlots[1], SyiBalSlots[2], SyiBalSlots[3],
      npptr,
      NonPagedPoolBuf[0], NonPagedPoolBuf[1],
         NonPagedPoolBuf[2], NonPagedPoolBuf[3],
      pptr,
      PagedPoolBuf[0], PagedPoolBuf[1], PagedPoolBuf[2], PagedPoolBuf[3],
      SwapFileBuf, PageFileBuf,
      SyiClusterNodes, SysInfo.ClusterMember, SyiClusterEVotes,
      SyiClusterVotes, SyiClusterQuorum);

   if (VMSnok (status)) FaoToEither (rqptr, "$FAO() !&S\n",  status);
}

/****************************************************************************/