1 /*
2  *   Unreal Internet Relay Chat Daemon, src/s_debug.c
3  *   Copyright (C) 1990 Jarkko Oikarinen and
4  *                      University of Oulu, Computing Center
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 1, or (at your option)
9  *   any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19  */
20 
21 
22 #ifndef CLEAN_COMPILE
23 static char sccsid[] =
24     "@(#)s_debug.c	2.30 1/3/94 (C) 1988 University of Oulu, \
25 Computing Center and Jarkko Oikarinen";
26 #endif
27 
28 #include "struct.h"
29 #include <string.h>
30 #include "proto.h"
31 /*
32  * Option string.  Must be before #ifdef DEBUGMODE.
33  */
34 MODVAR char serveropts[] = {
35 #ifdef	CHROOTDIR
36 	'c',
37 #endif
38 #ifdef	CMDLINE_CONFIG
39 	'C',
40 #endif
41 #ifdef	DEBUGMODE
42 	'D',
43 #endif
44 #ifndef	NO_FDLIST
45 	'F',
46 #endif
47 	/*
48 	 * Marks that the ircd is ``compiled as'' a hub.
49 	 * Now always defined as it's impossible to build unrealircd
50 	 * without hub support AFAIK. (#0003891) --binki
51 	 */
52 	'h',
53 #ifdef	SHOW_INVISIBLE_LUSERS
54 	'i',
55 #endif
56 	/* NOSPOOF is always compiled in now. --nenolod */
57 	'n',
58 #ifdef	VALLOC
59 	'V',
60 #endif
61 #ifdef	_WIN32
62 	'W',
63 #endif
64 #ifdef	USE_SYSLOG
65 	'Y',
66 #endif
67 #ifdef INET6
68 	'6',
69 #endif
70 #ifdef STRIPBADWORDS
71 	'X',
72 #endif
73 #ifdef USE_SSL
74 	'e',
75 #endif
76 #ifndef NO_OPEROVERRIDE
77 	'O',
78 #endif
79 #ifndef OPEROVERRIDE_VERIFY
80 	'o',
81 #endif
82 #ifdef ZIP_LINKS
83 	'Z',
84 #endif
85 #ifdef EXTCMODE
86 	'E',
87 #endif
88 	'\0', /* Don't change those 3 nuls. -- Syzop */
89 	'\0',
90 	'\0'
91 };
92 
93 char *extraflags = NULL;
94 
95 #include "numeric.h"
96 #include "common.h"
97 #include "sys.h"
98 #include "whowas.h"
99 #include "hash.h"
100 #ifndef _WIN32
101 #include <sys/file.h>
102 #endif
103 #ifdef HPUX
104 #include <fcntl.h>
105 #endif
106 #if !defined(ULTRIX) && !defined(SGI) && \
107     !defined(__convex__) && !defined(_WIN32)
108 # include <sys/param.h>
109 #endif
110 #ifdef HPUX
111 # include <sys/syscall.h>
112 # define getrusage(a,b) syscall(SYS_GETRUSAGE, a, b)
113 #endif
114 #ifdef GETRUSAGE_2
115 # ifdef _SOLARIS
116 #  include <sys/time.h>
117 #  ifdef RUSAGEH
118 #   include <sys/rusage.h>
119 #  endif
120 # endif
121 # include <sys/resource.h>
122 #else
123 #  ifdef TIMES_2
124 #   include <sys/times.h>
125 #  endif
126 #endif
127 #ifdef PCS
128 # include <time.h>
129 #endif
130 #ifdef HPUX
131 #include <unistd.h>
132 #endif
133 #include "h.h"
134 
135 #ifndef ssize_t
136 #define ssize_t unsigned int
137 #endif
138 
flag_add(char ch)139 void	flag_add(char ch)
140 {
141 	char *newextra;
142 	if (extraflags)
143 	{
144 		char tmp[2] = { ch, 0 };
145 		newextra = (char *)MyMalloc(strlen(extraflags) + 2);
146 		strcpy(newextra, extraflags);
147 		strcat(newextra, tmp);
148 		MyFree(extraflags);
149 		extraflags = newextra;
150 	}
151 	else
152 	{
153 		extraflags = malloc(2);
154 		extraflags[0] = ch;
155 		extraflags[1] = 0;
156 	}
157 }
158 
flag_del(char ch)159 void	flag_del(char ch)
160 {
161 	int newsz;
162 	char *p, *op;
163 	char *newflags;
164 	newsz = 0;
165 	p = extraflags;
166 	for (newsz = 0, p = extraflags; *p; p++)
167 		if (*p != ch)
168 			newsz++;
169 	newflags = MyMalloc(newsz + 1);
170 	for (p = newflags, op = extraflags; (*op) && (newsz); newsz--, op++)
171 		if (*op != ch)
172 			*p++ = *op;
173 	*p = '\0';
174 	MyFree(extraflags);
175 	extraflags = newflags;
176 }
177 
178 
179 
180 #ifdef DEBUGMODE
181 #ifndef _WIN32
182 #define SET_ERRNO(x) errno = x
183 #else
184 #define SET_ERRNO(x) WSASetLastError(x)
185 #endif /* _WIN32 */
186 
187 static char debugbuf[4096];
188 
189 #ifndef	USE_VARARGS
190 /*VARARGS2*/
debug(level,form,p1,p2,p3,p4,p5,p6,p7,p8,p9,p10)191 void debug(level, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10)
192 	int  level;
193 	char *form, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8, *p9, *p10;
194 {
195 #else
196 void debug(int level, char *form, ...)
197 #endif
198 {
199 	int err = ERRNO;
200 
201 	va_list vl;
202 	va_start(vl, form);
203 
204 	if ((debuglevel >= 0) && (level <= debuglevel))
205 	{
206 #ifndef USE_VARARGS
207 		(void)ircsprintf(debugbuf, form, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10);
208 #else
209 		(void)ircvsprintf(debugbuf, form, vl);
210 #if 0
211 # ifdef _WIN32
212 		strcat(debugbuf,"\r\n");
213 # endif
214 #endif
215 #endif
216 
217 #if 0
218 		if (local[2])
219 		{
220 			local[2]->sendM++;
221 			local[2]->sendB += strlen(debugbuf);
222 		}
223 #endif
224 #ifndef _WIN32
225 		(void)fprintf(stderr, "%s", debugbuf);
226 		(void)fputc('\n', stderr);
227 #else
228 //# ifndef _WIN32GUI
229 //		Cio_Puts(hCio, debugbuf, strlen(debugbuf));
230 //# else
231 		strcat(debugbuf, "\r\n");
232 		OutputDebugString(debugbuf);
233 //# endif
234 #endif
235 	}
236 	va_end(vl);
237 	SET_ERRNO(err);
238 }
239 
240 /*
241  * This is part of the STATS replies. There is no offical numeric for this
242  * since this isnt an official command, in much the same way as HASH isnt.
243  * It is also possible that some systems wont support this call or have
244  * different field names for "struct rusage".
245  * -avalon
246  */
247 void send_usage(aClient *cptr, char *nick)
248 {
249 
250 #ifdef GETRUSAGE_2
251 	struct rusage rus;
252 	time_t secs, rup;
253 #ifdef	hz
254 # define hzz hz
255 #else
256 # ifdef HZ
257 #  define hzz HZ
258 # else
259 	int  hzz = 1;
260 #  ifdef HPUX
261 	hzz = (int)sysconf(_SC_CLK_TCK);
262 #  endif
263 # endif
264 #endif
265 
266 	if (getrusage(RUSAGE_SELF, &rus) == -1)
267 	{
268 		sendto_one(cptr, ":%s NOTICE %s :Getruseage error: %s.",
269 		    me.name, nick, strerror(errno));
270 		return;
271 	}
272 	secs = rus.ru_utime.tv_sec + rus.ru_stime.tv_sec;
273 	rup = TStime() - me.since;
274 	if (secs == 0)
275 		secs = 1;
276 
277 	sendto_one(cptr,
278 	    ":%s %d %s :CPU Secs %ld:%ld User %ld:%ld System %ld:%ld",
279 	    me.name, RPL_STATSDEBUG, nick, secs / 60, secs % 60,
280 	    rus.ru_utime.tv_sec / 60, rus.ru_utime.tv_sec % 60,
281 	    rus.ru_stime.tv_sec / 60, rus.ru_stime.tv_sec % 60);
282 	sendto_one(cptr, ":%s %d %s :RSS %ld ShMem %ld Data %ld Stack %ld",
283 	    me.name, RPL_STATSDEBUG, nick, rus.ru_maxrss,
284 	    rus.ru_ixrss / (rup * hzz), rus.ru_idrss / (rup * hzz),
285 	    rus.ru_isrss / (rup * hzz));
286 	sendto_one(cptr, ":%s %d %s :Swaps %ld Reclaims %ld Faults %ld",
287 	    me.name, RPL_STATSDEBUG, nick, rus.ru_nswap,
288 	    rus.ru_minflt, rus.ru_majflt);
289 	sendto_one(cptr, ":%s %d %s :Block in %ld out %ld",
290 	    me.name, RPL_STATSDEBUG, nick, rus.ru_inblock, rus.ru_oublock);
291 	sendto_one(cptr, ":%s %d %s :Msg Rcv %ld Send %ld",
292 	    me.name, RPL_STATSDEBUG, nick, rus.ru_msgrcv, rus.ru_msgsnd);
293 	sendto_one(cptr, ":%s %d %s :Signals %ld Context Vol. %ld Invol %ld",
294 	    me.name, RPL_STATSDEBUG, nick, rus.ru_nsignals,
295 	    rus.ru_nvcsw, rus.ru_nivcsw);
296 #else
297 # ifdef TIMES_2
298 	struct tms tmsbuf;
299 	time_t secs, mins;
300 	int  hzz = 1, ticpermin;
301 	int  umin, smin, usec, ssec;
302 
303 #  ifdef HPUX
304 	hzz = sysconf(_SC_CLK_TCK);
305 #  endif
306 	ticpermin = hzz * 60;
307 
308 	umin = tmsbuf.tms_utime / ticpermin;
309 	usec = (tmsbuf.tms_utime % ticpermin) / (float)hzz;
310 	smin = tmsbuf.tms_stime / ticpermin;
311 	ssec = (tmsbuf.tms_stime % ticpermin) / (float)hzz;
312 	secs = usec + ssec;
313 	mins = (secs / 60) + umin + smin;
314 	secs %= hzz;
315 
316 	if (times(&tmsbuf) == -1)
317 	{
318 		sendto_one(cptr, ":%s %d %s :times(2) error: %s.",
319 		    me.name, RPL_STATSDEBUG, nick, STRERROR(ERRNO));
320 		return;
321 	}
322 	secs = tmsbuf.tms_utime + tmsbuf.tms_stime;
323 
324 	sendto_one(cptr,
325 	    ":%s %d %s :CPU Secs %d:%d User %d:%d System %d:%d",
326 	    me.name, RPL_STATSDEBUG, nick, mins, secs, umin, usec, smin, ssec);
327 # endif
328 #endif
329 	sendto_one(cptr, ":%s %d %s :Reads %d Writes %d",
330 	    me.name, RPL_STATSDEBUG, nick, readcalls, writecalls);
331 	sendto_one(cptr, ":%s %d %s :DBUF alloc %d blocks %d",
332 	    me.name, RPL_STATSDEBUG, nick, dbufalloc, dbufblocks);
333 	sendto_one(cptr,
334 	    ":%s %d %s :Writes:  <0 %d 0 %d <16 %d <32 %d <64 %d",
335 	    me.name, RPL_STATSDEBUG, nick,
336 	    writeb[0], writeb[1], writeb[2], writeb[3], writeb[4]);
337 	sendto_one(cptr,
338 	    ":%s %d %s :<128 %d <256 %d <512 %d <1024 %d >1024 %d",
339 	    me.name, RPL_STATSDEBUG, nick,
340 	    writeb[5], writeb[6], writeb[7], writeb[8], writeb[9]);
341 	return;
342 }
343 
344 int checkprotoflags(aClient *sptr, int flags, char *file, int line)
345 {
346 	if (!MyConnect(sptr))
347 		ircd_log(LOG_ERROR, "[Debug] [BUG] ERROR: %s:%d: IsToken(<%s>,%d) on remote client",
348 		         file, line, sptr->name, flags);
349 	return (sptr->proto & flags) ? 1 : 0;
350 }
351 #endif
352