Added context state to output of RWHO command.
[citadel.git] / citadel / server / modules / rwho / serv_rwho.c
1 // This module implements server commands related to the display and
2 // manipulation of the "Who's online" list.
3 //
4 // Copyright (c) 1987-2024 by the citadel.org team
5 //
6 // This program is open source software.  Use, duplication, or disclosure
7 // is subject to the terms of the GNU General Public License, version 3.
8
9 #include "../../sysdep.h"
10 #include <stdlib.h>
11 #include <unistd.h>
12 #include <stdio.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <errno.h>
17 #include <sys/types.h>
18 #include <time.h>
19 #include <sys/wait.h>
20 #include <string.h>
21 #include <limits.h>
22 #include <libcitadel.h>
23 #include "../../citadel_defs.h"
24 #include "../../server.h"
25 #include "../../citserver.h"
26 #include "../../support.h"
27 #include "../../config.h"
28 #include "../../control.h"
29 #include "../../user_ops.h"
30 #include "../../database.h"
31 #include "../../msgbase.h"
32 #include "../../ctdl_module.h"
33
34 // Don't show the names of private rooms unless the viewing
35 // user also knows the rooms.
36 void GenerateRoomDisplay(char *real_room, CitContext *viewed, CitContext *viewer) {
37         int ra;
38
39         strcpy(real_room, viewed->room.QRname);
40
41         if (viewed->room.QRflags & QR_MAILBOX) {
42                 strcpy(real_room, &real_room[11]);
43         }
44
45         if (viewed->room.QRflags & QR_PRIVATE) {
46                 CtdlRoomAccess(&viewed->room, &viewer->user, &ra, NULL);
47                 if ( (ra & UA_KNOWN) == 0) {
48                         strcpy(real_room, " ");
49                 }
50         }
51
52         if (viewed->cs_flags & CS_CHAT) {
53                 while (strlen(real_room) < 14) {
54                         strcat(real_room, " ");
55                 }
56                 strcpy(&real_room[14], "<chat>");
57         }
58
59 }
60
61
62 // display who's online
63 void cmd_rwho(char *argbuf) {
64         struct CitContext *nptr;
65         int nContexts, i;
66         int aide;
67         char room[ROOMNAMELEN];
68         char flags[5];
69         
70         // So that we don't keep the context list locked for a long time
71         // we create a copy of it first
72         nptr = CtdlGetContextArray(&nContexts) ;
73         if (!nptr) {
74                 // Couldn't malloc so we have to bail but stick to the protocol
75                 cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress(CC) );
76                 cprintf("000\n");
77                 return;
78         }
79         
80         aide = ( (CC->user.axlevel >= AxAideU) || (CC->internal_pgm) ) ;
81         cprintf("%d%c \n", LISTING_FOLLOWS, CtdlCheckExpress(CC) );
82         
83         for (i=0; i<nContexts; i++)  {
84                 flags[0] = '\0';
85                 
86                 if (!aide && nptr[i].state == CON_SYS)
87                         continue;
88
89                 if (!aide && nptr[i].kill_me != 0)
90                         continue;
91
92                 if (nptr[i].cs_flags & CS_POSTING) {
93                         strcat(flags, "*");
94                 }
95                 else {
96                         strcat(flags, ".");
97                 }
98                    
99                 GenerateRoomDisplay(room, &nptr[i], CC);
100
101                 if ((nptr[i].cs_flags & CS_STEALTH) && (aide)) {
102                         strcat(flags, "-");
103                 }
104                 
105                 if (((nptr[i].cs_flags&CS_STEALTH)==0) || (aide)) {
106                         cprintf("%d|%s|%s|%s|%s|%ld|%s|%s||||%d|%d\n",
107                                 nptr[i].cs_pid,
108                                 (nptr[i].logged_in ? nptr[i].curr_user : NLI),
109                                 room,
110                                 nptr[i].cs_host,
111                                 nptr[i].cs_clientname,
112                                 (long)(nptr[i].lastidle),
113                                 nptr[i].lastcmdname,
114                                 flags,
115                                 nptr[i].logged_in,
116                                 nptr[i].state
117                         );
118                 }
119         }
120         
121         // release our copy of the context list
122         free(nptr);
123
124         // Now it's magic time.  Before we finish, call any EVT_RWHO hooks
125         // so that external paging modules such as serv_icq can add more
126         // content to the Wholist.
127         PerformSessionHooks(EVT_RWHO);
128         cprintf("000\n");
129 }
130
131
132 // enter or exit "stealth mode"
133 void cmd_stel(char *cmdbuf) {
134         int requested_mode;
135
136         requested_mode = extract_int(cmdbuf,0);
137
138         if (CtdlAccessCheck(ac_logged_in)) return;
139
140         if (requested_mode == 1) {
141                 CC->cs_flags = CC->cs_flags | CS_STEALTH;
142                 PerformSessionHooks(EVT_STEALTH);
143         }
144         if (requested_mode == 0) {
145                 CC->cs_flags = CC->cs_flags & ~CS_STEALTH;
146                 PerformSessionHooks(EVT_UNSTEALTH);
147         }
148
149         cprintf("%d %d\n", CIT_OK,
150                 ((CC->cs_flags & CS_STEALTH) ? 1 : 0) );
151 }
152
153
154 // Initialization function, called from modules_init.c
155 char *ctdl_module_init_rwho(void) {
156         if (!threading) {
157                 CtdlRegisterProtoHook(cmd_rwho, "RWHO", "Display who is online");
158                 CtdlRegisterProtoHook(cmd_stel, "STEL", "Enter/exit stealth mode");
159
160         }
161         
162         // return our module name for the log
163         return "rwho";
164 }