pst3.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*****************************************************************************
  2. *
  3. * pst3
  4. *
  5. * License: GPL
  6. * Copyright (c) 2008 Nagios Plugin Development Team
  7. *
  8. * Description:
  9. *
  10. * This file contains the pst3 executable. This is a replacement ps command
  11. * for Solaris to get output which provides a long argument listing, which
  12. * is not possible with the standard ps command (due to truncation). /usr/ucb/ps
  13. * also has issues where some fields run into each other.
  14. *
  15. * This executable works by reading the kernel memory structures, so needs
  16. * to be executed as root
  17. *
  18. * Originally written by R.W.Ingraham
  19. *
  20. * This program is free software: you can redistribute it and/or modify
  21. * it under the terms of the GNU General Public License as published by
  22. * the Free Software Foundation, either version 3 of the License, or
  23. * (at your option) any later version.
  24. *
  25. * This program is distributed in the hope that it will be useful,
  26. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  27. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  28. * GNU General Public License for more details.
  29. *
  30. * You should have received a copy of the GNU General Public License
  31. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  32. *
  33. *****************************************************************************/
  34. #define _KMEMUSER 1
  35. #include <kvm.h>
  36. #include <sys/param.h>
  37. #include <sys/user.h>
  38. #include <sys/time.h>
  39. #include <sys/proc.h>
  40. #include <sys/types.h>
  41. #include <sys/stat.h>
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <unistd.h>
  45. #include <string.h>
  46. #include <procfs.h>
  47. #include <fcntl.h>
  48. #include <dirent.h>
  49. #include <errno.h>
  50. /*
  51. * Constants
  52. */
  53. #define PROC_DIR "/proc"
  54. #define MAX_PATH 1024
  55. #define OK 0
  56. #define FAIL NULL
  57. /*
  58. * Structures
  59. */
  60. /*
  61. * Globals
  62. */
  63. static char * szProg;
  64. static kvm_t * kd;
  65. static struct proc * pProc;
  66. static struct user * pUser;
  67. static char ** myArgv;
  68. /*
  69. * Prototypes
  70. */
  71. static int output_info(struct proc *proc_kvm, psinfo_t procinfo,char **proc_argv);
  72. static psinfo_t get_procinfo(struct proc *proc);
  73. static int HandleProc(struct proc *proc);
  74. /*----------------------------------------------------------------------------*/
  75. int main (int argc, char **argv)
  76. {
  77. DIR *pDir;
  78. struct dirent *pDent;
  79. int retcode = 0;
  80. struct proc *proc;
  81. struct pid pid;
  82. /* Set our program name global */
  83. if ((szProg = strrchr(argv[0], '/')) != NULL)
  84. szProg++;
  85. else
  86. szProg = argv[0];
  87. /* Make sure that our euid is root */
  88. if (geteuid() != 0)
  89. {
  90. fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
  91. exit(1);
  92. }
  93. /* Get a handle to the running kernel image */
  94. if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
  95. {
  96. fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
  97. exit(2);
  98. }
  99. /* reset to first proc in list */
  100. if(kvm_setproc(kd) == -1) {
  101. perror("kvm_setproc");
  102. exit(2);
  103. }
  104. /* Display column headings */
  105. printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
  106. 'S',
  107. "UID",
  108. "PID",
  109. "PPID",
  110. "VSZ",
  111. "RSS",
  112. "%CPU",
  113. "COMMAND",
  114. "ARGS"
  115. );
  116. /* Zip through all of the process entries */
  117. while((proc = kvm_nextproc(kd)) != 0) {
  118. HandleProc(proc);
  119. }
  120. /* Close the handle to the running kernel image */
  121. kvm_close(kd);
  122. return retcode;
  123. }
  124. /*----------------------------------------------------------------------------*/
  125. static int HandleProc(struct proc *proc)
  126. {
  127. struct pid pid;
  128. struct user *user;
  129. psinfo_t procinfo;
  130. char **proc_argv = 0;
  131. if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
  132. perror("kvm_read error");
  133. exit(2);
  134. }
  135. proc->p_pidp = &pid;
  136. user = kvm_getu(kd, proc);
  137. if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
  138. return FAIL;
  139. }
  140. procinfo = get_procinfo(proc);
  141. return output_info(proc, procinfo, proc_argv);
  142. }
  143. static psinfo_t get_procinfo(struct proc *proc)
  144. {
  145. char procpath[MAX_PATH];
  146. psinfo_t procinfo;
  147. int fd, len;
  148. sprintf(procpath, "/proc/%d/psinfo", proc->p_pidp->pid_id);
  149. if ((fd = open(procpath, O_RDONLY)) >= 0)
  150. {
  151. if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
  152. {
  153. fprintf(stderr,"%s: Read error of psingo structure (%d)\n", procpath, len);
  154. exit(2);
  155. }
  156. close(fd);
  157. }
  158. return procinfo;
  159. }
  160. static int output_info(struct proc *proc_kvm, psinfo_t procinfo, char **proc_argv)
  161. {
  162. char *procname;
  163. int i;
  164. if((procname = strrchr(proc_argv[0], '/')) != NULL)
  165. procname++;
  166. else
  167. procname = proc_argv[0];
  168. printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
  169. procinfo.pr_lwp.pr_sname,
  170. (int)(procinfo.pr_euid),
  171. (int)proc_kvm->p_pidp->pid_id,
  172. (int)proc_kvm->p_ppid,
  173. (unsigned long)(procinfo.pr_size),
  174. (unsigned long)(procinfo.pr_rssize),
  175. ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
  176. procname
  177. );
  178. for(i=0;proc_argv[i];i++) {
  179. printf(" %s", proc_argv[i]);
  180. }
  181. printf("\n");
  182. return OK;
  183. }