8ab32692a462ff05b94e7260c90a9bc01f8a6121
[remotetop.git] / sendtop.c
1 /*
2  * Copyright (c) 2004 Teodor Sigaev <teodor@sigaev.ru>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *      notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *      notice, this list of conditions and the following disclaimer in the
12  *      documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the author nor the names of any co-contributors
14  *      may be used to endorse or promote products derived from this software
15  *      without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
18  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
23  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <unistd.h>
34 #include <signal.h>
35 #include <errno.h>
36 #include <sys/sysctl.h>
37
38 #include "tlog.h"
39 #include "tmalloc.h"
40 #include "connection.h"
41
42 #include "top.h"
43
44 #define NITEM   0
45
46 static int
47 getsysctl(char *name, void *ptr, size_t len) {
48         size_t nlen = len;
49         if (sysctlbyname(name, ptr, &nlen, NULL, 0) == -1) {
50                 tlog(TL_ALARM, "sysctl(%s...) failed: %s\n", name,
51                         strerror(errno));
52                 return 1;
53         }   
54         if (nlen != len) {
55                 tlog(TL_ALARM, "sysctl(%s...) expected %lu, got %lu\n", name,
56                         (unsigned long)len, (unsigned long)nlen);
57                 return 1;
58         }
59         return 0;
60 }
61
62
63 #define GETSYSCTL(name, var) getsysctl(name, &(var), sizeof(var))
64
65 static void
66 fillMsgTop(TCMsgTop *m) {
67         double lll[3];
68         int    memory_tmp;
69
70         memset(m,0,sizeof(TCMsgTop));
71         if ( getloadavg(lll,3) >= NITEM+1 )
72                 m->load=lll[NITEM];
73         else
74                 m->load=-1.0;
75
76         m->freemem = 0;
77         if ( GETSYSCTL("vm.stats.vm.v_inactive_count", memory_tmp) == 0 )
78                 m->freemem += memory_tmp;
79         else
80                 m->freemem = -1;
81         if ( m->freemem>=0 && GETSYSCTL("vm.stats.vm.v_cache_count", memory_tmp) == 0 )
82                 m->freemem += memory_tmp;
83         else
84                 m->freemem = -1;
85         if ( m->freemem>=0 && GETSYSCTL("vm.stats.vm.v_free_count", memory_tmp) == 0 )
86                 m->freemem += memory_tmp;
87         else
88                 m->freemem = -1;
89
90         if (  m->freemem>=0 )
91                 m->freemem *= getpagesize();
92          
93         m->usermem =-1;
94         if ( GETSYSCTL("hw.usermem", memory_tmp) == 0 )
95                 m->usermem = memory_tmp;
96
97         tlog( TL_DEBUG, "Sended topdata: %.2f load, %d free, %d total", m->load, m->freemem, m->usermem);
98 }
99
100 static int
101 sendTop(Msg *msg) {
102         TCMsg *pmsg;
103
104         if ( !msg->msg ) {
105                 int msglen = TCMSGHDRSZ + sizeof(TCMsgTop);
106                 pmsg = (TCMsg*)tmalloc(msglen);
107                 pmsg->len = msglen;
108                 pmsg->type=TOPMSGTYPE;
109                 msg->msg = pmsg;
110         } else {
111                 pmsg = msg->msg;
112         }
113
114         fillMsgTop( (TCMsgTop*)(pmsg->data) );
115
116         return TC_sendMsg(msg);
117 }
118
119
120 extern char *optarg;
121 int
122 main( int argc, char *argv[] ) {
123         int ch;
124         Msg     msg;
125         int debug=0, child=0;
126         int period=30;
127
128         msg.port        = TOPD_SERVER_DEFAULT_PORT;
129         msg.host        = "127.0.0.1";
130         msg.msg = NULL;
131         msg.sockfd =-1;
132
133         while( (ch=getopt(argc, argv, "h:p:s:D"))!=-1) {
134                 switch(ch) {
135                         case 'h':
136                                 msg.host = strdup(optarg);
137                                 break;
138                         case 'p':
139                                 msg.port = atoi(optarg);
140                                 break;
141                         case 's':
142                                 period = atoi(optarg);
143                                 break;
144                         case 'D':
145                                 debug=1;
146                                 break;
147                         default:
148                                 return 1;
149                 }
150         }
151
152         signal(SIGCHLD, SIG_IGN);
153
154         if ( debug )
155                 opentlog( TL_OPEN_STDERR,  TL_DEBUG, NULL);
156         else
157                 opentlog( TL_OPEN_SYSLOG, TL_INFO, NULL);
158
159         if ( debug || (child = fork()) == 0 ) {
160                 while(1) {
161                         sendTop(&msg);
162                         sleep(period);  
163                 }
164                 TC_closefd(&msg);       
165         }
166         
167         if (child == -1)
168                 tlog(TL_CRIT|TL_EXIT, "Can't start child process: %s", strerror(errno));
169
170         return (0);
171 }