/* * Copyright © 2005-2007 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions of the * GNU General Public License v.2. This program is distributed in the hope * that it will be useful, but WITHOUT ANY WARRANTY expressed or implied, * including the implied warranties of MERCHANTABILITY or FITNESS FOR A * PARTICULAR PURPOSE. See the GNU General Public License for more details. * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat * trademarks that are incorporated in the source code or documentation are not * subject to the GNU General Public License and may only be used or replicated * with the express permission of Red Hat, Inc. * * Red Hat Author(s): Nathan Straz * Dean Jansa */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "btime_int.h" static unsigned int get_btime(void); int main(int argc, char **argv) { int sd; char inmsg[BTIME_MSGLEN]; char btimeonly[BTIME_MSGLEN]; char cookiemsg[BTIME_MSGLEN]; char *outmsg; struct sockaddr_storage cli_addr; socklen_t cli_addr_len; ssize_t nbytes; unsigned int local_btime; openlog("btimed", LOG_PID, LOG_USER); /* Running out of (x)inetd the socket was duped onto stdin. */ sd = fileno(stdin); /* Generate the standard btime message */ memset(btimeonly, 0, BTIME_MSGLEN); local_btime = get_btime(); sprintf(btimeonly, "%u\n", local_btime); syslog(LOG_INFO, "started with btime = %u", local_btime); for (;;) { memset(&cli_addr, 0, sizeof cli_addr); memset(inmsg, 0, BTIME_MSGLEN); cli_addr_len = sizeof cli_addr; nbytes = recvfrom(sd, &inmsg, BTIME_MSGLEN, MSG_WAITALL, (struct sockaddr *)&cli_addr, &cli_addr_len); if (nbytes < 0) { /* Bail if we get an error. client side resends * request, no need to retry here. */ syslog(LOG_INFO, "exitting"); exit(0); } if (inmsg[0] == 'B' && inmsg[1] == 'T' ) { /* New style heartbeat with cookie */ /* Copy cookie to message and append timestamp */ memset(cookiemsg, 0, BTIME_MSGLEN); memcpy(cookiemsg, inmsg, COOKIE_LEN); strcpy(cookiemsg + COOKIE_LEN, btimeonly); outmsg = cookiemsg; } else { outmsg = btimeonly; } sendto(sd, outmsg, BTIME_MSGLEN, MSG_DONTWAIT, (struct sockaddr *)&cli_addr, cli_addr_len); } return 0; } /* *--------------------------------------------------------------------------- * * get_btime -- * * Return machine's boot time rounded up to the nearest five seconds. * * Returns: * 0 on failure * non-zero on success. * *--------------------------------------------------------------------------- */ static unsigned int get_btime(void) { unsigned int btime = 0; long hertz = sysconf(_SC_CLK_TCK); btime = time(0); if (access("/proc/uptime", F_OK | R_OK) == 0) { FILE *proc_uptime; unsigned long upsec = 0; proc_uptime = fopen("/proc/uptime", "r"); fscanf(proc_uptime, "%lu.%*u %*u.%*u\n", &upsec); fclose(proc_uptime); btime -= upsec; } else { struct tms tms; btime -= (times(&tms) / hertz); } return btime; }