Files
ncpfs/util/nwuserlist.c
2026-04-28 20:56:04 +02:00

506 lines
13 KiB
C

/*
nwuserlist.c - Lists users attached to server
Copyright (C) 1996 by Volker Lendecke
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Revision history:
0.00 1996 Volker Lendecke
Initial revision.
0.01 1999 Petr Vandrovec <vandrove@vc.cvut.cz>
Non-IPX addresses listing.
1.00 1999, November 20 Petr Vandrovec <vandrove@vc.cvut.cz>
Added license.
1.01 2000, May 28 Petr Vandrovec <vandrove@vc.cvut.cz>
Added -q to print object ID.
1.02 2001, January 27 Petr Vandrovec <vandrove@vc.cvut.cz>
Dump open files.
1.03 2001, February 11 Petr Vandrovec <vandrove@vc.cvut.cz>
Dump open semaphores.
1.04 2002, July 21 Petr Vandrovec <vandrove@vc.cvut.cz>
Dump some statistical information.
*/
#include "config.h"
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <ncp/nwcalls.h>
#include <ncp/nwfse.h>
#include "private/libintl.h"
#define _(X) gettext(X)
#define N_(X) (X)
static char *progname;
static void
usage(void)
{
fprintf(stderr, _("usage: %s [pattern]\n"), progname);
}
static void
str_trim_right(char *s, char c)
{
int len = strlen(s) - 1;
while ((len > 0) && (s[len] == c))
{
s[len] = '\0';
len -= 1;
}
}
static void
help(void)
{
printf(_("\n"
"usage: %s [options]\n"), progname);
printf(_("\n"
"-h Print this help text\n"
"-S server Server name to be used\n"
"-a Print Station's addr\n"
"-q Print object ID\n"
"-f List open files\n"
"-ft Print raw information about open files\n"
"-fd Print detailed information about each open file\n"
"-fD Print DOS filename\n"
"-s List open semaphores\n"
"-i List statistical information\n"
"-ih List read/written bytes in human readable format (e.g. 1K, 234M)\n"
"-iH Same as above, but use units of 1000 bytes instead of 1024\n"
"\n"));
}
static const char* conntype(unsigned int id) {
static const char* ct[] = {
"unset", "CLIB", "NCP", "NLM", "AFP", "FTAM",
"ANCP", "ACP", "SMB", "WINSOCK", "HTTP", "UDP",
};
if (id > 11) {
return _("Unknown");
}
return ct[id];
}
struct mt {
unsigned int mask;
const char* text;
};
static const char* connstatus(unsigned int id) {
static char tmp[1000];
static const struct mt fns[] = {
{ FSE_LOGGED_IN, N_("logged in") },
{ FSE_BEING_ABORTED, N_("being aborted") },
{ FSE_AUDITED, N_("audited") },
{ FSE_NEEDS_SECURITY_CHANGE, N_("needs security change") },
{ FSE_MAC_STATION, N_("MAC station") },
{ FSE_AUTHENTICATED_TEMPORARY, N_("temporary authenticated") },
{ FSE_AUDIT_CONNECTION_RECORDED, N_("audit connection recorded") },
{ FSE_DSAUDIT_CONNECTION_RECORDED, N_("DS audit connection recorded") },
{ ~0xFF, N_("???") },
{ 0, N_("none") },
};
const struct mt* ptr;
char* dst = tmp;
for (ptr = fns; ptr->mask; ptr++) {
if (ptr->mask & id) {
if (dst != tmp) {
strcpy(dst, ", ");
dst += 2;
}
strcpy(dst, _(ptr->text));
dst = strchr(dst, 0);
}
}
if (dst == tmp) {
strcpy(dst, _(ptr->text));
}
return tmp;
}
static void print_value(int format, const char* title, const char* units, u_int64_t value) {
static const char* si_prefixes = " kMGTPE";
const char* unitptr;
unsigned int div;
if (format == 0) {
printf(_(" %-21s%llu %s\n"), title, (unsigned long long)value, units);
return;
}
if (format == 1) {
div = 1024;
} else {
div = 1000;
}
unitptr = si_prefixes;
while (value >= div * 10 && unitptr[1]) {
value /= div;
unitptr++;
}
if (unitptr == si_prefixes) {
printf(_(" %-21s%5llu %s\n"), title, (unsigned long long)value, units);
} else {
printf(_(" %-21s%5llu %c%s\n"), title, (unsigned long long)value, *unitptr, units);
}
}
static inline size_t my_strftime(char *s, size_t max, const char *fmt, const struct tm *tm) {
return strftime(s, max, fmt, tm);
}
int
main(int argc, char **argv)
{
struct ncp_conn *conn;
int opt;
long err;
struct ncp_file_server_info info;
struct ncp_bindery_object user;
time_t login_time;
int i;
int do_help = 0;
int print_addr = 0;
int print_id = 0;
int print_file = 0;
int print_techinfo = 0;
int print_details = 0;
int print_dos = 0;
int print_semaphores = 0;
int print_stat = 0;
int print_stat_k = 0;
setlocale(LC_ALL, "");
bindtextdomain(NCPFS_PACKAGE, LOCALEDIR);
textdomain(NCPFS_PACKAGE);
progname = argv[0];
if ((conn = ncp_initialize(&argc, argv, 1, &err)) == NULL)
{
com_err(argv[0], err, _("when initializing"));
goto finished;
}
while ((opt = getopt(argc, argv, "h?aqftdDsiH")) != EOF)
{
switch (opt)
{
case 'h':
if (!do_help) {
do_help = 1;
break;
}
case '?':
help();
goto finished;
case 'a':
print_addr = 1;
break;
case 'q':
print_id = 1;
break;
case 'f':
print_file = 1;
break;
case 't':
print_techinfo = 1;
break;
case 'd':
print_details = 1;
break;
case 'D':
print_dos = 1;
break;
case 's':
print_semaphores = 1;
break;
case 'i':
print_stat = 1;
break;
case 'H':
print_stat_k = 2;
break;
default:
usage();
goto finished;
}
}
if (do_help) {
if (!print_stat || print_stat_k) {
help();
goto finished;
}
print_stat_k = 1;
}
if (ncp_get_file_server_information(conn, &info) != 0)
{
perror(_("Could not get server information"));
ncp_close(conn);
return 1;
}
if (isatty(1))
{
switch (print_id * 2 + print_addr) {
case 0:
printf(_("\n%-6s%-21s%-12s\n"
"---------------------------------------------"
"------\n"),
_("Conn"),
_("User name"),
_("Login time"));
break;
case 1:
printf(_("\n%-6s%-21s%-27s%-12s\n"
"---------------------------------------------"
"---------------------------------\n"),
_("Conn"),
_("User name"),
_("Station Address"),
_("Login time"));
break;
case 2:
printf(_("\n%-6s%-9s%-21s%-12s\n"
"------------------------------------------------------"
"------\n"),
_("Conn"),
_("ObjectID"),
_("User name"),
_("Login time"));
break;
case 3:
printf(_("\n%-6s%-9s%-21s%-27s%-12s\n"
"------------------------------------------------------"
"---------------------------------\n"),
_("Conn"),
_("ObjectID"),
_("User name"),
_("Station Address"),
_("Login time"));
break;
}
}
for (i = 0; i <= info.MaximumServiceConnections; i++)
{
char name[49];
name[48] = '\0';
if (ncp_get_stations_logged_info(conn, i, &user,
&login_time) != 0)
{
continue;
}
memcpy(name, user.object_name, 48);
str_trim_right(name, ' ');
if (print_id)
printf(_("%4d: %08X %-20s "), i, (unsigned int)user.object_id, name);
else
printf(_("%4d: %-20s "), i, name);
if (print_addr != 0)
{
union ncp_sockaddr addr;
u_int8_t conn_type;
memset(&addr, 0, sizeof(addr));
if (ncp_get_internet_address(conn, i, &addr.any, &conn_type)) {
printf("XXXXXXXX:YYZZYYXXTTXX:QQQQ");
} else switch (addr.any.sa_family) {
#ifdef NCP_IPX_SUPPORT
case AF_IPX: ipx_print_saddr(&addr.ipx);
break;
#endif
#ifdef NCP_IN_SUPPORT
case AF_INET: {
char q[30];
u_int32_t sa = ntohl(addr.inet.sin_addr.s_addr);
sprintf(q, "%d.%d.%d.%d/%d", (u_int8_t)(sa >> 24), (u_int8_t)(sa >> 16),
(u_int8_t)(sa >> 8), (u_int8_t)(sa),
ntohs(addr.inet.sin_port));
printf("%-26s", q);
}
break;
#endif
default: printf("%-26s", _("Unknown format"));
break;
}
printf(" ");
}
{
char text_login_time[200];
struct tm* tm;
tm = localtime(&login_time);
my_strftime(text_login_time, sizeof(text_login_time), "%c", tm);
printf("%s\n", text_login_time);
}
if (print_file) {
OPEN_FILE_CONN_CTRL ofcc;
OPEN_FILE_CONN ofc;
nuint16 ih;
ih = 0;
while (!NWScanOpenFilesByConn2(conn, i, &ih, &ofcc, &ofc)) {
char tmp[1000];
NWCCODE err2;
char* fname;
err2 = ncp_ns_get_full_name(conn, NW_NS_DOS, print_dos ? NW_NS_DOS : ofc.nameSpace, 1,
ofc.volNumber, ofc.dirEntry, NULL, 0, tmp, sizeof(tmp));
if (err2) {
fname = ofc.fileName;
} else {
fname = tmp;
}
if (print_techinfo) {
printf(_(" File: (%02X:%08X) %s\n"), ofc.volNumber, ofc.dirEntry, fname);
} else {
printf(_(" File: %s\n"), fname);
}
if (print_details) {
static const char* lock_bits[] = {N_("locked"), N_("open shareable"),
N_("logged"), N_("open normal"),
N_("rsvd"), N_("rsvd"),
N_("TTS locked"), N_("TTS")};
static const char* acc_bits[] = {N_("read"), N_("write"),
N_("deny read"), N_("deny write"),
N_("detached"), N_("TTS holding detach"),
N_("TTS holding open"), N_("rsvd")};
char lstr[200];
char accstr[200];
char* l2str;
const char* nmstr;
char* p;
int li;
p = NULL;
for (li = 0; li < 8; li++) {
if (ofc.lockType & (1 << li)) {
if (p) {
strcpy(p, ", ");
p = strchr(p, 0);
} else {
p = lstr;
}
strcpy(p, _(lock_bits[li]));
p = strchr(p, 0);
}
}
if (!p) {
strcpy(p, _("unlocked"));
}
switch (ofc.lockFlag) {
case 0x00: l2str = _("Not locked"); break;
case 0xFE: l2str = _("Locked by a file lock"); break;
case 0xFF: l2str = _("Locked by Begin Share File Set"); break;
default: l2str = _("Unknown lock state"); break;
}
nmstr = ncp_namespace_to_str(NULL, ofc.nameSpace);
p = NULL;
for (li = 0; li < 8; li++) {
if (ofc.accessControl & (1 << li)) {
if (p) {
strcpy(p, ", ");
p = strchr(p, 0);
} else {
p = accstr;
}
strcpy(p, _(acc_bits[li]));
p = strchr(p, 0);
}
}
if (!p) {
strcpy(p, _("unlocked"));
}
if (print_techinfo) {
printf(_(" Task: %-5u Lock: (%02X) %s\n"), ofc.taskNumber, ofc.lockType, lstr);
printf(_(" Fork count: %-3u (%02X) %s\n"), ofc.forkCount, ofc.lockFlag, l2str);
printf(_(" Namespace: (%02X) %-5s Access: (%02X) %s\n"), ofc.nameSpace, nmstr, ofc.accessControl, accstr);
} else {
printf(_(" Task: %-5u Lock: %s\n"), ofc.taskNumber, lstr);
printf(_(" Fork count: %-3u %s\n"), ofc.forkCount, l2str);
printf(_(" Namespace: %-5s Access: %s\n"), nmstr, accstr);
}
}
}
}
if (print_semaphores) {
CONN_SEMAPHORES css;
CONN_SEMAPHORE cs;
nuint16 ih;
ih = 0;
while (!NWScanSemaphoresByConn(conn, i, &ih, &cs, &css) && cs.openCount) {
printf(_(" Semaphore: %s\n"), cs.semaphoreName);
if (print_details) {
printf(_(" Task: %-5u Value: %-5d Open Count: %-5u\n"),
cs.taskNumber, cs.semaphoreValue, cs.openCount);
}
}
}
if (print_stat) {
NWFSE_USER_INFO fseui;
err = NWGetUserInfo(conn, i, NULL, &fseui);
if (!err) {
#define ui fseui.userInfo
if (print_techinfo) {
printf(_(" Type: (%02X) %-9.9s Status: (%08X) %s\n"),
ui.connServiceType, conntype(ui.connServiceType),
ui.status, connstatus(ui.status));
printf(_(" Use count: %-9u ExpTime: %08X ObjType: %08X\n"), ui.useCount,
ui.expirationTime, ui.objType);
printf(_(" Transaction flag: %9u Filler: %18u\n"),
ui.transactionFlag, ui.filler);
printf(_(" Logical lock threshold: %3u Record lock threshold: %3u\n"),
ui.logicalLockThreshold, ui.recordLockThreshold);
printf(_(" File write flags: 0x%02X File write state: 0x%02X\n"),
ui.fileWriteFlags, ui.fileWriteState);
printf(_(" File lock count: %10u Record lock count: %7u\n"),
ui.fileLockCount, ui.recordLockCount);
} else {
printf(_(" Type: %-14s Status: %s\n"),
conntype(ui.connServiceType),
connstatus(ui.status));
}
print_value(print_stat_k, _("Bytes read:"), _("B"), ui.totalBytesRead);
print_value(print_stat_k, _("Bytes written:"), _("B"), ui.totalBytesWritten);
print_value(print_stat_k, _("Requests:"), "", ui.totalRequests);
if (ui.heldRequests || ui.heldBytesRead || ui.heldBytesWritten) {
print_value(print_stat_k, _("Held bytes read:"), _("B"), ui.heldBytesRead);
print_value(print_stat_k, _("Held bytes written:"), _("B"), ui.heldBytesWritten);
print_value(print_stat_k, _("Held requests:"), "", ui.heldRequests);
}
#undef ui
}
}
}
finished:
ncp_close(conn);
return 0;
}