/* $Id: machine.c,v 1.6 2008/09/16 22:56:44 ksb Exp $ * find the parts of a process we need on Linux, a bit specail case. (ksb) */ #include #include #include #include #include #include #include #include #include #include #include #include "machine.h" extern char *progname; #if USE_KVM_FROM_PROC static kvm_t XM_kvm; /* error interface (ksb) */ char * kvm_geterr(kvm_t *pkvm) { return "LINUX: not implemented"; } /* fake this enough to compile, no more (ksb) */ kvm_t * kvm_openfiles(const char *pcExec, const char *pcCore, const char *pcSwap, int iFlags, char *pcError) { XM_kvm.pKImem = (struct kinfo_proc *)0; return & XM_kvm; } static char acProc[] = "/proc"; /* return enough information to fake ptree (ksb) */ struct kinfo_proc * kvm_getprocs(kvm_t *pkvm, int iFlag, int Junk, int *piEntries) { register DIR *pDI; register struct dirent *pDE; register struct kinfo_proc *pKIRet; register int iAllow; register int fd; auto struct stat stCount; auto char acDir[MAXPATHLEN+4]; auto char acBuffer[4096]; *piEntries = 0; if (-1 == stat(acProc, & stCount) || !S_ISDIR(stCount.st_mode) || (DIR *)0 == (pDI = opendir(acProc)) || stCount.st_nlink < 3) { errno = ENOENT; return (struct kinfo_proc *)0; } /* might grow a little as we read them */ iAllow = (stCount.st_nlink|7)+9; if ((struct kinfo_proc *)0 == (pKIRet = (struct kinfo_proc *)calloc(iAllow, sizeof(struct kinfo_proc)))) { errno = ENOMEM; return (struct kinfo_proc *)0; } XM_kvm.pKImem = pKIRet; while ((struct dirent *)0 != (pDE = readdir(pDI))) { register char *pc; register struct kinfo_proc *pKI; register int iCc; for (pc = pDE->d_name; isdigit(*pc); ++pc) { /* nada */ } if ('\000' != *pc) continue; snprintf(acDir, sizeof(acDir), "%s/%s/stat", acProc, pDE->d_name); if (-1 == (fd = open(acDir, O_RDONLY, 0))) continue; if (-1 == fstat(fd, & stCount)) { close(fd); continue; } iCc = read(fd, acBuffer, sizeof(acBuffer)); close(fd); if (iCc == sizeof(acBuffer)) --iCc; acBuffer[iCc] = '\000'; if ((char *)0 == (pc = strchr(acBuffer, ' '))) { continue; } ++pc; if (0 == iAllow--) { fprintf(stderr, "%s: process table grew too fast\n", progname); break; } pKI = & pKIRet[(*piEntries)++]; pKI->xm_pid = atoi(pDE->d_name); pKI->xm_ruid = stCount.st_uid; pKI->xm_rgid = stCount.st_gid; ++pc; /* skip '(' */ for (iCc = 0; ')' != *pc && iCc < sizeof(pKI->xm_comm)-1; ++pc, ++iCc) { pKI->xm_comm[iCc] = *pc; } pKI->xm_comm[iCc] = '\000'; do { ++pc; } while (!isspace(*pc)); ++pc; while (!isspace(*pc++)) { /* nada */ } pKI->xm_ppid = atoi(pc); } closedir(pDI); return pKIRet; } /* copy in args, not implmented yet (ksb) */ char ** kvm_getargv(kvm_t *pkvm, struct kinfo_proc *pKI, int iLen) { register int fdCmd; register char *pcMem, **ppcArgv; auto char acFile[MAXPATHLEN+2]; snprintf(acFile, sizeof(acFile), "%s/%d/cmdline", acProc, pKI->PTREE_FIND_PID); if (iLen < 2) { iLen = 2; } if ((char **)0 == (ppcArgv = calloc(iLen, sizeof(char *)))) return (char **)0; if (-1 == (fdCmd = open(acFile, O_RDONLY, 0))) { return (char **)0; } ppcArgv[0] = calloc(XM_2BIG+1, sizeof(char)); ppcArgv[1] = (char *)0; ppcArgv[0][0] = '\000'; read(fdCmd, ppcArgv[0], XM_2BIG); close(fdCmd); return ppcArgv; } /* free, close, unload, cleanup (ksb) */ int kvm_close(kvm_t *pkvm) { if ((struct kinfo_proc *)0 != pkvm->pKImem) { free((void *)pkvm->pKImem); pkvm->pKImem = (struct kinfo_proc *)0; } /* we do not allocate this, it is static in this instance */ return 0; } #else #if USE_KVM_FROM_PSINFO /* AIX or IBMR2 for example */ #include static kvm_t XM_kvm; /* error interface (ksb) */ char * kvm_geterr(kvm_t *pkvm) { return "AIX: not implemented"; } /* fake this enough to compile, no more (ksb) */ kvm_t * kvm_openfiles(const char *pcExec, const char *pcCore, const char *pcSwap, int iFlags, char *pcError) { XM_kvm.pKImem = (struct kinfo_proc *)0; return & XM_kvm; } static char acProc[] = "/proc"; /* return enough information to fake ptree (ksb) */ struct kinfo_proc * kvm_getprocs(kvm_t *pkvm, int iFlag, int Junk, int *piEntries) { register DIR *pDI; register struct dirent *pDE; register struct kinfo_proc *pKIRet; register int iAllow; register int fd; auto struct stat stCount; auto char acDir[MAXPATHLEN+4]; auto struct psinfo PSI; *piEntries = 0; if (-1 == stat(acProc, & stCount) || !S_ISDIR(stCount.st_mode) || (DIR *)0 == (pDI = opendir(acProc))) { errno = ENOENT; return (struct kinfo_proc *)0; } /* might grow a little as we read them, on AIX the number of link * to /proc is not set to anything sane (like the number of processes). */ iAllow = stCount.st_nlink; while ((struct dirent *)0 != (pDE = readdir(pDI))) { ++iAllow; } iAllow |= 7; iAllow += 9+64; rewinddir(pDI); if ((struct kinfo_proc *)0 == (pKIRet = (struct kinfo_proc *)calloc(iAllow, sizeof(struct kinfo_proc)))) { errno = ENOMEM; return (struct kinfo_proc *)0; } XM_kvm.pKImem = pKIRet; while ((struct dirent *)0 != (pDE = readdir(pDI))) { register char *pc; register struct kinfo_proc *pKI; register int iCc; for (pc = pDE->d_name; isdigit(*pc); ++pc) { /* nada */ } if ('\000' != *pc) continue; snprintf(acDir, sizeof(acDir), "%s/%s/psinfo", acProc, pDE->d_name); if (-1 == (fd = open(acDir, O_RDONLY, 0))) continue; if (-1 == fstat(fd, & stCount)) { close(fd); continue; } iCc = read(fd, & PSI, sizeof(PSI)); close(fd); if (iCc != sizeof(PSI)) continue; if (0 == iAllow--) { fprintf(stderr, "%s: process table grew too fast\n", progname); break; } pKI = & pKIRet[(*piEntries)++]; pKI->xm_pid = (pid_t)PSI.pr_pid; pKI->xm_ruid = (uid_t)PSI.pr_uid; pKI->xm_rgid = (uid_t)PSI.pr_gid; pKI->xm_ppid = (pid_t)PSI.pr_ppid; strncpy(pKI->xm_comm, PSI.pr_fname, sizeof(pKI->xm_comm)); if ('\000' == PSI.pr_psargs[0]) { continue; } strncat(pKI->xm_comm, " ", sizeof(pKI->xm_comm)); strncat(pKI->xm_comm, PSI.pr_psargs, sizeof(pKI->xm_comm)); } closedir(pDI); return pKIRet; } /* copy in args, implmented prototype (ksb) */ char ** kvm_getargv(kvm_t *pkvm, struct kinfo_proc *pKI, int iLen) { register int fdCmd; register char *pcMem, **ppcArgv; auto struct psinfo PSI; auto char acFile[MAXPATHLEN+2]; snprintf(acFile, sizeof(acFile), "%s/%d/prinfo", acProc, pKI->PTREE_FIND_PID); if (iLen < 2) { iLen = 2; } if ((char **)0 == (ppcArgv = calloc(iLen, sizeof(char *)))) return (char **)0; if (-1 == (fdCmd = open(acFile, O_RDONLY, 0))) { return (char **)0; } ppcArgv[0] = calloc(sizeof(PSI.pr_psargs), sizeof(char)); ppcArgv[1] = (char *)0; ppcArgv[0][0] = '\000'; if (sizeof(PSI) != read(fdCmd, & PSI, sizeof(PSI))) { close(fdCmd); return ppcArgv; } strncpy(ppcArgv[0], PSI.pr_psargs, sizeof(PSI.pr_psargs)); close(fdCmd); return ppcArgv; } /* free, close, unload, cleanup (ksb) */ int kvm_close(kvm_t *pkvm) { if ((struct kinfo_proc *)0 != pkvm->pKImem) { free((void *)pkvm->pKImem); pkvm->pKImem = (struct kinfo_proc *)0; } /* we do not allocate this, it is static in this instance */ return 0; } #else #if USE_KVM_FROM_PSTAT_GETPROC #include /* HPUX11 for example */ static kvm_t XM_kvm; /* error interface (ksb) */ char * kvm_geterr(kvm_t *pkvm) { return "HPUX: not fully implemented"; } /* no files to open for this interface (ksb) */ kvm_t * kvm_openfiles(const char *pcExec, const char *pcCore, const char *pcSwap, int iFlags, char *pcError) { XM_kvm.pKImem = (struct kinfo_proc *)0; return & XM_kvm; } #define BURST ((size_t)128) #define START (BURST*16) /* Return enough information to fake ptree (ksb) */ struct kinfo_proc * kvm_getprocs(kvm_t *pkvm, int iFlag, int Junk, int *piEntries) { register struct kinfo_proc *pKIRet; register int iEnts, iMax; register int i, iCount, iCur; auto struct pst_status pst[BURST]; iMax = START; pKIRet = (struct kinfo_proc *)calloc(iMax, sizeof(struct kinfo_proc)); if ((struct kinfo_proc *)0 == pKIRet) { return pKIRet; } iEnts = 0; iCur = 0; while (0 < (iCount = pstat_getproc(pst, sizeof(pst[0]), BURST, iCur))) { if (iCount + iEnts >= iMax) { iMax += BURST*2; pKIRet = realloc((void *)pKIRet, sizeof(struct kinfo_proc)*iMax); if ((struct kinfo_proc *)0 == pKIRet) return pKIRet; } for (i = 0; i < iCount; ++i) { pKIRet[iEnts].xm_ppid = pst[i].pst_ppid; pKIRet[iEnts].xm_pid = pst[i].pst_pid; pKIRet[iEnts].xm_ruid = pst[i].pst_uid; pKIRet[iEnts].xm_rgid = pst[i].pst_gid; strncpy(pKIRet[iEnts].xm_comm, pst[i].pst_ucomm, sizeof(pKIRet[0].xm_comm)); ++iEnts; } iCur = pst[iCount-1].pst_idx + 1; } if (iCount == -1) { fprintf(stderr, "%s: pstat_getproc: %s\n", progname, strerror(errno)); } *piEntries = iEnts; return pKIRet; } #undef BURST /* copy in args, not implmented yet (ksb) */ char ** kvm_getargv(kvm_t *pkvm, struct kinfo_proc *pKI, int iLen) { register char **ppcArgv; if ((char **)0 == (ppcArgv = calloc(iLen, sizeof(char *)))) return (char **)0; ppcArgv[0] = pKI->xm_comm; ppcArgv[1] = (char *)0; (void)pstat_getcommandline(pKI->xm_comm, (size_t)sizeof(pKI->xm_comm), (size_t)1, pKI->xm_pid); return ppcArgv; } /* free, close, unload, cleanup (ksb) */ int kvm_close(kvm_t *pkvm) { if ((struct kinfo_proc *)0 != pkvm->pKImem) { free((void *)pkvm->pKImem); pkvm->pKImem = (struct kinfo_proc *)0; } /* we do not allocate this, it is static in this instance */ return 0; } #endif /* HPUX */ #endif /* AIX */ #endif /* LINUX */