/usr.bin/rup/rup.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 254 lines · 180 code · 40 blank · 34 comment · 37 complexity · b1f65da25ad85ac59b052a83ecae36d0 MD5 · raw file

  1. /*-
  2. * Copyright (c) 1993, John Brezak
  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. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. #include <sys/cdefs.h>
  34. __FBSDID("$FreeBSD$");
  35. #include <sys/param.h>
  36. #include <sys/socket.h>
  37. #include <rpc/rpc.h>
  38. #include <rpc/pmap_clnt.h>
  39. #undef FSHIFT /* Use protocol's shift and scale values */
  40. #undef FSCALE
  41. #include <rpcsvc/rstat.h>
  42. #include <arpa/inet.h>
  43. #include <err.h>
  44. #include <netdb.h>
  45. #include <stdio.h>
  46. #include <string.h>
  47. #include <stdlib.h>
  48. #include <time.h>
  49. #include <unistd.h>
  50. #define HOST_WIDTH 15
  51. struct host_list {
  52. struct host_list *next;
  53. struct in_addr addr;
  54. } *hosts;
  55. static int
  56. search_host(struct in_addr addr)
  57. {
  58. struct host_list *hp;
  59. if (!hosts)
  60. return(0);
  61. for (hp = hosts; hp != NULL; hp = hp->next) {
  62. if (hp->addr.s_addr == addr.s_addr)
  63. return(1);
  64. }
  65. return(0);
  66. }
  67. static void
  68. remember_host(struct in_addr addr)
  69. {
  70. struct host_list *hp;
  71. if (!(hp = (struct host_list *)malloc(sizeof(struct host_list))))
  72. errx(1, "no memory");
  73. hp->addr.s_addr = addr.s_addr;
  74. hp->next = hosts;
  75. hosts = hp;
  76. }
  77. static bool_t
  78. rstat_reply(caddr_t replyp, struct sockaddr_in *raddrp)
  79. {
  80. struct tm *tmp_time;
  81. struct tm host_time;
  82. struct tm host_uptime;
  83. char days_buf[16];
  84. char hours_buf[16];
  85. struct hostent *hp;
  86. char *host;
  87. statstime *host_stat = (statstime *)replyp;
  88. time_t tmp_time_t;
  89. if (search_host(raddrp->sin_addr))
  90. return(0);
  91. hp = gethostbyaddr((char *)&raddrp->sin_addr.s_addr,
  92. sizeof(struct in_addr), AF_INET);
  93. if (hp)
  94. host = hp->h_name;
  95. else
  96. host = inet_ntoa(raddrp->sin_addr);
  97. /* truncate hostname to fit nicely into field */
  98. if (strlen(host) > HOST_WIDTH)
  99. host[HOST_WIDTH] = '\0';
  100. printf("%-*s\t", HOST_WIDTH, host);
  101. if (sizeof(time_t) == sizeof(host_stat->curtime.tv_sec)) {
  102. tmp_time = localtime((time_t *)&host_stat->curtime.tv_sec);
  103. host_time = *tmp_time;
  104. host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
  105. tmp_time = gmtime((time_t *)&host_stat->curtime.tv_sec);
  106. host_uptime = *tmp_time;
  107. }
  108. else { /* non-32-bit time_t */
  109. tmp_time_t = host_stat->curtime.tv_sec;
  110. tmp_time = localtime(&tmp_time_t);
  111. host_time = *tmp_time;
  112. host_stat->curtime.tv_sec -= host_stat->boottime.tv_sec;
  113. tmp_time_t = host_stat->curtime.tv_sec;
  114. tmp_time = gmtime(&tmp_time_t);
  115. host_uptime = *tmp_time;
  116. }
  117. #define updays (host_stat->curtime.tv_sec / 86400)
  118. if (host_uptime.tm_yday != 0)
  119. sprintf(days_buf, "%3d day%s, ", updays,
  120. (updays > 1) ? "s" : "");
  121. else
  122. days_buf[0] = '\0';
  123. if (host_uptime.tm_hour != 0)
  124. sprintf(hours_buf, "%2d:%02d, ",
  125. host_uptime.tm_hour, host_uptime.tm_min);
  126. else
  127. if (host_uptime.tm_min != 0)
  128. sprintf(hours_buf, "%2d mins, ", host_uptime.tm_min);
  129. else if (host_stat->curtime.tv_sec < 60)
  130. sprintf(hours_buf, "%2d secs, ", host_uptime.tm_sec);
  131. else
  132. hours_buf[0] = '\0';
  133. printf(" %2d:%02d%cm up %9.9s%9.9s load average: %.2f %.2f %.2f\n",
  134. (host_time.tm_hour % 12) ? host_time.tm_hour % 12 : 12,
  135. host_time.tm_min,
  136. (host_time.tm_hour >= 12) ? 'p' : 'a',
  137. days_buf,
  138. hours_buf,
  139. (double)host_stat->avenrun[0]/FSCALE,
  140. (double)host_stat->avenrun[1]/FSCALE,
  141. (double)host_stat->avenrun[2]/FSCALE);
  142. remember_host(raddrp->sin_addr);
  143. return(0);
  144. }
  145. static int
  146. onehost(char *host)
  147. {
  148. CLIENT *rstat_clnt;
  149. statstime host_stat;
  150. struct sockaddr_in addr;
  151. struct hostent *hp;
  152. struct timeval tv;
  153. hp = gethostbyname(host);
  154. if (hp == NULL) {
  155. warnx("unknown host \"%s\"", host);
  156. return(-1);
  157. }
  158. rstat_clnt = clnt_create(host, RSTATPROG, RSTATVERS_TIME, "udp");
  159. if (rstat_clnt == NULL) {
  160. warnx("%s %s", host, clnt_spcreateerror(""));
  161. return(-1);
  162. }
  163. bzero((char *)&host_stat, sizeof(host_stat));
  164. tv.tv_sec = 15; /* XXX ??? */
  165. tv.tv_usec = 0;
  166. if (clnt_call(rstat_clnt, RSTATPROC_STATS,
  167. (xdrproc_t)xdr_void, NULL,
  168. (xdrproc_t)xdr_statstime, &host_stat, tv) != RPC_SUCCESS) {
  169. warnx("%s: %s", host, clnt_sperror(rstat_clnt, host));
  170. clnt_destroy(rstat_clnt);
  171. return(-1);
  172. }
  173. addr.sin_addr.s_addr = *(int *)hp->h_addr;
  174. rstat_reply((caddr_t)&host_stat, &addr);
  175. clnt_destroy(rstat_clnt);
  176. return (0);
  177. }
  178. static void
  179. allhosts(void)
  180. {
  181. statstime host_stat;
  182. enum clnt_stat clnt_stat;
  183. clnt_stat = clnt_broadcast(RSTATPROG, RSTATVERS_TIME, RSTATPROC_STATS,
  184. (xdrproc_t)xdr_void, NULL,
  185. (xdrproc_t)xdr_statstime, &host_stat,
  186. (resultproc_t)rstat_reply);
  187. if (clnt_stat != RPC_SUCCESS && clnt_stat != RPC_TIMEDOUT)
  188. errx(1, "%s", clnt_sperrno(clnt_stat));
  189. }
  190. static void
  191. usage(void)
  192. {
  193. fprintf(stderr, "usage: rup [host ...]\n");
  194. exit(1);
  195. }
  196. int
  197. main(int argc, char *argv[])
  198. {
  199. int ch;
  200. while ((ch = getopt(argc, argv, "?")) != -1)
  201. switch (ch) {
  202. default:
  203. usage();
  204. /*NOTREACHED*/
  205. }
  206. setlinebuf(stdout);
  207. if (argc == optind)
  208. allhosts();
  209. else {
  210. for (; optind < argc; optind++)
  211. (void) onehost(argv[optind]);
  212. }
  213. exit(0);
  214. }