#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "node.h" #include "sysinfo.h" struct user User = {0}; static long CallerPos = -1L; void login_user(void) { FILE *f; struct user u; long pos = 0L; long free = -1L; struct stat statbuf; if (stat(DATA_NODE_LOGIN_FILE, &statbuf) == -1) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (statbuf.st_size % sizeof(struct user) != 0) { node_msg("%s: Incorrect size", DATA_NODE_LOGIN_FILE); node_log(LOGLVL_ERROR, "%s: Incorrect size", DATA_NODE_LOGIN_FILE); return; } time(&User.logintime); User.cmdtime = User.logintime; User.pid = getpid(); if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (flock(fileno(f), LOCK_EX) == -1) { node_perror("login_user: flock", errno); fclose(f); return; } while (fread(&u, sizeof(u), 1, f) == 1) { if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) { free = pos; break; } pos += sizeof(u); } if (free != -1L && fseek(f, free, 0L) == -1) { node_perror("login_user: fseek", errno); fclose(f); return; } fflush(f); CallerPos = ftell(f); fwrite(&User, sizeof(User), 1, f); fflush(f); flock(fileno(f), LOCK_UN); fclose(f); } void logout_user(void) { FILE *f; if (CallerPos == -1L) return; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (fseek(f, CallerPos, 0) == -1) { node_perror("logout_user: fseek", errno); fclose(f); return; } User.pid = -1; fwrite(&User, sizeof(User), 1, f); fclose(f); } void update_user(void) { FILE *f; if (CallerPos == -1L) return; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r+")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return; } if (fseek(f, CallerPos, 0) == -1) { node_perror("update_user: fseek", errno); fclose(f); return; } fwrite(&User, sizeof(User), 1, f); fclose(f); } int user_count(void) { FILE *f; struct user u; int cnt = 0; if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return 0; } while (fread(&u, sizeof(u), 1, f) == 1) if (u.pid != -1 && (kill(u.pid, 0) != -1 || errno != ESRCH)) cnt++; fclose(f); return cnt; } int user_list(int argc, char **argv) { FILE *f; struct user u; struct tm *tp; struct proc_nr_nodes *np; char buf[80]; long l; axio_puts("",NodeIo); if ((f = fopen(DATA_NODE_LOGIN_FILE, "r")) == NULL) { node_perror(DATA_NODE_LOGIN_FILE, errno); return 0; } if (User.ul_type == AF_NETROM) { axio_printf(NodeIo, "%s} %s", NodeId, VERSION); } if (User.ul_type == AF_INET) { axio_printf(NodeIo, "\e[01;35m"); } else { axio_printf(NodeIo, "Current users:"); } if (user_count() == 0) { axio_printf(NodeIo, " No users online.\n"); } if (User.ul_type == AF_INET) { axio_printf(NodeIo,"\e[0;m"); } if (user_count() != 0) /* axio_printf(NodeIo,"") */ ; while (fread(&u, sizeof(u), 1, f) == 1) { if (u.pid == -1 || (kill(u.pid, 0) == -1 && errno == ESRCH)) continue; switch (u.ul_type) { case AF_FLEXNET: sprintf(buf, "\nFlexNet (%.9s)", u.call); break; case AF_AX25: sprintf(buf, "\nUplink (%.9s on interface %.10s)", u.call, u.ul_name); break; case AF_NETROM: if ((np = find_node(u.ul_name, NULL)) != NULL) { sprintf(buf, "\nCircuit (%.9s %.18s)", u.call, print_node(np->alias, np->call)); } else { sprintf(buf, "\nCircuit (%.9s %.18s)", u.call, u.ul_name); } break; #ifdef HAVE_ROSE case AF_ROSE: sprintf(buf, "\nROSE (%.9s %.18s)", u.call, u.ul_name); break; #endif case AF_INET: sprintf(buf, "\nTelnet (%.9s @ %.16s)", u.call, u.ul_name); break; case AF_INET6: sprintf(buf, "\nTelnet6 (%.9s via IPv6)", u.call); break; case AF_UNSPEC: sprintf(buf, "\nHost (%.9s on local)", u.call); break; default: sprintf(buf, "\n?????? (%.9s %.18s)", u.call, u.ul_name); break; } axio_printf(NodeIo,"%-37.37s ", buf); switch (u.state) { case STATE_QUIT: logout_user(); break; case STATE_LOGIN: axio_puts(" -> Logging in",NodeIo); break; case STATE_IDLE: time(&l); l -= u.cmdtime; tp = gmtime(&l); axio_printf(NodeIo," -> Idle (%d:%02d:%02d:%02d)", tp->tm_yday, tp->tm_hour, tp->tm_min, tp->tm_sec); break; case STATE_TRYING: switch (u.dl_type) { case AF_FLEXNET: axio_printf(NodeIo," -> Trying (%s)", u.dl_name); break; case AF_AX25: axio_printf(NodeIo," -> Trying (%s on interface %s)", u.dl_name, u.dl_port); break; case AF_NETROM: axio_printf(NodeIo," -> Trying (%s)", u.dl_name); break; #ifdef HAVE_ROSE case AF_ROSE: axio_printf(NodeIo," -> Trying (%s)", u.dl_name); break; #endif case AF_INET: axio_printf(NodeIo," -> Trying (%s:%s)", u.dl_name, u.dl_port); break; default: axio_puts(" -> ???",NodeIo); break; } break; case STATE_CONNECTED: switch (u.dl_type) { case AF_FLEXNET: axio_printf(NodeIo,"<--> FlexNet (%s)", u.dl_name); break; case AF_AX25: axio_printf(NodeIo,"<--> Downlink (%s on interface %s)", u.dl_name, u.dl_port); break; case AF_NETROM: axio_printf(NodeIo,"<--> Circuit (%s)", u.dl_name); break; #ifdef HAVE_ROSE case AF_ROSE: axio_printf(NodeIo,"<--> ROSE (%s)", u.dl_name); break; #endif case AF_INET: axio_printf(NodeIo,"<--> Telnet (%s:%s)", u.dl_name, u.dl_port); break; default: axio_printf(NodeIo,"<--> ???"); break; } break; case STATE_PINGING: axio_printf(NodeIo,"<--> Pinging (%s)", u.dl_name); break; case STATE_EXTCMD: axio_printf(NodeIo,"<--> Extcmd (%s)", u.dl_name); break; default: axio_puts(" -> ??????",NodeIo); break; } axio_puts("",NodeIo); } if (User.ul_type == AF_NETROM) { node_msg(""); } fclose(f); return 0; }