leres@ucbarpa.Berkeley.EDU (Craig Leres) (07/26/87)
Here's my Eunice emulation of /usr/ucb/finger for VAX/VMS. More information can be found in README. When unpacking, don't forget to make the sharchive a vms text file before trying to execute it as a shell script. Craig ------ #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # Makefile # README # ddbdef.i # dsc.h # finger.c # getidle.c # item_list_3.h # rmtinfo.c # syssym.awk # ucbdef.i # vms # vmsperror.c # This archive created: Tue Jul 21 19:24:05 1987 export PATH; PATH=/bin:$PATH echo shar: extracting "'Makefile'" '(2949 characters)' if test -f 'Makefile' then echo shar: will not over-write existing file "'Makefile'" else sed 's/^X//' << \SHAR_EOF > 'Makefile' X# Eunice finger makefile X XCFLAGS= -O XSRCS= finger.c getidle.c rmtinfo.c vmsperror.c XOBJS= finger.o getidle.o rmtinfo.o vmsperror.o syssym.o X X# Ignore vms_struct exit status, it's random. XVMSSTRUCT= -/etc/vms/vms_struct X X# Map can be in different places if running a cluster. X#SYSMAP= /sys/sysexe/sys.map XSYSMAP= /sys/syscommon/sysexe/sys.map X Xfinger: ${OBJS} X ${CC} -noshare -notraceback finger.c -o finger ${OBJS} X Xlint: X lint -hbx ${COPTS} ${SRCS} X Xclean: X rm -f ${OBJS} syssym.s *.mar vms/*.h finger core X Xfinger.o: finger.c vms/dvidef.h vms/jpidef.h vms/ssdef.h \ X vms/statedef.h vms/tt2def.h vms/ttdef.h X Xgetidle.o: getidle.c vms/dcdef.h vms/ddbdef.h vms/devdef.h \ X vms/ssdef.h vms/ttyucbdef.h vms/ucbdef.h X Xrmtinfo.o: rmtinfo.c vms/nfbdef.h vms/ssdef.h vms/iodef.h X Xsyssym.s: X egrep 'GL_ABSTIM|GL_DEVLIST|IPID_TO_EPID' ${SYSMAP} | \ X tr A-Z a-z | awk -f syssym.awk >syssym.s X Xsyssym.o: syssym.s X as -o syssym.o syssym.s X Xvms/dcdef.h: X vms library 'sys$$library:starlet.mlb /extra=($$dcdef) /out=dcdef.mar' X ${VMSSTRUCT} dcdef.mar >vms/dcdef.h X rm -f dcdef.mar X Xvms/ddbdef.h: ddbdef.i X vms library 'sys$$library:lib.mlb /extra=($$ddbdef) /out=ddbdef.mar' X ${VMSSTRUCT} -i ddbdef.i ddbdef.mar >vms/ddbdef.h X rm -f ddbdef.mar X Xvms/devdef.h: X vms library 'sys$$library:starlet.mlb /extra=($$devdef) /out=devdef.mar' X ${VMSSTRUCT} devdef.mar >vms/devdef.h X rm -f devdef.mar X Xvms/dvidef.h: X vms library 'sys$$library:starlet.mlb /extra=($$dvidef) /out=dvidef.mar' X ${VMSSTRUCT} dvidef.mar >vms/dvidef.h X rm -f dvidef.mar X Xvms/iodef.h: X vms library 'sys$$library:starlet.mlb /extra=($$iodef) /out=iodef.mar' X ${VMSSTRUCT} iodef.mar >vms/iodef.h X rm -f iodef.mar X Xvms/jpidef.h: X vms library 'sys$$library:starlet.mlb /extra=($$jpidef) /out=jpidef.mar' X ${VMSSTRUCT} jpidef.mar >vms/jpidef.h X rm -f jpidef.mar X Xvms/nfbdef.h: X vms library 'sys$$library:lib.mlb /extra=($$nfbdef) /out=nfbdef.mar' X ${VMSSTRUCT} nfbdef.mar >vms/nfbdef.h X rm -f nfbdef.mar X Xvms/ssdef.h: X vms library 'sys$$library:starlet.mlb /extra=($$ssdef) /out=ssdef.mar' X ${VMSSTRUCT} ssdef.mar >vms/ssdef.h X rm -f ssdef.mar X Xvms/statedef.h: X vms library 'sys$$library:lib.mlb /extra=($$statedef) /out=statedef.mar' X ${VMSSTRUCT} statedef.mar >vms/statedef.h X rm -f statedef.mar X Xvms/tt2def.h: X vms library 'sys$$library:starlet.mlb /extra=($$tt2def) /out=tt2def.mar' X ${VMSSTRUCT} tt2def.mar >vms/tt2def.h X rm -f tt2def.mar X Xvms/ttdef.h: X vms library 'sys$$library:starlet.mlb /extra=($$ttdef) /out=ttdef.mar' X ${VMSSTRUCT} ttdef.mar >vms/ttdef.h X rm -f ttdef.mar X Xvms/ttyucbdef.h: X vms library 'sys$$library:lib.mlb /extra=($$ttyucbdef) /out=ttyucbdef.mar' X egrep -v 'W_TT_DESIZE|W_RTT_SYSTYPE' ttyucbdef.mar >ttyucbdef.mar2 X ${VMSSTRUCT} ttyucbdef.mar2 >vms/ttyucbdef.h X rm -f ttyucbdef.mar ttyucbdef.mar2 X Xvms/ucbdef.h: ucbdef.i X vms library 'sys$$library:lib.mlb /extra=($$ucbdef) /out=ucbdef.mar' X ${VMSSTRUCT} -i ucbdef.i ucbdef.mar >vms/ucbdef.h X rm -f ucbdef.mar SHAR_EOF if test 2949 -ne "`wc -c < 'Makefile'`" then echo shar: error transmitting "'Makefile'" '(should have been 2949 characters)' fi fi # end of overwriting check echo shar: extracting "'README'" '(1196 characters)' if test -f 'README' then echo shar: will not over-write existing file "'README'" else sed 's/^X//' << \SHAR_EOF > 'README' X21-Jul-1987 X XHere's a Eunice emulation of /usr/ucb/finger. I've attempted to make it Xnot depend on local features of the Eunice I run, but I'm sure people Xwith older versions of Eunice will have some difficulty getting it to Xrun. (I have the 4.3 BSD Eunice and use this program under VMS V4.5.) X XThis program requires CMKRNL, WORLD, and NETMBX for normal use. Since Xit uses CMKRNL too look at kernel data structures (to get things like Xidle time and network location), I highly recommend that you test it on Xan unused system since simple errors in the building of this program Xcan crash your machine. X XThis version of finger displays username, real name, terminal, idle and Xlogin time, and location. Terminals with broadcasts disabled are noted Xwith an asterisk. It uses getpwent() to get the real name. Hardwired Xport locations are found in /etc/locations which looks similar this: X X opa0:,Console X tta0:,Machine room vt100 X tta1:,Machine room vt100 X tta2:,Dialup 666-1234 X tta3:,Dialup 666-1235 X tta4:,Portselector X tta5:,Portselector X tta6:, X tta7:,Craig's office X XInternet locations are determined by consulting gethostbyaddr(). XDECnet locations are determined by consulting NETACP. X X Craig SHAR_EOF if test 1196 -ne "`wc -c < 'README'`" then echo shar: error transmitting "'README'" '(should have been 1196 characters)' fi fi # end of overwriting check echo shar: extracting "'ddbdef.i'" '(67 characters)' if test -f 'ddbdef.i' then echo shar: will not over-write existing file "'ddbdef.i'" else sed 's/^X//' << \SHAR_EOF > 'ddbdef.i' Xstruct DDB *ddb$l_link Xstruct UCB *ddb$l_ucb Xstruct DDT *ddb$l_ddt SHAR_EOF if test 67 -ne "`wc -c < 'ddbdef.i'`" then echo shar: error transmitting "'ddbdef.i'" '(should have been 67 characters)' fi fi # end of overwriting check echo shar: extracting "'dsc.h'" '(85 characters)' if test -f 'dsc.h' then echo shar: will not over-write existing file "'dsc.h'" else sed 's/^X//' << \SHAR_EOF > 'dsc.h' X/* X * Standard VMS string descriptor X */ X Xstruct dsc { X int d_len; X char * d_buf; X}; SHAR_EOF if test 85 -ne "`wc -c < 'dsc.h'`" then echo shar: error transmitting "'dsc.h'" '(should have been 85 characters)' fi fi # end of overwriting check echo shar: extracting "'finger.c'" '(13167 characters)' if test -f 'finger.c' then echo shar: will not over-write existing file "'finger.c'" else sed 's/^X//' << \SHAR_EOF > 'finger.c' X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: finger.c,v 1.13 87/04/21 17:50:03 leres Exp $ (LBL)"; X#endif X/* X * VAX/VMS finger X * X * Craig Leres, Lawrence Berkeley Laboratory X */ X X#include <stdio.h> X#include <ctype.h> X#include <string.h> X#include <pwd.h> X#include <sys/types.h> X#include <sys/socket.h> X#include <netdb.h> X#include <netinet/in.h> X#include <arpa/inet.h> X X#include <eunice/eunice.h> X X#include "vms/jpidef.h" X#include "vms/dvidef.h" X#include "vms/ttdef.h" X#include "vms/tt2def.h" X#include "vms/ssdef.h" X#include "vms/statedef.h" X X#include "item_list_3.h" X#include "dsc.h" X X/* People list */ Xstruct plist { X struct plist *p_next; X char *p_realname; X char *p_location; X u_long p_logintime; X long p_idletime; X u_long p_pid; X u_long p_state; X u_long p_net; X int p_nomesg; X char p_username[16]; X char p_terminal[8]; X}; X X/* Remote locations */ Xstatic struct rlist { X struct rlist *r_next; X u_long r_net; X char *r_location; X}; X X/* Variables for jpi call */ Xstatic char busername[13]; Xstatic short lusername; Xstatic char bterminal[8]; Xstatic short lterminal; Xstatic u_long blogintime[2]; Xstatic u_long bstate; X Xstatic struct item_list_3 itmlst[] = { X sizeof(busername) - 1, JPI$_USERNAME, busername, &lusername, X sizeof(bterminal) - 1, JPI$_TERMINAL, bterminal, <erminal, X sizeof(blogintime), JPI$_LOGINTIM, (char *)blogintime, 0, X sizeof(bstate), JPI$_STATE, (char *)&bstate, 0, X 0, 0, 0, 0 X}; X X/* Variables for dvi call */ Xstatic u_long bdevdepend, bdevdepend2; X Xstatic struct item_list_3 dvilst[] = { X sizeof(bdevdepend), DVI$_DEVDEPEND, (char *)&bdevdepend, 0, X sizeof(bdevdepend2), DVI$_DEVDEPEND2, (char *)&bdevdepend2, 0, X 0, 0, 0, 0 X}; X X/* Function declarations */ Xchar *malloc(), *pidle(), *ptime(), *getstate(), *getnetloc(); Xu_long cvt_to_unix_time(); Xstruct plist *makelist(); X X/* Globals */ Xchar *argv0; /* Program name pointer */ Xstruct rlist *netlocs = 0; /* List of remote locations */ Xint doseconds = 0; /* display seconds of idle time */ Xint dofast = 0; /* display locations by default */ X Xextern int vmserrno; X X#define SAVESTR(cp) strcpy(malloc(strlen(cp) + 1), cp) X Xmain(argc, argv) X int argc; X char *argv[]; X{ X register int i; X register char *cp; X register struct plist *pp; X int didany; X char *usage = "usage: %s [-fs] [[user]@host] ...\n"; X X argv0 = argv[0]; X X /* Handle arguments */ X didany = 0; X for (i = 1; i < argc; i++) { X cp = argv[i]; X if (netfinger(cp)) { X didany++; X continue; X } X if (*cp != '-') { X fprintf(stderr, usage, argv0); X exit(1); X } X for (cp++; *cp != '\0'; cp++) X switch (*cp) { X X case 'f': X dofast++; X break; X case 's': X doseconds++; X break; X default: X fprintf(stderr, usage, argv0); X exit(1); X } X } X if (didany) X exit(0); X X /* Get the stuff */ X pp = makelist(); X X /* Fill in the locations */ X getlocs(pp); X X /* Fill in the real names */ X getreal(pp); X X /* Output the data */ X printf("Login Name TTY Idle When Location\n"); X while (pp) { X /* X * Print out info about one user X */ X printf("%-12.12s %-20.20s%c%4s %4s %9.9s", X pp->p_username, X pp->p_realname ? pp->p_realname : "", X pp->p_nomesg ? '*' : ' ', X pp->p_terminal, X pidle(pp->p_idletime), X pp->p_logintime ? X ptime(pp->p_logintime) : getstate(pp->p_state)); X if (pp->p_location) X printf(" %s", pp->p_location); X putchar('\n'); X pp = pp->p_next; X } X exit(0); X} X X/* X * Create the list of logged in users X */ Xstruct plist * Xmakelist() X{ X register int i, j; X long *lp_tim; X u_long *lp_pid; X u_long *lp_net; X struct plist *p, *pp, *plast, pjunk; X long iosb[2]; X X /* Get the idle time info */ X vmserrno = getidle(&lp_tim, &lp_pid, &lp_net); X if ((vmserrno & 1) == 0) { X fprintf(stderr, "%s: ", argv0); X vmsperror("getidle()"); X exit(1); X } X X /* Loop through the idle info and build the list */ X bzero((char *)&pjunk, sizeof(struct plist)); X for (i = 0; lp_pid[i]; i++) { X bterminal[0] = '\0'; X vmserrno = sys$getjpiw(0, &lp_pid[i], 0, itmlst, iosb, 0, 0); X if (vmserrno & 1 || vmserrno == SS$_SUSPENDED) X vmserrno = iosb[0]; X if (vmserrno == SS$_NONEXPR) X continue; X if ((vmserrno & 1) == 0 && vmserrno != SS$_SUSPENDED) { X fprintf(stderr, "%s: ", argv0); X vmsperror("sys$getjpiw()"); X exit(1); X } X if (bterminal[0] == '\0') X continue; X p = (struct plist *) malloc(sizeof(struct plist)); X bzero((char *)p, sizeof(struct plist)); X busername[lusername] = '\0'; X munch(busername); X (void) strcpy(p->p_username, busername); X if (lterminal > 1 && bterminal[lterminal-1] == ':') X lterminal--; X bterminal[lterminal] = '\0'; X munch(bterminal); X (void) strcpy(p->p_terminal, bterminal); X if (vmserrno != SS$_SUSPENDED) X p->p_logintime = cvt_to_unix_time(blogintime); X else X p->p_logintime = 0; X p->p_state = bstate; X p->p_idletime = lp_tim[i]; X p->p_pid = lp_pid[i]; X p->p_nomesg = nomesg(bterminal); X if (p->p_net = lp_net[i]) X p->p_location = getnetloc(p->p_net, p->p_terminal); X X /* Insert in proper order */ X plast = &pjunk; X for (pp = plast->p_next; pp; pp = pp->p_next) { X if ((j = ttycmp(p->p_terminal, pp->p_terminal)) < 0) { X /* Insert in front */ X p->p_next = plast->p_next; X plast->p_next = p; X p = 0; X break; X } else if (j == 0 && p->p_pid == pp->p_pid) { X /* X * Managed to get some terminal twice. X * This can happen if someone allocates X * a terminal that isn't logged in... X * X * Keep one of the two entries. Keep the new X * entry if it has a location (implying it's a X * network entry) or has a non zero idle time. X */ X if (p->p_location != 0 || p->p_idletime > 0) { X pp->p_idletime = p->p_idletime; X pp->p_net = p->p_net; X pp->p_location = p->p_location; X } X p = 0; X break; X } X plast = pp; X } X if (p) X plast->p_next = p; X } X return(pjunk.p_next); X} X X/* X * Pound a string to lowercase and lose trailing spaces X */ Xstatic munch(str) X char *str; X{ X register char *cp; X X for (cp = str; *cp != ' ' && *cp != '\0' && *cp != '\n'; cp++) X if (isupper(*cp)) X *cp = tolower(*cp); X *cp = '\0'; X} X X/* X * Add locations to the list X */ Xgetlocs(p) X struct plist *p; X{ X int todo; X register struct plist *pp; X register char *cp; X char line[256]; X FILE *f; X X /* If no locations file, no thing to do */ X if ((f = fopen("/etc/locations","r")) == NULL) X return; X X /* Count number of entries to do */ X todo = 0; X for (pp = p; pp; pp = pp->p_next) X if (pp->p_location == 0) X todo++; X X /* Read the locations file once, updating list as we go along */ X while (todo > 0 && fgets(line, sizeof(line), f) != NULL) { X line[sizeof(line)-1] = '\0'; X if ((cp = index(line, '\n')) != NULL) X *cp = '\0'; X if ((cp = index(line, ',')) != NULL) X *cp++ = '\0'; X for (pp = p; pp; pp = pp->p_next) X if (pp->p_location == 0 && strcmpn(pp->p_terminal, X line, strlen(pp->p_terminal)) == 0) { X pp->p_location = SAVESTR(cp); X todo--; X break; X } X } X (void) fclose(f); X return; X} X X/* X * Add real names to the list X */ Xgetreal(p) X struct plist *p; X{ X register struct plist *pp; X register struct passwd *pw; X register char *cp, *name; X int todo; X X /* Can't do much here without the password file */ X if (setpwent() == 0) X return; X X /* Count number of entries */ X todo = 0; X for (pp = p; pp; pp = pp->p_next) X todo++; X X /* Read the password file once, updating list as we go along */ X while (todo > 0 && (pw = getpwent())) { X name = 0; X for (pp = p; pp; pp = pp->p_next) X if (strcmp(pp->p_username, pw->pw_name) == 0) { X if (name == 0) { X name = SAVESTR(pw->pw_gecos); X if ((cp = index(name, ',')) != NULL) X *cp = '\0'; X } X pp->p_realname = name; X todo--; X } X } X (void) endpwent(); X return; X} X X/* X * Format idle time X */ Xchar * Xpidle(idle) X long idle; X{ X register long l; X static char idlebuf[16]; X X if ((l = idle/60) == 0) { X if (idle > 0 && doseconds) X (void) sprintf(idlebuf, "%ds", idle); X else X idlebuf[0] = '\0'; X } else if (l < 60) X (void) sprintf(idlebuf, "%d", l); X else if (l/60 < 10) X (void) sprintf(idlebuf, "%d:%02d", l/60, l%60); X else if ((l = l/60) < 24) X (void) sprintf(idlebuf, "%dh", l); X else X (void) sprintf(idlebuf, "%dd", l/24); X return(idlebuf); X} X X/* X * Format the time X */ Xchar * Xptime(u) X u_long u; X{ X static char timebuf[32]; X struct tm *tp; X static char days[][4] = { X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" X }; X X if (u == 0) X return("<susp>"); X X tp = localtime(&u); X (void) sprintf(timebuf,"%s %2d:%02d", X days[tp->tm_wday], X tp->tm_hour, X tp->tm_min); X return(timebuf); X} X X/* X * Determine if a terminal has broadcasts disabled X */ Xnomesg(tty) X char *tty; X{ X struct dsc tdsc; X long iosb[2]; X X tdsc.d_buf = tty; X tdsc.d_len = strlen(tdsc.d_buf); X X vmserrno = sys$getdviw(0, 0, &tdsc, dvilst, iosb, 0, 0, 0); X if (vmserrno & 1) X vmserrno = iosb[0]; X if ((vmserrno & 1) == 0) { X fprintf(stderr, "%s: ", argv0); X vmsperror("sys$getdviw()"); X exit(1); X } X return((bdevdepend & TT$M_NOBRDCST) != 0 && X (bdevdepend2 & TT2$M_BRDCSTMBX) == 0); X} X X/* X * Determine the network location of a terminal X */ Xchar * Xgetnetloc(n, tty) X u_long n; X char *tty; X{ X register struct rlist *rp; X struct hostent *hp; X char host[32], loc[256]; X long node; X X /* First, check if we've already figured this one out */ X for (rp = netlocs; rp; rp = rp->r_next) X if (n == rp->r_net) X return(rp->r_location); X X /* Figure this one out for the first time */ X if (strcmpn(tty, "nty", 3) == 0 || strcmpn(tty, "nta", 3) == 0) { X if (dofast == 0 && X (hp = gethostbyaddr(&n, sizeof(u_long), AF_INET))) X (void) strcpy(loc, hp->h_name); X else X (void) sprintf(loc, "%d.%d.%d.%d", X n & 0xff, X n >> 8 & 0xff, X n >> 16 & 0xff, X n >> 24 & 0xff); X } else { X host[0] = '\0'; X if (((vmserrno = rmtinfo(n, &node, host)) & 1) == 0) { X fprintf(stderr, "%s: ", argv0); X vmsperror("rmtinfo()"); X exit(1); X } X if (host[0] != '\0') X (void) strcpy(loc, host); X else X (void) sprintf(loc, "node %d", node); X } X X /* Add this one to our list */ X rp = (struct rlist *) malloc(sizeof(struct rlist)); X bzero((char *)rp, sizeof(struct rlist)); X rp->r_net = n; X rp->r_location = SAVESTR(loc); X if (netlocs) { X rp->r_next = netlocs->r_next; X netlocs->r_next = rp; X } else X netlocs = rp; X X return(rp->r_location); X} X Xchar * Xgetstate(state) X u_long state; X{ X static char buf[32]; X X switch (state) { X X case SCH$C_CEF: X return("<cef>"); X case SCH$C_COM: X return("<com>"); X case SCH$C_COMO: X return("<como>"); X case SCH$C_CUR: X return("<cur>"); X case SCH$C_COLPG: X return("<colpg>"); X case SCH$C_FPG: X return("<fpg>"); X case SCH$C_HIB: X return("<hib>"); X case SCH$C_HIBO: X return("<hibo>"); X case SCH$C_LEF: X return("<lef>"); X case SCH$C_LEFO: X return("<lefo>"); X case SCH$C_MWAIT: X return("<mwait>"); X case SCH$C_PFW: X return("<pfw>"); X case SCH$C_SUSP: X return("<susp>"); X case SCH$C_SUSPO: X return("<suspo>"); X } X return(sprintf(buf, "<%d>", state)); X} X X/* X * Similar to strcmp() but handles trailing unit number part numerically. X */ Xttycmp(s1, s2) X register char *s1, *s2; X{ X X while (isalpha(*s1) && isalpha(*s2) && *s1 == *s2++) X if (*s1++=='\0') X return(0); X if (isdigit(*s1) && isdigit(*s2)) X return(atoi(s1) - atoi(s2)); X return(*s1 - *--s2); X} X X/* X * Finger a remote machine X */ Xnetfinger(name) X char *name; X{ X char *host; X struct hostent *hp; X struct servent *sp; X struct sockaddr_in sin; X int s; X register FILE *f; X register int c; X register int lastc; X X if (name == 0) X return (0); X if ((host = rindex(name, '@')) == 0) X return (0); X *host++ = '\0'; X bzero((char *)&sin, sizeof (sin)); X if ((sin.sin_addr.s_addr = inet_addr(host)) != -1) X sin.sin_family = AF_INET; X else if ((hp = gethostbyname(host)) != 0) { X sin.sin_family = hp->h_addrtype; X bcopy(hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length); X host = hp->h_name; X } else { X printf("%s: unknown host\n", host); X return(1); X } X printf("[%s]", host); X if ((sp = getservbyname("finger", "tcp")) == 0) { X printf("tcp/finger: unknown service\n"); X return (1); X } X sin.sin_port = sp->s_port; X s = socket(sin.sin_family, SOCK_STREAM, 0); X if (s < 0) { X (void) fflush(stdout); X perror("socket"); X return (1); X } X if (connect(s, (char *)&sin, sizeof (sin)) < 0) { X (void) fflush(stdout); X perror("connect"); X (void) close(s); X return (1); X } X putchar('\n'); X#ifdef notdef X if (large) X write(s, "/W ", 3); X#endif X write(s, name, strlen(name)); X write(s, "\r\n", 2); X f = fdopen(s, "r"); X while ((c = getc(f)) != EOF) { X switch(c) { X case 0210: X case 0211: X case 0212: X case 0214: X c -= 0200; X break; X case 0215: X c = '\n'; X break; X } X lastc = c; X if (isprint(c) || isspace(c)) X putchar(c); X else X putchar(c ^ 100); X } X if (lastc != '\n') X putchar('\n'); X (void) fclose(f); X return (1); X} X X/* X * Convert a VMS time quadword to Unix format X */ Xstatic u_long Xcvt_to_unix_time(time) X u_long time[2]; X{ X u_long local[2]; X int dummy; X static int January_1_1970[2] = {0x4bec0000,0x007c9567}; X X local[0] = time[0]; local[1] = time[1]; X _$Subtract_Quadword(January_1_1970, local); X if (!(_$Cache_Flags & _$GMT_VALID)) _$Get_GMT_Info(); X return(_$EDIV(10000000, local, &dummy) + _$Seconds_From_GMT); X} SHAR_EOF if test 13167 -ne "`wc -c < 'finger.c'`" then echo shar: error transmitting "'finger.c'" '(should have been 13167 characters)' fi fi # end of overwriting check echo shar: extracting "'getidle.c'" '(3921 characters)' if test -f 'getidle.c' then echo shar: will not over-write existing file "'getidle.c'" else sed 's/^X//' << \SHAR_EOF > 'getidle.c' X/* X * getidle() - determine idle information for terminals (privileged) X * X * revision history X * X * 05b 18Jul86 cal .Modified to reference system variables as externs. X * Wrote exe_ipid_to_epid() using asm()s. X * 05a 01Apr86 cal .Converted to VMS V4. X * 04a 19Mar84 cal .First "c" version. X * X * synopsis X * X * #include <sys/types.h> X * X * int status, getidle(); X * long *ap_tim; X * u_long *ap_tim; X * u_long *ap_tim; X * X * status = getidle([&ap_tim], &ap_pid, [&ap_net]); X * X * ap_tim - pointer to receive idle time buffer (optional) X * ap_pid - pointer to receive pid buffer X * ap_net - pointer to receive net address buffer (optional) X * status - returned VMS status X * X * The optional arguments may be replaced with "0". The idle times, X * process ids, and net values are stored in the buffers in consecutive X * elements with a zero longword in the pid buffer to mark end of the X * list. X * X * The net address buffer contains either the Decnet logical link number X * for a remote terminal or else the host address for a "nty" port. X * X * The information is ordered by terminal name. X * X * Note: Use of this routine requires the privilege CMKRNL. X * X */ X X#include <sys/types.h> X#include <netinet/in.h> X X#include "vms/ucbdef.h" X#include "vms/ddbdef.h" X#include "vms/ttyucbdef.h" X#include "vms/dcdef.h" X#include "vms/devdef.h" X#include "vms/ssdef.h" X Xstatic struct XUCB { X char xucb_dummy[0x13c]; X u_long xucb$x_netaddr; X}; X Xextern struct DDB *ioc$gl_devlist; Xextern int exe$gl_abstim; X Xstatic int idlekrn(); Xstatic u_long exe_ipid_to_epid(); X X/* X * Useful constants X */ X X#define FUDGE 2 /* add this to exe$gl_abstim */ X#define MAX_UNITS 128 /* max units to report about */ X Xstatic long bl_tim[MAX_UNITS]; Xstatic u_long bl_pid[MAX_UNITS]; Xstatic u_long bl_net[MAX_UNITS]; X Xgetidle(ap_tim, ap_pid, ap_net) X long **ap_tim; X u_long **ap_pid; X u_long **ap_net; X{ X register int i; X X#ifdef notdef X status = sys$lkwset(); X if (status != SS$_WASCLR && status != SS$_WASSET) X return(status); X#endif X i = sys$cmkrnl(idlekrn, 0); X#ifdef notdef X status = sys$ulwset(); X if (status != SS$_WASCLR && status != SS$_WASSET) X return(status); X#endif X if (i != SS$_NORMAL) X return(i); X if (ap_tim) X *ap_tim = bl_tim; X *ap_pid = bl_pid; X if (ap_net) X *ap_net = bl_net; X return(SS$_NORMAL); X} X X X/* X * Entry point for the privileged search and slurp. X */ X Xstatic u_long *nty = (u_long *)"\003NTY"; Xstatic u_long *nta = (u_long *)"\003NTA"; X Xstatic idlekrn() X{ X register int i; X register struct UCB *up; X register struct DDB *dp; X register u_long *p_pid; X register long *p_tim; X register u_long *p_net; X char *cp; X int now; X int status; X X i = 0; X status = SS$_NORMAL; X p_tim = bl_tim; X p_pid = bl_pid; X p_net = bl_net; X X now = exe$gl_abstim + FUDGE; X#ifdef notdef X asm("jsb _sch$iolockr"); X#endif X X for (dp = ioc$gl_devlist; dp; dp = dp->ddb$l_link) { X if ((up = dp->ddb$l_ucb) == 0 || up->ucb$b_devclass != DC$_TERM) X continue; X for ( ; up; up = up->ucb$l_link) { X if (up->ucb$l_pid == 0) X continue; X X /* Store process id */ X *p_pid++ = exe_ipid_to_epid(up->ucb$l_pid); X X /* Get idle time */ X if ((up->ucb$w_sts & UCB$M_TIM) != 0 || X (up->ucb$w_sts & UCB$M_BSY) == 0 || X (*p_tim = now - up->ucb$l_duetim) < 0) X *p_tim = 0; X p_tim++; X X /* Get network info (if a rta, nty, or nta) */ X *p_net = 0; X if ((up->ucb$l_devchar2 & DEV$M_RTT) != 0) X *p_net = ((struct TTYUCB *)up)->ucb$w_rtt_link; X else if (*nty == *(u_long *)dp->ddb$t_name || X *nta == *(u_long *)dp->ddb$t_name) X *p_net = ((struct XUCB *)up)->xucb$x_netaddr; X p_net++; X X if (++i >= MAX_UNITS) { X status = SS$_BUFFEROVF; X goto done; X } X } X } Xdone: X X#ifdef notdef X asm("jsb _sch$iounlock"); X#endif X *p_pid = 0; X return(status); X} X Xstatic u_long Xexe_ipid_to_epid(pid) X u_long pid; X{ X#ifdef lint X return(pid); X#else X asm("movl 4(ap),r0"); X asm("jsb _exe$ipid_to_epid"); X asm("ret"); X#endif X} SHAR_EOF if test 3921 -ne "`wc -c < 'getidle.c'`" then echo shar: error transmitting "'getidle.c'" '(should have been 3921 characters)' fi fi # end of overwriting check echo shar: extracting "'item_list_3.h'" '(258 characters)' if test -f 'item_list_3.h' then echo shar: will not over-write existing file "'item_list_3.h'" else sed 's/^X//' << \SHAR_EOF > 'item_list_3.h' X/* X * Define the standard item list 3 struct. X */ X Xstruct item_list_3 { X short i_length; /* length of user buffer */ X short i_code; /* request code number */ X char *i_buffer; /* buffer address */ X short *i_rslength; /* result length address */ X}; SHAR_EOF if test 258 -ne "`wc -c < 'item_list_3.h'`" then echo shar: error transmitting "'item_list_3.h'" '(should have been 258 characters)' fi fi # end of overwriting check echo shar: extracting "'rmtinfo.c'" '(3042 characters)' if test -f 'rmtinfo.c' then echo shar: will not over-write existing file "'rmtinfo.c'" else sed 's/^X//' << \SHAR_EOF > 'rmtinfo.c' X#ifndef lint Xstatic char rcsid[] = X "@(#) $Header: rmtinfo.c,v 1.3 87/04/09 20:20:51 leres Exp $ (LBL)"; X#endif X/* X * The privilege NETMBX is required for use. X * X * Warning: This routine is chalked full of undocumented MAGIC. X */ X#include <ctype.h> X#include <strings.h> X X#include "vms/nfbdef.h" X#include "vms/ssdef.h" X#include "vms/iodef.h" X X/* X * Use nfb block to help define what we need. X */ Xstatic struct XNFB { X struct NFB x; X#define xnfb$b_fct x.nfb$b_fct X#define xnfb$b_flags x.nfb$b_flags X#define xnfb$b_database x.nfb$b_database X#define xnfb$b_oper x.nfb$b_oper X#define xnfb$l_srch_key x.nfb$l_srch_key X#define xnfb$l_srch2_key x.nfb$l_srch2_key X#define xnfb$l_x_lli_pna x.nfb$l_fldid X unsigned long xnfb$l_x_lli_pnn; X unsigned long xnfb$l_x_endoflist; X} nfb; X Xstatic struct acpbuf { X long a_node; /* decnet node number */ X short a_length; /* length of the decnet host name */ X char a_name[6]; /* decnet host name */ X} abuf; X Xstatic struct dsc { X long d_length; X char *d_address; X}; X Xrmtinfo(link, node, name) X long link; X long *node; X char *name; X{ X register int i, status; X int sys$assign(), sys$qiow(); X short iosb[4]; X struct dsc netdsc, nfbdsc, keydsc, bufdsc; X long key[2]; X static int chan = 0; X X /* X * If necessary, assign a channel to NET X */ X if (!chan) { X netdsc.d_address = "NET:"; X netdsc.d_length = strlen(netdsc.d_address); X if ((status = sys$assign(&netdsc, &chan, 0, 0)) != SS$_NORMAL) X return(status); X } X /* X * Set up the nfb request buffer X */ X bzero(&nfb, sizeof(nfb)); X nfb.xnfb$b_fct = NFB$C_FC_SHOW; X nfb.xnfb$b_flags = NFB$M_NOCTX; /* don't update the database */ X nfb.xnfb$b_database = NFB$C_DB_LLI; /* logical link info database */ X nfb.xnfb$b_oper = NFB$C_OP_EQL; /* match the key exactly */ X nfb.xnfb$l_srch_key = NFB$C_LLI_LLN; /* key is logical link number */ X nfb.xnfb$l_srch2_key = NFB$C_WILDCARD; /* search the whole database */ X nfb.xnfb$l_x_lli_pna = NFB$C_LLI_PNA; /* partner's node address */ X nfb.xnfb$l_x_lli_pnn = NFB$C_LLI_PNN; /* partner's node name */ X nfb.xnfb$l_x_endoflist = NFB$C_ENDOFLIST; X /* X * Construct the nfb descriptor X */ X nfbdsc.d_address = (char *) &nfb; X nfbdsc.d_length = sizeof(nfb); X /* X * Construct the key descriptor X */ X keydsc.d_address = (char *) &key[0]; X keydsc.d_length = sizeof(key); X /* X * Construct the logical link key descriptor X */ X key[0] = 0; X key[1] = link; X /* X * Construct the return buffer descriptor X */ X bufdsc.d_address = (char *) &abuf; X bufdsc.d_length = sizeof(abuf); X /* X * Ask NET about this port X */ X status = sys$qiow(0, chan, IO$_ACPCONTROL, iosb, 0, 0, X &nfbdsc, &keydsc, 0, &bufdsc, 0, 0); X if (status != SS$_NORMAL) X return(status); X status = iosb[0]; X if (status != SS$_NORMAL) X return(status); X /* X * Return the node number X */ X *node = abuf.a_node; X /* X * Return the node name X */ X if ((i = abuf.a_length) > sizeof(abuf.a_name)) X i = sizeof(abuf.a_name); X name[i] = '\0'; X for (--i; i >= 0; i--) X if (isupper(name[i] = abuf.a_name[i])) X name[i] = tolower(name[i]); X return(SS$_NORMAL); X} SHAR_EOF if test 3042 -ne "`wc -c < 'rmtinfo.c'`" then echo shar: error transmitting "'rmtinfo.c'" '(should have been 3042 characters)' fi fi # end of overwriting check echo shar: extracting "'syssym.awk'" '(115 characters)' if test -f 'syssym.awk' then echo shar: will not over-write existing file "'syssym.awk'" else sed 's/^X//' << \SHAR_EOF > 'syssym.awk' X/^8/ { X name = substr( $2, 3, length ( $2 ) - 2 ) X printf("\n\t.globl\t_%s\n\t.set\t_%s,0x%s\n", name, name, $1) X} SHAR_EOF if test 115 -ne "`wc -c < 'syssym.awk'`" then echo shar: error transmitting "'syssym.awk'" '(should have been 115 characters)' fi fi # end of overwriting check echo shar: extracting "'ucbdef.i'" '(284 characters)' if test -f 'ucbdef.i' then echo shar: will not over-write existing file "'ucbdef.i'" else sed 's/^X//' << \SHAR_EOF > 'ucbdef.i' Xstruct FKB *ucb$l_fqfl Xstruct FKB *ucb$l_fqbl Xstruct CRB *ucb$l_crb Xstruct DDB *ucb$l_ddb Xstruct UCB *ucb$l_link Xstruct VCB *ucb$l_vcb Xstruct IRP *ucb$l_ioqfl Xstruct IRP *ucb$l_ioqbl Xstruct IRP *ucb$lirp Xstruct UCB *ucb$l_amb Xchar *ucb$l_svpn Xchar *ucb$l_svapte Xstruct DDT *ucb$l_ddt SHAR_EOF if test 284 -ne "`wc -c < 'ucbdef.i'`" then echo shar: error transmitting "'ucbdef.i'" '(should have been 284 characters)' fi fi # end of overwriting check if test ! -d 'vms' then echo shar: creating directory "'vms'" mkdir 'vms' fi echo shar: entering directory "'vms'" cd 'vms' echo shar: done with directory "'vms'" cd .. echo shar: extracting "'vmsperror.c'" '(491 characters)' if test -f 'vmsperror.c' then echo shar: will not over-write existing file "'vmsperror.c'" else sed 's/^X//' << \SHAR_EOF > 'vmsperror.c' X#include <stdio.h> X X#include "dsc.h" X Xextern int vmserrno; X Xvmsperror(s) X char *s; X{ X int status; X unsigned short len; X struct dsc dsc; X char buf[128]; X X dsc.d_buf = buf; X dsc.d_len = sizeof(buf); X len = 0; X if (((status = sys$getmsg(vmserrno, &len, &dsc, 0xf, 0)) & 1) == 0) { X sprintf(buf, "0x%x (0x%x)", vmserrno, status); X len = strlen(buf); X } X write(fileno(stderr), s, strlen(s)); X write(fileno(stderr), ": ", 2); X write(fileno(stderr), buf, len); X write(fileno(stderr), "\n", 1); X} SHAR_EOF if test 491 -ne "`wc -c < 'vmsperror.c'`" then echo shar: error transmitting "'vmsperror.c'" '(should have been 491 characters)' fi fi # end of overwriting check # End of shell archive exit 0