[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); } /****************************************************************************/