/* 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 Non-IPX addresses listing. 1.00 1999, November 20 Petr Vandrovec Added license. 1.01 2000, May 28 Petr Vandrovec Added -q to print object ID. 1.02 2001, January 27 Petr Vandrovec Dump open files. 1.03 2001, February 11 Petr Vandrovec Dump open semaphores. 1.04 2002, July 21 Petr Vandrovec Dump some statistical information. */ #include "config.h" #include #include #include #include #include #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; }