who.c 6.24 KB
Newer Older
Justin Mitchell's avatar
Justin Mitchell committed
1 2 3 4 5 6
/*********************************************************
 *     The Milliways III System is copyright 1992        *
 *      J.S.Mitchell. (arthur@sugalaxy.swan.ac.uk)       *
 *       see licence for furthur information.            *
 *********************************************************/

7
#include <stdlib.h>
Justin Mitchell's avatar
Justin Mitchell committed
8 9 10 11
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <fcntl.h>
12
#include <time.h>
13
#include <stdbool.h>
Justin Mitchell's avatar
Justin Mitchell committed
14 15

#include "talker_privs.h"
16
#include "special.h"
17
#include "strings.h"
18
#include "str_util.h"
19
#include "ipc.h"
20 21
#include "perms.h"
#include "talker.h"
22 23
#include "userio.h"
#include "who.h"
24
#include "main.h"
25 26
#include <str_util.h>
#include <util.h>
Justin Mitchell's avatar
Justin Mitchell committed
27

28
extern int busy;
29
extern struct user * const user;
30

31
char *itime(unsigned long t)
Justin Mitchell's avatar
Justin Mitchell committed
32
{
33
	static char out[20];
34

35 36 37 38 39 40 41 42 43
	if (t>=3600*48) sprintf(out,"%2ldd%2ldh",t/86400, (t%86400)/3600);
	else
	if (t>=3600) sprintf(out,"%2ldh%2ldm",t/3600,(t%3600)/60);
	else
	if (t>=60) sprintf(out,"%2ldm%2lds",t/60,t%60);
	else
	sprintf(out,"%5lds",t);
	return(out);
}
Justin Mitchell's avatar
Justin Mitchell committed
44

45 46 47 48
static json_t * whoinfo = NULL;
static time_t   whowhen = 0;
static int      whotype = -1;
#define WHOCACHE 120  /* cache who data for this many seconds */
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#define NO_CALLBACK -1

/* check if we need to refresh the wholist
 * and request it if we do 
 * report if we did
 */
static int refresh_wholist(int type)
{
	time_t now = time(0);
	if (whoinfo == NULL || whowhen < (now - WHOCACHE)) {
		whotype = type;
		ipc_message_t * msg = ipcmsg_create(IPC_WHOLIST, user->posn);
		ipcmsg_transmit(msg);
		return 1;
	}
	return 0;
}
66

67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
/* If we don't get the who list within the timeout, fail */
#define WHOINFO_TIMEOUT 10000
#define WHOINFO_CHECK_INTERVAL (WHOINFO_TIMEOUT / 250)
int require_whoinfo(void)
{
	int n = 0;

	while (whoinfo == NULL && n < WHOINFO_TIMEOUT) {
		idle(-1, WHOINFO_CHECK_INTERVAL);
		n += WHOINFO_CHECK_INTERVAL;
	}
	if (whoinfo == NULL)
		return 1;
	return 0;
}

83 84 85 86 87 88
void display_wholist(int mode)
{
	time_t now = time(NULL);

	/* we dont have a recent cache of who list,
	 * request one, and get called back when it arrives */
89
	if (refresh_wholist(mode)) {
90 91
		return;
	}
Justin Mitchell's avatar
Justin Mitchell committed
92

93 94
	busy++;
	if (mode == 1)
95
		format_message("\nUser status...");
96
	else
Imran Hussain's avatar
Imran Hussain committed
97
		format_message("\n %-*s %-*s  Idle  What...",NAMESIZE,"Name",20,"RealName");
98

99
	_autofree char *divider = NULL;
100
	for (int i = 0; i < screen_w(); i++) string_add(&divider, "-");
101
	format_message("%s", divider);
102

103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	size_t wi;
	json_t *entry;
	json_array_foreach(whoinfo, wi, entry) {
		const char *name = json_getstring(entry, "name");
		const char *realname = json_getstring(entry, "realname");
		time_t dowhen = json_getint(entry, "dowhen");
		const char * doing = json_getstring(entry, "doing");
		time_t idletime = json_getint(entry, "idletime");
		int channel = json_getint(entry, "channel");
		json_t *perms = json_object_get(entry, "perms");

		if (mode == 1) {
			if (dowhen && doing!=NULL && doing[0] != 0)
				format_message("%s %s\033-- (%s ago)",name, doing ,itime(time(0)-dowhen));
		} else {
			char chat=' ';
			//const char *status = json_getstring(perms, "status");
			const char *chatmode = json_getstring(perms, "chatmode");
			const char *chatprivs = json_getstring(perms, "chatprivs");
			const char *prot = json_getstring(perms, "protection");

			if (json_getint(perms, "wizchat") > 0) chat='*';

126
			format_message("%c%-*s %-30.30s %6s Room %d (%s,%s,%s)\033--",chat,NAMESIZE,name,realname,itime(now-idletime),channel, chatmode, prot, chatprivs);
Justin Mitchell's avatar
Justin Mitchell committed
127 128
		}
	}
129
	format_message("%s", divider);
130
	busy--;
Justin Mitchell's avatar
Justin Mitchell committed
131 132
}

133
void update_wholist(ipc_message_t *msg)
134
{
135
	/* there is an old one, clear it */
136
	if (whoinfo != NULL) {
137
		json_decref(whoinfo);
138
	}
139 140 141 142 143 144 145 146 147

	/* store the new one */
	whoinfo = json_init(msg);
	whowhen = time(NULL);

	/* we were waiting for one, show it */
	if (whotype >= 0) {
		display_wholist(whotype);
		whotype = -1;
148 149 150
	}
}

151
char *part_who(const char *text, int status)
Justin Mitchell's avatar
Justin Mitchell committed
152
{
153 154 155 156 157
	static int len = 0;
	static int index = 0; /* looking for the Nth answer */

	/* we dont have a recent cache of who list,
	 * ask for an update, then do the best you can */
158
	refresh_wholist(NO_CALLBACK);
159 160 161 162 163 164 165 166

	/* we dont even have stale info */
	if (whoinfo == NULL) return(NULL);

	/* start a new search */
	if (status == 0) {
		len = strlen(text);
		index = 0;
Justin Mitchell's avatar
Justin Mitchell committed
167 168
	}

169 170 171 172 173 174 175 176 177 178
	size_t wi;
	json_t *entry;
	int count = 0;
	json_array_foreach(whoinfo, wi, entry) {
		const char *name = json_getstring(entry, "name");
		if (name == NULL) continue;
		if (strncasecmp(name, text, len)==0) {
			/* found the one we want */
			if (count == index) {
				index++;
179
				return strdup(name);
Justin Mitchell's avatar
Justin Mitchell committed
180
			}
181 182
			/* found one we dont want */
			count++;
Justin Mitchell's avatar
Justin Mitchell committed
183 184
		}
	}
185 186
	/* run out of answers */
	return NULL;
Justin Mitchell's avatar
Justin Mitchell committed
187 188
}

189
char *part_who_talk(const char *text, int status)
Justin Mitchell's avatar
Justin Mitchell committed
190
{
191 192 193 194 195
	static int len = 0;
	static int index = 0; /* looking for the Nth answer */

	/* we dont have a recent cache of who list,
	 * ask for an update, then do the best you can */
196
	refresh_wholist(NO_CALLBACK);
Justin Mitchell's avatar
Justin Mitchell committed
197

198 199 200 201 202 203 204
	/* we dont even have stale info */
	if (whoinfo == NULL) return(NULL);

	/* start a new search */
	if (status == 0) {
		len = strlen(text);
		index = 0;
Justin Mitchell's avatar
Justin Mitchell committed
205
	}
206 207 208 209 210 211 212 213

	size_t wi;
	json_t *entry;
	int count = 0;
	json_array_foreach(whoinfo, wi, entry) {
		const char *name = json_getstring(entry, "name");
		json_t * perms = json_object_get(entry, "perms");
		const char *chatmode = NULL;
214
		if (perms != NULL) chatmode=json_getstring(perms, "chatmode");
215 216 217 218 219 220 221 222 223 224 225

		if (name == NULL) continue;
		if (chatmode == NULL) continue;

		/* isnt on chat */
		if (strchr(chatmode, 'c')==NULL) continue;

		if (strncasecmp(name, text, len)==0) {
			/* found the one we want */
			if (count == index) {
				index++;
226
				return strdup(name);
227 228 229
			}
			/* found one we dont want */
			count++;
Justin Mitchell's avatar
Justin Mitchell committed
230 231
		}
	}
232 233
	/* run out of answers */
	return NULL;
Justin Mitchell's avatar
Justin Mitchell committed
234 235
}

236 237 238 239 240 241 242
/* grab a handle to the current wholist
 * you need to json_decref it when finished
 */
json_t * grab_wholist(void)
{
	/* we dont have a recent cache of who list,
	 * ask for an update, then do the best you can */
243
	refresh_wholist(NO_CALLBACK);
244 245 246 247

	if (whoinfo != NULL) json_incref(whoinfo);
	return whoinfo;
}
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266

int32_t who_find(const char *username)
{
	json_t *wlist = grab_wholist();
	if (wlist == NULL) return -1;

	size_t wi;
	json_t *entry;
	json_array_foreach(wlist, wi, entry) {
		const char *name = json_getstring(entry, "name");
		int32_t uid = json_getint(entry, "id");
		if (strcasecmp(username, name)==0) {
			json_decref(wlist);
			return uid;
		}
	}
	json_decref(wlist);
	return -1;
}