4
0

pst3.c 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  1. /* pst3.c
  2. *
  3. * Third version to get process arg info; this time by using
  4. * a combination of reading the /proc/<pid>/psinfo structures
  5. * and reading the complete arg vector from kernel memory structures.
  6. *
  7. * Developed and tested under Solaris 5.8 (both 32 and 64 bit modes).
  8. *
  9. * NOTE: This program must be setuid-root (or run by root) to work!
  10. *
  11. * Written: 2005-04-28 R.W.Ingraham
  12. */
  13. #define _KMEMUSER 1
  14. #include <kvm.h>
  15. #include <sys/param.h>
  16. #include <sys/user.h>
  17. #include <sys/time.h>
  18. #include <sys/proc.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <unistd.h>
  24. #include <string.h>
  25. #include <procfs.h>
  26. #include <fcntl.h>
  27. #include <dirent.h>
  28. #include <errno.h>
  29. /*
  30. * Constants
  31. */
  32. #define PROC_DIR "/proc"
  33. #define MAX_PATH 1024
  34. /*
  35. * Structures
  36. */
  37. /*
  38. * Globals
  39. */
  40. static char * szProg;
  41. static kvm_t * kd;
  42. static struct proc * pProc;
  43. static struct user * pUser;
  44. static char ** myArgv;
  45. /*
  46. * Prototypes
  47. */
  48. static int HandleFile (struct dirent *pDent);
  49. static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo);
  50. static int GetArgVectors (pid_t pid);
  51. static void ShowArgVectors (void);
  52. static void ReleaseArgVectors();
  53. /*----------------------------------------------------------------------------*/
  54. int main (int argc, char **argv)
  55. {
  56. DIR *pDir;
  57. struct dirent *pDent;
  58. int retcode = 0;
  59. /* Set our program name global */
  60. if ((szProg = strrchr(argv[0], '/')) != NULL)
  61. szProg++;
  62. else
  63. szProg = argv[0];
  64. /* Make sure that our euid is root */
  65. if (geteuid() != 0)
  66. {
  67. fprintf(stderr, "%s: This program can only be run by the root user!\n", szProg);
  68. exit(1);
  69. }
  70. /* Get a handle to the running kernel image */
  71. if ((kd = kvm_open(NULL, NULL, NULL, O_RDONLY, argv[0])) == NULL)
  72. {
  73. fprintf(stderr, "%s: Failed to open kernel memory: %s\n", szProg, strerror(errno));
  74. exit(2);
  75. }
  76. /* Open the /proc directory */
  77. if ((pDir = opendir(PROC_DIR)) != NULL)
  78. {
  79. /* Display column headings */
  80. printf("S UID PPID VSZ RSS %%CPU COMMAND ARGS\n");
  81. /* Zip through all of the process entries */
  82. while ((pDent = readdir(pDir)) != NULL)
  83. {
  84. /* Handle each pid sub-directory */
  85. HandleFile(pDent);
  86. }
  87. /* Close the directory */
  88. closedir(pDir);
  89. }
  90. else /* ERROR: Failure to open PROC_DIR */
  91. {
  92. fprintf(stderr, "%s: Failed to open \"%s\": %s\n", szProg, PROC_DIR, strerror(errno));
  93. retcode = 3;
  94. }
  95. /* Close the handle to the running kernel image */
  96. kvm_close(kd);
  97. return retcode;
  98. }
  99. /*----------------------------------------------------------------------------*/
  100. static int HandleFile (struct dirent *pDent)
  101. {
  102. char szPath[MAX_PATH];
  103. psinfo_t sPsInfo;
  104. int fd, len;
  105. int rc = 0;
  106. /* Skip files beginning with a "." */
  107. if (pDent->d_name[0] == '.')
  108. return 0;
  109. /* Cosntruct the path to the psinfo file */
  110. len = sprintf(szPath, "%s/%s/psinfo", PROC_DIR, pDent->d_name);
  111. /* Open the psinfo file for this pid and print out its arg vectors */
  112. if ((fd = open(szPath, O_RDONLY)) >= 0)
  113. {
  114. /* Read the psinfo struct */
  115. if ((len = read(fd, &sPsInfo, sizeof(sPsInfo))) != sizeof(sPsInfo))
  116. {
  117. rc = errno;
  118. fprintf(stderr, "%s: Read error of psinfo structure (%d)\n", szPath, len);
  119. return rc;
  120. }
  121. /* Close the psinfo file */
  122. close(fd);
  123. /* Pass psinfo struct to reporting function */
  124. HandlePsInfo(szPath, &sPsInfo);
  125. }
  126. else if (errno != ENOENT)
  127. {
  128. rc = errno;
  129. fprintf(stderr, "%s: %s\n", szPath, strerror(errno));
  130. }
  131. return 0;
  132. }
  133. /*----------------------------------------------------------------------------*/
  134. static int HandlePsInfo (char *szPath, psinfo_t *pPsInfo)
  135. {
  136. int retcode;
  137. char *thisProg;
  138. /* Make sure that the process is still there */
  139. if ((retcode = GetArgVectors(pPsInfo->pr_pid)) == 0)
  140. {
  141. /* We use the program name from the kvm argv[0] instead
  142. * of pr_fname from the psinfo struct because pr_fname
  143. * may be truncated.
  144. *
  145. * Also, strip-off leading path information.
  146. */
  147. if ((thisProg = strrchr(myArgv[0], '/')) != NULL)
  148. thisProg++;
  149. else
  150. thisProg = myArgv[0];
  151. /* Display the ps columns (except for argv) */
  152. printf("%c %5d %5d %6lu %6lu %4.1f %s ",
  153. pPsInfo->pr_lwp.pr_sname,
  154. (int)(pPsInfo->pr_euid),
  155. (int)(pPsInfo->pr_ppid),
  156. (unsigned long)(pPsInfo->pr_size),
  157. (unsigned long)(pPsInfo->pr_rssize),
  158. ((float)(pPsInfo->pr_pctcpu) / 0x8000 * 100.0),
  159. thisProg);
  160. /* Display the arg vectors associated with this pid */
  161. ShowArgVectors();
  162. /* Release the arg vector buffer memory */
  163. ReleaseArgVectors();
  164. }
  165. return retcode;
  166. }
  167. /*----------------------------------------------------------------------------*/
  168. static int GetArgVectors (pid_t pid)
  169. {
  170. int retcode = 1;
  171. /* Get the proc structure for the specified PID */
  172. if ((pProc = kvm_getproc(kd, pid)) != NULL)
  173. {
  174. /* Save a copy of the process' u-area */
  175. if ((pUser = kvm_getu(kd, pProc)) != NULL)
  176. {
  177. /* Reconstruct the process' argv vector array */
  178. if (kvm_getcmd(kd, pProc, pUser, &myArgv, NULL) == 0)
  179. {
  180. retcode = 0;
  181. }
  182. }
  183. }
  184. return retcode;
  185. }
  186. /*----------------------------------------------------------------------------*/
  187. static void ShowArgVectors (void)
  188. {
  189. int i;
  190. for (i=0; myArgv[i]; i++)
  191. {
  192. printf(" %s", myArgv[i]);
  193. }
  194. printf("\n");
  195. }
  196. /*----------------------------------------------------------------------------*/
  197. static void ReleaseArgVectors()
  198. {
  199. /* NOOP */
  200. }
  201. /*----------------------------------------------------------------------------*/