burdick@hpindda.HP.COM (Matt Burdick) (12/02/89)
I would like to ftp a new copy of the Andrew source from emsworth.andrew.cmu.edu, but keep getting a 'permission denied' message. Here are some of the messages when I take a look at the directory: ftp> dir 200 PORT command successful. 150 Opening data connection for /bin/ls (15.255.208.3,11945) (0 bytes). [Can't determine primary cell, using workstation cell] [Can't determine workstation cell, using 'andrew.cmu.edu'] Total: 66 kbytes -rwx 1 80 0 185 Oct 18 13:13 AndrewSetup -rw- 1 469 0 665 Nov 22 15:56 README -r-- 1 38 0 55702 Nov 22 17:04 andrew.README l 1 469 0 16 Nov 27 21:55 andrew.tar.Z -> sub/andrew.tar.Z d 2 1342 0 2048 Sep 20 17:10 bin d 2 38 0 2048 Nov 28 13:18 bugs d 2 1342 0 2048 Nov 15 08:56 patches d 2 1342 0 2048 Oct 23 09:07 util alpha-patches: Permission denied sub: Permission denied andrew: Permission denied 226 Transfer complete. 755 bytes received in 1.11 seconds (0.66 Kbytes/sec) Could someone fix the permissions on these? Also, here is a new version of the atk/console/stats/hp300/getstats.c file. I am including the entire thing, since I changed quite a lot: #---------------------------------- cut here ---------------------------------- # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by Matt Burdick <burdick@hpindlw> on Fri Dec 1 16:20:17 1989 # # This archive contains: # getstats.c # # Error checking via wc(1) will be performed. # Error checking via sum(1) will be performed. LANG=""; export LANG PATH=/bin:/usr/bin:$PATH; export PATH if sum -r </dev/null >/dev/null 2>&1 then sumopt='-r' else sumopt='' fi echo x - getstats.c cat >getstats.c <<'@EOF' /* ********************************************************************** *\ * Copyright IBM Corporation 1988,1989 - All Rights Reserved * * For full copyright information see:'andrew/config/COPYRITE' * \* ********************************************************************** */ /* $Header: /afs/.andrew.cmu.edu/itc/src/andrew/atk/console/stats/hp300/RCS/getstats.c,v 1.4 89/10/18 12:26:09 cfe Exp $ */ /* $Source: /afs/.andrew.cmu.edu/itc/src/andrew/atk/console/stats/hp300/RCS/getstats.c,v $ */ #ifndef lint static char *getstats_c_id = "$Header: /afs/.andrew.cmu.edu/itc/src/andrew/atk/console/stats/hp300/RCS/getstats.c,v 1.4 89/10/18 12:26:09 cfe Exp $"; #endif /* lint */ /* ********************************************************************** * This code is designed to read what might be priveledged (setuid) * information regarding both Disk Statistics (% full) and a host of * stats from /dev/kmem (including but not limited to, CPU, I/O, and VM) * * When retriving the data - this program will print out to stdout * a string in the form of either "%d:%d\n" or "%d:%d:%s\n" * The latter case is for passing the name of where a disk is mounted * back to the parent program. * * The parent program (Console, or any other program which wishes to get * at this information) is responsible for setting up a pipe, binding the * child's (this program) stdout to one end of a pipe, and parsing the * strings which are passed back. * * The basic string format is an ID (int), a colon, a value (int), and * optionally another colon followed by a string. The ID is coded from * the included file "getstats.h" - ID values 50 and over represent * ERRORS as documented in the above mentioned inclued file. When an * ERROR or the optional string is passed, the value (second parameter) * can be safely ignored, and is usually set to 0. * * The arguments to be passed to this program are the effective UID from * the parent program, a polling frequency (# of seconds) for checking * /dev/kmem (usually between 1 and 5, must be > 0), and a polling * frequency for checking how full the local disks are (generally higher * than the value for /dev/kmem, but could vary greatly). Thus the call * is: * * execvp("getstats", argv) * * with argv as: * * argv[0]="getstats"; * argv[1]=~ ("%d", UID); * argv[2]=~ ("%d", kmempollfrequency); * argv[3]=~ ("%d", diskpollfrequency); * argv[4]=NULL; * ********************************************************************** */ #include <sitevars.h> #include <system.h> #include <stdio.h> #include <sys/param.h> #include <sys/dir.h> #include <sys/signal.h> #include <sys/user.h> #include <sys/proc.h> #include <sys/vm.h> #include <sys/dk.h> #include <sys/map.h> #include <sys/buf.h> #include <netinet/in.h> #include <errno.h> #include <sys/stat.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/if_ether.h> #include <checklist.h> #include <mntent.h> #include <sys/vfs.h> #include <sys/fs.h> #undef MAXUPRC long maxuprc = 0; /* we have to nlist in HP-UX */ #define VMMON_DODECL #include <getstats.h> extern struct nlist RawStatistics[]; char root[32]; int TotalTime; int deficit; int MemoryFile /* file descriptor for unix memory */ ; int nproc; off_t procp; struct proc proc[8];/* 8 = a few, for fewer syscalls */ struct proc *mproc; extern char *malloc(); struct{ long time[CPUSTATES]; long xfer[DK_NDRIVE]; struct vmmeter Rate; struct vmtotal Total; long dk_xfer[DK_NDRIVE]; }s, s1; union { struct fs iu_fs; char dummy[SBSIZE]; } sb; #define sendval(text) {printf text ;fflush(stdout);} GetGVMStats(UsersID) int UsersID; { register int i; long t; struct mapent *sp; int myval = 0; lseek(MemoryFile,(long) RawStatistics[X_CPTIME].n_value, 0); read(MemoryFile, s.time, sizeof(s.time)); lseek(MemoryFile,(long) RawStatistics[X_DKXFER].n_value, 0); read(MemoryFile, s.dk_xfer, sizeof(s.dk_xfer)); lseek(MemoryFile,(long) RawStatistics[X_RATE].n_value, 0); read(MemoryFile, &s.Rate, sizeof(s.Rate)); lseek(MemoryFile,(long) RawStatistics[X_TOTAL].n_value, 0); read(MemoryFile, &s.Total, sizeof(s.Total)); lseek(MemoryFile,(long) RawStatistics[X_DEFICIT].n_value, 0); read(MemoryFile, &deficit, sizeof(deficit)); for (i = 0; i < CPUSTATES; i++) { t = s.time[i]; s.time[i] -= s1.time[i]; s1.time[i] = t; } s.time[1] += s.time[0]; TotalTime = 0; for (i = 1; i < CPUSTATES; i++) TotalTime += s.time[i]; if (TotalTime == 0) TotalTime = 1; sendval(("%d:%d\n", LOADCPU, (s.time[1] + s.time[2]) * 100 / TotalTime)); for (i = 1; i < DK_NDRIVE - 1; i++) s.dk_xfer[0] += s.dk_xfer[i]; if (s1.dk_xfer[0] == 0){ s1.dk_xfer[0] = s.dk_xfer[0]; } myval = s.dk_xfer[0] - s1.dk_xfer[0]; if (myval > 100) myval = 100; sendval(("%d:%d\n", LOADIO, myval)); s1.dk_xfer[0] = s.dk_xfer[0]; sendval(("%d:%d\n", LOADUSER, s.time[1] * 100 / TotalTime)); sendval(("%d:%d\n", LOADSYS, s.time[2] * 100 / TotalTime)); sendval(("%d:%d\n", LOADIDLE, s.time[3] * 100 / TotalTime)); sendval(("%d:%d\n", VM, (int)((double)s.Total.t_avm/(double)s.Total.t_vm * 100))); sendval(("%d:%d\n", PAGEIN, s.Rate.v_pgpgin / 2)); sendval(("%d:%d\n", PAGEOUT, s.Rate.v_pgpgout / 2)); sendval(("%d:%d\n", PAGEREPLACABLE, s.Rate.v_scan)); sendval(("%d:%d\n", PAGEDEFICIT, deficit)); sendval(("%d:%d\n", MEMACTIVE, s.Total.t_avm / 2)); sendval(("%d:%d\n", MEMFREE, s.Total.t_free / 2)); sendval(("%d:%d\n", QUEUERUN, s.Total.t_rq)); sendval(("%d:%d\n", QUEUEBLOCK, s.Total.t_dw + s.Total.t_pw)); sendval(("%d:%d\n", QUEUEMEM, s.Total.t_sw)); sendval(("%d:%d\n", INTSIO, s.Rate.v_intr)); sendval(("%d:%d\n", INTSSYS, s.Rate.v_syscall)); sendval(("%d:%d\n", INTSSWAP, s.Rate.v_swtch)); if (1) {/* DoPROCESSES */ int i, j, userprocesses, totalprocesses, otherprocs; off_t tmpprocp; userprocesses = 0; totalprocesses = 1; otherprocs = 0; tmpprocp = procp; for (i = 0; i < nproc; i += 8) { lseek(MemoryFile, (long) tmpprocp, 0); j = nproc - i; if (j > 8) j = 8; j *= sizeof(struct proc); if (read(MemoryFile, (char *) proc, j) != j) { sendval(("%d:%d\n", GVM_ERR_1, 0)); exit(-1); } tmpprocp += j; for (j = j / sizeof(struct proc) - 1; j >= 0; j--) { mproc = &proc[j]; if (mproc->p_pid != 0) { totalprocesses++; if (UsersID == mproc->p_uid) { userprocesses ++; } else if (mproc->p_uid) { otherprocs++; } } } } sendval(("%d:%d\n", PROCSUSER, maxuprc ? (userprocesses * 100) / maxuprc : -1)); sendval(("%d:%d\n", PROCSTOTAL, nproc ? totalprocesses * 100 / nproc : -1)); sendval(("%d:%d\n", PROCSOTHER, otherprocs)); } } InitGVMStats() { time_t bootime; int code = 0; /* set up Unix interface: scan name list for current system addresses and then open a file which is the memory image of the system. */ code = nlist(_SITE_VMUNIX, RawStatistics); if (code == -1){ sendval(("%d:%d\n", GVM_ERR_2, 0)); exit(-1); } else{ if (RawStatistics[0].n_type == 0){ sendval(("%d:%d\n", GVM_ERR_3, 0)); exit(-1); } } MemoryFile = open(_SITE_DEV_KMEM, 0); if (MemoryFile < 0){ sendval(("%d:%d\n", GVM_ERR_4, 0)); exit(-1); } lseek(MemoryFile,(long) RawStatistics[X_BOOTIME].n_value, 0); read(MemoryFile, &bootime, sizeof(bootime)); lseek(MemoryFile, (long) RawStatistics[X_PROC].n_value, 0); read(MemoryFile,(char *) &procp, sizeof(procp)); lseek(MemoryFile, (long) RawStatistics[X_NPROC].n_value, 0); read(MemoryFile,(char *) &nproc, sizeof(nproc)); #ifndef MAXUPRC lseek(MemoryFile, (long) RawStatistics[X_MAXUPRC].n_value, 0); read(MemoryFile,(char *) &maxuprc, sizeof(maxuprc)); #endif /* MAXUPRC */ } /* the DeviceTable keeps a list of all the devices (and their mounted directory file name) that we should watch */ extern int getmnt(); GetDiskStats(Init) int Init; { int i = 0; struct stat statb; char tmpname[1024]; register FILE *mtabp; register struct mntent *mnt; sync(); if ((mtabp = setmntent(MNT_MNTTAB, "r")) == NULL) { sendval(("%d:%d\n", DISK_ERR_1, 0)); exit(1); } i = DISK1 - 1; /* figuratively 0 */ while ((mnt = getmntent(mtabp)) != NULL) { i++; if (strcmp(mnt->mnt_type, MNTTYPE_IGNORE) == 0 || strcmp(mnt->mnt_type, MNTTYPE_SWAP) == 0) continue; if (strcmp(mnt->mnt_type, MNTTYPE_HFS) == 0 && (stat(mnt->mnt_fsname, &statb) >= 0) && (((statb.st_mode & S_IFMT) == S_IFBLK) || ((statb.st_mode & S_IFMT) == S_IFCHR))) { (void) strcpy(tmpname, mnt->mnt_fsname); dfree1(i, tmpname, 0, Init); } else { dfree2(i, mnt->mnt_dir, mnt, Init); } } (void) endmntent(mtabp); } int bread(fi, bno, buf, cnt) int fi; daddr_t bno; char *buf; int cnt; { extern int errno; (void) lseek(fi, (long)(bno * DEV_BSIZE), 0); if (read(fi, buf, (unsigned) cnt) < 0) { /* probably a dismounted disk if errno == EIO */ if (errno != EIO) { sendval(("%d:%d\n", DISK_ERR_5, 0)); } return (0); } return (1); } /* * Given a name like /dev/rrp0h, returns the mounted path, like /usr. */ char *mpath(file) char *file; { FILE *mntp; register struct mntent *mnt; if ((mntp = setmntent(MNT_MNTTAB, "r")) == 0) { sendval(("%d:%d\n", DISK_ERR_1, 0)); exit(1); } while ((mnt = getmntent(mntp)) != 0) { if (strcmp(file, mnt->mnt_fsname) == 0) { (void) endmntent(mntp); return (mnt->mnt_dir); } } (void) endmntent(mntp); return ""; } int round(num) double num; { int inum = (int) num; return(((num - inum) >= 0.5) ? (inum + 1) : inum); } dfree1(id, file, infsent, Init) int id; char *file; int infsent; int Init; { long totalblks, availblks, free, used; int fi; struct stat stbuf; struct checklist *fsp; if (stat(file, &stbuf) == 0 && (stbuf.st_mode&S_IFMT) != S_IFCHR && (stbuf.st_mode&S_IFMT) != S_IFBLK) { if (infsent) { sendval(("%d:%d\n", DISK_ERR_3, 0)); return; } setfsent(); while (fsp = getfsent()) { struct stat stb; if (stat(fsp->fs_spec, &stb) == 0 && stb.st_rdev == stbuf.st_dev) { file = fsp->fs_spec; endfsent(); goto found; } } endfsent(); sendval(("%d:%d\n", DISK_ERR_4, 0)); return; } found: fi = open(file, 0); if (fi < 0){ return; } if (bread(fi, SBLOCK, (char *)&sb.iu_fs, SBSIZE) == 0) { (void) close(fi); return; } totalblks = sb.iu_fs.fs_dsize; free = sb.iu_fs.fs_cstotal.cs_nbfree * sb.iu_fs.fs_frag + sb.iu_fs.fs_cstotal.cs_nffree; used = totalblks - free; availblks = totalblks * (100 - sb.iu_fs.fs_minfree) / 100; if(Init){ sendval(("%d:%d:%s\n", id, 0, mpath(file))); } else{ sendval(("%d:%d\n", id, availblks == 0 ? 0 : round((double) used / (double) availblks * 100.0))); } (void) close(fi); } dfree2(id, file, mnt, Init) int id; char *file; struct mntent *mnt; int Init; { struct statfs fs; long totalblks, avail, free, used, reserved; if (statfs(file, &fs) < 0) { return; } totalblks = fs.f_blocks; free = fs.f_bfree; used = totalblks - free; avail = fs.f_bavail; reserved = free - avail; if (avail < 0) avail = 0; totalblks -= reserved; if(Init){ sendval(("%d:%d:%s\n",id, 0, mnt->mnt_dir)); } else{ sendval(("%d:%d\n", id, round((double) used / (double) totalblks * 100.0))); } } @EOF set `sum $sumopt <getstats.c`; if test $1 -ne 17015 then echo ERROR: getstats.c checksum is $1 should be 17015 fi set `wc -lwc <getstats.c` if test $1$2$3 != 434145011654 then echo ERROR: wc results of getstats.c are $* should be 434 1450 11654 fi chmod 644 getstats.c exit 0
mss+@ANDREW.CMU.EDU (Mark Sherman) (12/03/89)
The previous materials on emsworth.andrew.cmu.edu were for beta testing (as advertised). The beta test period is over, since the release had to go to MIT at Thanksgiving in order to go on the X.V11R4 tape (as per MIT's announced schedule). Our "lastest" sources would be the result of "patch 8" which we never explicitly cr eated or distributed. These sources went to MIT. We then sent people to Cambridge to do last minute testing against the actual R4 servers (nearly all beta testing was against R3 servers). These people have been making various tweaks and fixes so that the release on the tape should build and work easily. But, the consequences of this procedure include that we do not have a real copy of the released code, since by definition it is still in Cambridge. Therefore, we have tried to limit access to our (now outdated) beta sources; they will be replaced with the released sources when we get them back and integrate the changes into our mainstream source control system. And as promised, we will let people know when everything is ready and when they can come and get it. -Mark (By the way, we are starting to put together the final hard copy documentation and lay in a supply of Borenstein's book on Andrew development. It would help us if we knew how much interest there was in these materials -- a note to me, mss@andrew.cmu.edu, would be fine; don't bother the entire group.)