pst3.c 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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 void output_info(struct proc *proc_kvm,char **proc_argv);
  72. static void HandleProc(struct proc *proc);
  73. /*----------------------------------------------------------------------------*/
  74. int main (int argc, char **argv)
  75. {
  76. DIR *pDir;
  77. struct dirent *pDent;
  78. int retcode = 0;
  79. struct proc *proc;
  80. struct pid pid;
  81. /* Set our program name global */
  82. if ((szProg = strrchr(argv[0], '/')) != NULL)
  83. szProg++;
  84. else
  85. szProg = argv[0];
  86. /* Make sure that our euid is root */
  87. if (geteuid() != 0)
  88. {
  89. fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
  90. exit(1);
  91. }
  92. /* Get a handle to the running kernel image */
  93. if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
  94. {
  95. fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
  96. exit(2);
  97. }
  98. /* reset to first proc in list */
  99. if(kvm_setproc(kd) == -1) {
  100. perror("kvm_setproc");
  101. exit(2);
  102. }
  103. /* Display column headings */
  104. printf("%c %5s %5s %5s %6s %6s %4s %s %s\n",
  105. 'S',
  106. "UID",
  107. "PID",
  108. "PPID",
  109. "VSZ",
  110. "RSS",
  111. "%CPU",
  112. "COMMAND",
  113. "ARGS"
  114. );
  115. /* Zip through all of the process entries */
  116. while((proc = kvm_nextproc(kd)) != 0) {
  117. HandleProc(proc);
  118. }
  119. /* Close the handle to the running kernel image */
  120. kvm_close(kd);
  121. return retcode;
  122. }
  123. /*----------------------------------------------------------------------------*/
  124. static void HandleProc(struct proc *proc)
  125. {
  126. struct pid pid;
  127. struct user *user;
  128. char **proc_argv = NULL;
  129. if(kvm_kread(kd, (unsigned long) proc->p_pidp, (char *) &pid, sizeof pid) == -1) {
  130. perror("kvm_read error");
  131. exit(2);
  132. }
  133. proc->p_pidp = &pid;
  134. user = kvm_getu(kd, proc);
  135. if(kvm_getcmd(kd, proc, user, &proc_argv, NULL) == -1) {
  136. return;
  137. }
  138. if(proc_argv == NULL) {
  139. return;
  140. }
  141. output_info(proc, proc_argv);
  142. free(proc_argv);
  143. }
  144. static void output_info(struct proc *proc_kvm, char **proc_argv)
  145. {
  146. char procpath[MAX_PATH];
  147. psinfo_t procinfo;
  148. int fd, len;
  149. char *procname;
  150. int i;
  151. sprintf(procpath, "/proc/%d/psinfo", proc_kvm->p_pidp->pid_id);
  152. if ((fd = open(procpath, O_RDONLY)) >= 0)
  153. {
  154. if ((len = read(fd, &procinfo, sizeof(procinfo))) != sizeof(procinfo))
  155. {
  156. fprintf(stderr,"%s: Read error of psinfo structure (%d)\n", procpath, len);
  157. exit(2);
  158. }
  159. close(fd);
  160. }
  161. if((procname = strrchr(proc_argv[0], '/')) != NULL)
  162. procname++;
  163. else
  164. procname = proc_argv[0];
  165. printf("%c %5d %5d %5d %6lu %6lu %4.1f %s ",
  166. procinfo.pr_lwp.pr_sname,
  167. (int)(procinfo.pr_euid),
  168. (int)proc_kvm->p_pidp->pid_id,
  169. (int)proc_kvm->p_ppid,
  170. (unsigned long)(procinfo.pr_size),
  171. (unsigned long)(procinfo.pr_rssize),
  172. ((float)(procinfo.pr_pctcpu) / 0x8000 * 100.0),
  173. procname
  174. );
  175. for(i=0;proc_argv[i];i++) {
  176. printf(" %s", proc_argv[i]);
  177. }
  178. printf("\n");
  179. }