1 /*
2 **
3 ** Copyright (c) 2010-2017 The SquirrelMail Project Team
4 ** Copyright (c) 2002-2010 Dave McMurtrie
5 **
6 ** Licensed under the GNU GPL. For full terms see the file COPYING.
7 **
8 ** This file is part of SquirrelMail IMAP Proxy.
9 **
10 **  Facility:
11 **
12 **	pimpstat.c
13 **
14 **  Abstract:
15 **
16 **	Polling Imap Mail Proxy STATistical display tool.
17 **
18 **  Authors:
19 **
20 **      Dave McMurtrie <davemcmurtrie@hotmail.com>
21 **
22 **  Version:
23 **
24 **      $Id: pimpstat.c 14647 2017-01-27 20:53:57Z pdontthink $
25 **
26 **  Modification History:
27 **
28 **      $Log$
29 **
30 **      Revision 1.9  2006/02/17 01:42:37  dave64
31 **      Spelling correction (Connectsions) by Matt Selsky.
32 **
33 **      Revision 1.8  2005/06/15 12:11:36  dgm
34 **      Patch by Mathew Anderson to add -c flag and behavior.
35 **
36 **      Revision 1.7  2004/02/24 14:56:10  dgm
37 **      Added SELECT cache stuff.
38 **
39 **      Revision 1.6  2003/05/20 19:08:02  dgm
40 **      Comment changes only.
41 **
42 **      Revision 1.5  2003/05/15 11:33:22  dgm
43 **      Patch by Ken Murchison <ken@oceana.com> to clean up build process:
44 **      Conditionally include <sys/param.h> instead of defining MAXPATHLEN.
45 **
46 **      Revision 1.4  2003/05/13 11:41:02  dgm
47 **      Patches by Ken Murchison <ken@oceana.com> to clean up build process.
48 **
49 **      Revision 1.3  2003/01/27 13:49:36  dgm
50 **      Added patch by Frode Nordahl <frode@powertech.no> to allow
51 **      compilation on Linux platforms.
52 **
53 **      Revision 1.2  2002/12/17 14:24:11  dgm
54 **      Added support for global configuration structure.
55 **
56 **      Revision 1.1  2002/08/30 13:32:55  dgm
57 **      Initial revision
58 **
59 */
60 
61 
62 #include "imapproxy.h"
63 #include <errno.h>
64 #include <stdlib.h>
65 #include <string.h>
66 #include <sys/mman.h>
67 #include <sys/types.h>
68 #include <sys/stat.h>
69 #include <fcntl.h>
70 #include <curses.h>
71 #include <time.h>
72 #include <strings.h>
73 #include <signal.h>
74 
75 #if HAVE_SYS_PARAM_H
76 #include <sys/param.h>
77 #endif
78 
79 #if HAVE_UNISTD_H
80 #include <unistd.h>
81 #endif
82 
83 #define DIGITS 11
84 
85 extern WINDOW *stdscr;
86 
87 static void Exit( int );
88 static void Handler();
89 static void Usage( void );
90 
91 
92 ProxyConfig_Struct PC_Struct;
93 
94 
95 /*++
96  * Function:	Exit
97  *
98  * Purpose:	Set the terminal back to normal and then exit
99  *
100  * Parameters:	int -- exit code to be passed to exit()
101  *
102  * Returns:	nada
103  *
104  * Authors:	Dave McMurtrie <davemcmurtrie@hotmail.com>
105  *
106  * Notes:
107  *--
108  */
Exit(int ExitCode)109 static void Exit( int ExitCode )
110 {
111     clear();
112     refresh();
113     endwin();
114     exit( ExitCode );
115 }
116 
117 
118 /*++
119  * Function:	Handler
120  *
121  * Purpose:	SIGINT handler routine
122  *
123  * Parameters:	nada
124  *
125  * Returns:	nada
126  *
127  * Authors:	Dave McMurtrie <davemcmurtrie@hotmail.com>
128  *
129  * Notes:
130  *--
131  */
Handler()132 static void Handler()
133 {
134     Exit( 0 );
135 }
136 
137 
138 
main(int argc,char * argv[])139 int main( int argc, char *argv[] )
140 {
141     IMAPCounter_Struct *IMAPCount;
142     int fd;
143     char *fn = "pimpstat";
144     int i, command;
145     char ccc[DIGITS+1];  /* current client conns */
146     char pcc[DIGITS+1];  /* peak client conns */
147     char asc[DIGITS+1];  /* active server conns */
148     char psc[DIGITS+1];  /* peak server conns */
149     char rsc[DIGITS+1];  /* retained (cached) server conns */
150     char prsc[DIGITS+1]; /* peak retained (cached) server conns */
151     char tcca[DIGITS+1]; /* total client connections accepted */
152     char tcl[DIGITS+1];  /* total client logins */
153     char tscc[DIGITS+1]; /* total server conns created */
154     char tscr[DIGITS+1]; /* total server conns reused */
155     char ssrr[DIGITS+4]; /* server socket reuse ration */
156     char tsch[DIGITS+1]; /* total select cache hits */
157     char tscm[DIGITS+1]; /* total select cache misses */
158     float Ratio;
159     char stimebuf[64];
160     char ctimebuf[64];
161     char *CP;
162     extern char *optarg;
163     extern int optind;
164     char ConfigFile[ MAXPATHLEN ];
165 
166     ConfigFile[0] = '\0';
167 
168     signal( SIGINT, (void (*)()) Handler );
169 
170     command = 0;
171 
172     while (( i = getopt( argc, argv, "f:ch" ) ) != EOF )
173     {
174 
175         switch( i )
176         {
177 
178         case 'f':
179             /* user specified a config filename */
180             strncpy( ConfigFile, optarg, sizeof ConfigFile -1 );
181             break;
182 
183 	case 'c':
184 	    /* user wants output via command line */
185 	    command=1;
186 	    break;
187 
188         case 'h':
189             Usage();
190             exit( 0 );
191 
192         case '?':
193             Usage();
194 
195             exit( 1 );
196 
197         }
198 
199     }
200 
201     if ( ! ConfigFile[0] )
202     {
203 
204         strncpy( ConfigFile, DEFAULT_CONFIG_FILE, sizeof ConfigFile -1 );
205     }
206 
207     SetConfigOptions( ConfigFile );
208 
209     fd = open( PC_Struct.stat_filename, O_RDONLY );
210     if ( fd == -1 )
211     {
212         printf("%s: open() failed for '%s': %s -- Exiting.\n", fn,
213                PC_Struct.stat_filename, strerror( errno ) );
214         exit( 1 );
215     }
216 
217 
218     IMAPCount = ( IMAPCounter_Struct *)mmap( 0, sizeof( IMAPCounter_Struct ),
219                                              PROT_READ, MAP_SHARED, fd, 0 );
220 
221     if ( IMAPCount == MAP_FAILED )
222     {
223         printf("%s: mmap() failed: %s -- Exiting.\n", fn, strerror( errno ) );
224         exit( 1 );
225     }
226 
227 
228     if ( command == 0 )
229     {
230 	stdscr = initscr();
231 
232 	if ( !stdscr )
233 	{
234 	    printf("%s: failed to initialize screen -- exiting.\n", fn );
235 	    exit( 1 );
236 	}
237 
238 	border( 0, 0, 0, 0, 0, 0, 0, 0 );
239 	mvaddstr( 2, 8, "Server Start Time:" );
240 	mvaddstr( 3, 2, "Last Counter Reset Time:" );
241 	mvaddstr( 5, 2, "CLIENT CONNECTIONS" );
242 	mvaddstr( 7, 5, "current:" );
243 	mvaddstr( 7, 40, "peak:" );
244 	mvaddstr( 9, 2, "ACTIVE SERVER CONNECTIONS" );
245 	mvaddstr( 11, 5, "current:" );
246 	mvaddstr( 11, 40, "peak:" );
247 	mvaddstr( 13, 2, "CACHED SERVER CONNECTIONS" );
248 	mvaddstr( 15, 5, "current:");
249 	mvaddstr( 15, 40, "peak:" );
250 	mvaddstr( 17, 2, "CONNECTION TOTALS" );
251 	mvaddstr( 19, 5, "client connections accepted:" );
252 	mvaddstr( 20, 5, "client logins:" );
253 	mvaddstr( 21, 5, "server connections created:" );
254 	mvaddstr( 22, 5, "server connection reuses:" );
255 	mvaddstr( 23, 5, "client login to server login ratio:" );
256 	if ( PC_Struct.enable_select_cache )
257 	{
258 	    mvaddstr( 25, 2, "SELECT CACHE TOTALS" );
259 	    mvaddstr( 27, 5, "hit:" );
260 	    mvaddstr( 27, 40, "miss:" );
261 	}
262 	else
263 	{
264 	    mvaddstr( 25, 2, "SELECT CACHE NOT ENABLED" );
265 	}
266 
267 	mvaddstr( 29, 2, "CTRL-C to quit." );
268 
269 	for ( ; ; )
270 	{
271 	    /*
272 	     * I don't know crap about curses.  There's prolly an easy way to
273 	     * accomplish this, but I don't know how.  Basically we have to
274 	     * turn all of our numbers into strings so curses can display them.
275 	     * I'd guess there's a printf equivalent in curses, but I dunno.
276 	     */
277 
278 	    if ( IMAPCount->TotalServerConnectionsCreated == 0 )
279 	    {
280 		snprintf( ssrr, DIGITS + 3, "          N/A" );
281 	    }
282 	    else
283 	    {
284 		Ratio = (float)IMAPCount->TotalClientLogins /
285 		    (float)IMAPCount->TotalServerConnectionsCreated;
286 		snprintf( ssrr, DIGITS + 3, "%9.2f : 1", Ratio );
287 	    }
288 
289 	    /*
290 	     * ctime is putting a \n at the end of the string and that's
291 	     * making curses do goofy stuff that I don't understand.  Rather
292 	     * than figure out why it's breaking curses, I'm just going to
293 	     * copy ctime's strings into my own buffers and get rid of the
294 	     * \n.
295 	     */
296 	    strncpy( stimebuf, ctime( &IMAPCount->StartTime ),
297 		     sizeof stimebuf - 1 );
298 	    strncpy( ctimebuf, ctime( &IMAPCount->CountTime ),
299 		     sizeof ctimebuf - 1 );
300 
301 	    CP = strrchr( stimebuf, '\n' );
302 	    if (CP)
303 		*CP = '\0';
304 
305 	    CP = strrchr( ctimebuf, '\n' );
306 	    if (CP)
307 		*CP ='\0';
308 
309 	    snprintf( ccc, DIGITS, "%9d", IMAPCount->CurrentClientConnections );
310 	    snprintf( pcc, DIGITS, "%9d", IMAPCount->PeakClientConnections );
311 	    snprintf( asc, DIGITS, "%9d", IMAPCount->InUseServerConnections );
312 	    snprintf( psc, DIGITS, "%9d", IMAPCount->PeakInUseServerConnections );
313 	    snprintf( rsc, DIGITS, "%9d", IMAPCount->RetainedServerConnections );
314 	    snprintf( prsc, DIGITS, "%9d", IMAPCount->PeakRetainedServerConnections );
315 	    snprintf( tcca, DIGITS, "%9d", IMAPCount->TotalClientConnectionsAccepted );
316 	    snprintf( tcl, DIGITS, "%9d", IMAPCount->TotalClientLogins );
317 	    snprintf( tscr, DIGITS, "%9d", IMAPCount->TotalServerConnectionsReused );
318 	    snprintf( tscc, DIGITS, "%9d", IMAPCount->TotalServerConnectionsCreated );
319 	    snprintf( tsch, DIGITS, "%9d", IMAPCount->SelectCacheHits );
320 	    snprintf( tscm, DIGITS, "%9d", IMAPCount->SelectCacheMisses );
321 
322 	    mvaddstr( 2, 31, stimebuf );
323 	    mvaddstr( 3, 31, ctimebuf );
324 	    mvaddstr( 7, 14, ccc );
325 	    mvaddstr( 7, 46, pcc );
326 	    mvaddstr( 11, 14, asc );
327 	    mvaddstr( 11, 46, psc );
328 	    mvaddstr( 15, 14, rsc );
329 	    mvaddstr( 15, 46, prsc );
330 	    mvaddstr( 19, 46, tcca );
331 	    mvaddstr( 20, 46, tcl );
332 	    mvaddstr( 21, 46, tscc );
333 	    mvaddstr( 22, 46, tscr );
334 	    mvaddstr( 23, 42, ssrr );
335 	    if ( PC_Struct.enable_select_cache )
336 	    {
337 		mvaddstr( 27, 14, tsch );
338 		mvaddstr( 27, 46, tscm );
339 	    }
340 
341 	    refresh();
342 
343 	    sleep( 1 );
344 	}
345 
346     }
347     else
348     {
349 	/*
350 	 * We only get here if command is non-zero.
351 	 */
352 	printf( " %d Current Client Connections\n %d Peak Client Connections\n %d In Use Connections\n %d Peak In Use Connections\n %d Retained Server Connections\n %d Peak Retained Server Connections\n %d Total Client Connections\n %d Total Client Logins\n %d Total Reused Connections\n %d Total Created Connections\n %d Cache Hits\n %d Cache Misses\n", IMAPCount->CurrentClientConnections,
353 		IMAPCount->PeakClientConnections,
354 		IMAPCount->InUseServerConnections,
355 		IMAPCount->PeakInUseServerConnections,
356 		IMAPCount->RetainedServerConnections,
357 		IMAPCount->PeakRetainedServerConnections,
358 		IMAPCount->TotalClientConnectionsAccepted,
359 		IMAPCount->TotalClientLogins,
360 		IMAPCount->TotalServerConnectionsReused,
361 		IMAPCount->TotalServerConnectionsCreated,
362 		IMAPCount->SelectCacheHits,
363 		IMAPCount->SelectCacheMisses );
364 
365 	exit( 0 );
366     }
367 }
368 
369 
370 
371 /*++
372  * Function:    Usage
373  *
374  * Purpose:     Display a usage string to stdout
375  *
376  * Parameters:  None.
377  *
378  * Returns:     nada
379  *
380  * Authors:     Dave McMurtrie <davemcmurtrie@hotmail.com>
381  *
382  * Notes:
383  *--
384  */
Usage(void)385 void Usage( void )
386 {
387     printf( "Usage: pimpstat [-f config filename] [-h] [-c]\n" );
388     printf( " -c is for simple command line output format instead of curses.\n" );
389 
390     return;
391 }
392 
393 /*
394  *                            _________
395  *                           /        |
396  *                          /         |
397  *                         /    ______|
398  *                        /    /       ________
399  *                       |    |        |      /
400  *                       |    |        |_____/
401  *                       |    |        ______
402  *                       |    |        |     \
403  *                       |    |        |______\
404  *                        \    \_______
405  *                         \           |
406  *                          \          |
407  *                           \_________|
408  */
409 
410 
411