/* * call_ftw_for_dev() uses ftw() to pass pathnames under /dev to gdev() * along with a status buffer. */ static void call_ftw_for_dev(void) { int gdev(); int rcode; ndev = 0; rcode = ftw("/dev", gdev, 17); switch (rcode) { case 0: return; /* successful return, devl populated */ case 1: SYSLOG0(" ftw() encountered problem\n"); break; case -1: SYSLOG1(" ftw() failed, %s\n", strerror(errno)); break; default: SYSLOG1(" ftw() unexpected return, rcode=%d\n", rcode); break; } exit(1); }
void get_ps_data(void) { ps_ldata_t *ps_last = PS_LNULL; ps_ldata_t *ps_head = PS_LNULL; ps_ldata_t *psp; ps_data_t *pstp; static char *usrname; int i = 0; DIR *dirp; struct dirent *dentp; char pname[MAXNAMELEN]; int pdlen; char *gettty(); if (pstable != PS_NULL) { /* Don't run ps unless we need to */ if ((cache_now - ps_cache_time) <= cache_lifetime) return; free(pstable); } pstable_lines = 0; ps_cache_time = cache_now; /* * Determine root path for remote machine. */ if (!readata()) { /* get data from psfile */ call_ftw_for_dev(); wrdata(); } /* * Determine which processes to print info about by searching * the /proc directory and looking at each process. */ if ((dirp = opendir(procdir)) == NULL) { (void) SYSLOG0("Cannot open PROC directory\n"); return; } (void) strcpy(pname, procdir); pdlen = strlen(pname); pname[pdlen++] = '/'; /* for each active process --- */ while (dentp = readdir(dirp)) { int procfd; if (dentp->d_name[0] == '.') /* skip . and .. */ continue; (void) strcpy(pname + pdlen, dentp->d_name); retry: if ((procfd = open(pname, O_RDONLY)) == -1) continue; /* * Get the info structure for the process and close quickly. */ if (ioctl(procfd, PIOCPSINFO, (char *)&info) == -1) { int saverr = errno; (void) close(procfd); if (saverr == EAGAIN) goto retry; if (saverr != ENOENT) (void) SYSLOG2("PIOCPSINFO on %s: %s\n", pname, strerror(saverr)); continue; } (void) close(procfd); if ((psp = (ps_ldata_t *)malloc(sizeof (ps_ldata_t))) == PS_LNULL) break; memset((char *)psp, 0, sizeof (ps_ldata_t)); psp->pdata.uid = info.pr_uid; psp->pdata.pid = info.pr_pid; psp->pdata.ppid = info.pr_ppid; psp->pdata.sz = info.pr_size; if (info.pr_wchan) sprintf(psp->pdata.wchan, "%9x", info.pr_wchan); else strcpy(psp->pdata.wchan, " "); memset(&psp->pdata.stat[0], 0, STAT_SZ+1); if (info.pr_sname) psp->pdata.stat[0] = info.pr_sname; i = 0; strcpy(psp->pdata.tty, (char *)gettty(&i)); psp->pdata.cpu = info.pr_time.tv_sec; strcpy(psp->pdata.cmd, info.pr_fname); if ((usrname = (get_usr_name(psp->pdata.uid))) != NULL) strncpy(psp->pdata.usrname, usrname, USRNM_SZ); else { free(psp); continue; } psp->pdata.usrname[USRNM_SZ] = '\0'; pstable_lines++; if (ps_last == PS_LNULL) ps_head = psp; else ps_last->link = psp; ps_last = psp; } (void) closedir(dirp); if ((pstable = (ps_data_t *)malloc(pstable_lines * sizeof (ps_data_t))) == PS_NULL) { clean_ps(ps_head); return; } for (pstp = pstable, psp = ps_head; psp != PS_LNULL; pstp++, psp = psp->link) { memcpy((char *)pstp, (char *)&(psp->pdata), sizeof (ps_data_t)); } clean_ps(ps_head); qsort(pstable, pstable_lines, sizeof (ps_data_t), (int (*)())pscomp); }
static int ContactGlobal() { int sleepTime; int status; int retries; int ioctlRetries; int realErrno; int success = 0; static int firstContact = 1; /* First time we are trying to reach the global daemon? */ int t; t = time(0); if (migd_Debug > 1) { fprintf(stderr, "ContactGlobal - %s\n", ctime(&t)); } /* * Set a temporary variable to track firstContact, and reset it so * any subsequent calls have the updated value. This avoids the * need to reset it before every return statement. */ if (firstContact) { /* * First time we've been called. Set up seed for random * numbers. */ srandom(getpid()); firstContact = 0; } /* * Clean up any old descriptor. */ if (migdGlobalDesc >= 0) { Fs_EventHandlerDestroy(migdGlobalDesc); (void) close(migdGlobalDesc); } sleepTime = (random() & 07) + 1; for (retries = 1; retries <= MAX_GLOBAL_CONTACTS && !migd_Quit && !success; retries++) { migdGlobalDesc = open(migd_GlobalPdevName, O_RDWR, 0); if (migdGlobalDesc < 0) { if (migd_Debug > 2) { fprintf(stderr, "ContactGlobal - sleeping %d seconds\n", sleepTime); } sleep(sleepTime); sleepTime *= 2; migdGlobalDesc = open(migd_GlobalPdevName, O_RDWR, 0); } if (migdGlobalDesc < 0) { if (migd_Debug > 0) { fprintf(stderr, "ContactGlobal: couldn't open %s: %s\n", migd_GlobalPdevName, strerror(errno)); } /* * If errno is ENOENT, there is not currently a master, anywhere. * (When the master exits it removes the pdev.) EIO * may mean the daemon crashed. EINVAL may mean the daemon's host * crashed. We special case EIO due to a race condition * between recovery and starting daemons. */ if (errno == ENOENT || errno == EIO || errno == EINVAL) { if (retries == MAX_GLOBAL_CONTACTS - 1 && errno != ENOENT) { /* * We're getting desperate here. We can't open * the file, but we should be able to. Remove * the pdev and try one last time to create the * master, since it may be that the host running * the master has crashed and the name server * is continually returning a bad status to us. * We risk clobbering someone else who has successfully * opened the pdev just before us, but there's a small * window of vulnerability and by this time we're sleeping * a long time. */ (void) unlink(migd_GlobalPdevName); } if (!migd_NeverRunGlobal) { if (CreateGlobal() < 0) { return(-1); } } /* * Go to start of for loop, trying to open pdev. */ continue; } else { realErrno = errno; fprintf(stderr, "Migd_Init - Unable to contact master of global pdev: %s\n", strerror(errno)); errno = realErrno; return(-1); } } else { /* * We've successfully opened the pdev. * Try to tell the global master that we're a daemon. It may say * DEV_BUSY, which means that there is already a daemon. In that * case, it tells the other daemon to go away, and we will keep * trying. In some cases we may get an error doing the ioctl, * such as a stale handle, in which case we close the file and * go to the top again. */ for (ioctlRetries = 1; ioctlRetries <= MAX_GLOBAL_CONTACTS; ioctlRetries++) { status = Fs_IOControl(migdGlobalDesc, IOC_MIG_DAEMON, sizeof(Mig_Info), (char *) ¤tInfo, 0, (char *) NULL); if (status == DEV_BUSY) { if (migd_Debug > 0) { fprintf(stderr, "ContactGlobal - ioctl returned busy.\n"); } sleepTime = ((random() & 07) + 1) * ioctlRetries; if (migd_Debug > 2) { fprintf(stderr, "ContactGlobal - sleeping %d seconds\n", sleepTime); } sleep(sleepTime); } else { /* * An error we can't deal with, or SUCCESS. */ break; } } if (status != SUCCESS) { SYSLOG1(LOG_ERR, "ContactGlobal: warning: error during ioctl to global master: %s\n", Stat_GetMsg(status)); errno = Compat_MapCode(status); close(migdGlobalDesc); } else { /* * We did it! Break out of the inner for loop, and the * success flag will break us out of the outer loop. */ success = 1; break; } } } if (!success) { realErrno = errno; SYSLOG0(LOG_ERR, "unable to contact master; giving up.\n"); errno = realErrno; return(-1); } #ifdef FAST_SELECT Fs_EventHandlerCreate(migdGlobalDesc, FS_READ|FS_EXCEPTION, HandleException, (ClientData) NULL); #endif /* FAST_SELECT */ if (migd_Debug > 1) { fprintf(stderr, "ContactGlobal - completed successfully\n"); } return (0); }