eps@toaster.SFSU.EDU (Eric P. Scott) (01/22/90)
I finally got tired of the ptys not-cleaned-up-after by Terminal et al., and killing off scores of comsats and ntalkds that glom on to them. Yes, it's another one of my infamous quick-and-dirty hacks! Ghostbuster scans utmp for logged-in ptys with no controlling process, and logs them out properly. It will message syslogd if it catches anything, so you can tell it's been working. What do you do with it? To be honest, I don't really know (could have something to do with the late hour :-) )--it could be run out of cron, or as a LogoutHook, or whatever. Anyway, enjoy. -=EPS=- K&R C, BSD conventions, depends on int==32 bits, runs as root. ------- /* * ghostbuster - log out orphaned ptys * Eric P. Scott, San Francisco State University, January 1990 * * cc -o ghostbuster -s -O -bsd ghostbuster.c -lsys_s * chown root.tty ghostbuster * chmod 4755 ghostbuster */ #include <stdio.h> #include <grp.h> #include <utmp.h> #include <sys/types.h> #include <sys/file.h> #include <sys/stat.h> #include <sys/syslog.h> main(argc, argv) int argc; char *argv[]; { char *malloc(); time_t time(); register struct utmp *ut; register char *ubuf; register struct group *gr; register int s; int u, w, p; struct stat st; char devname[12]; s=3; do close(s); while (++s<20); openlog("ghostbuster", LOG_PID, LOG_AUTH); if ((u=open("/etc/utmp", O_RDWR))<0) { syslog(LOG_ERR, "/etc/utmp: %m"); exit(1); } gr=getgrnam("tty"); endgrent(); (void)fstat(u, &st); if ((st.st_size%sizeof (struct utmp))!=0) { syslog(LOG_ALERT, "utmp corrupt"); exit(1); } if (!(ubuf=malloc(st.st_size))) abort(); if ((s=read(u, ubuf, st.st_size))!=st.st_size) { if (s<0) syslog(LOG_ERR, "read error: %m"); else syslog(LOG_ERR, "read expected %d, got %d\n", st.st_size, s); exit(1); } s/=sizeof (struct utmp); for (ut=(struct utmp *)ubuf;s>0;--s,ut++) { if (ut->ut_line[0]!='t'||ut->ut_line[1]!='t'|| ut->ut_line[2]!='y'|| ut->ut_line[3]<'p'|| ut->ut_line[3]>'s'||!ut->ut_name[0]) continue; sprintf(devname, "/dev/pty%.5s", &ut->ut_line[3]); if ((p=open(devname, O_RDWR))<0) continue; devname[5]='t'; bzero(ut->ut_name, sizeof ut->ut_name); bzero(ut->ut_host, sizeof ut->ut_host); (void)time(&ut->ut_time); if ((w=open("/usr/adm/wtmp", O_WRONLY|O_APPEND))>=0) { (void)write(w, (char *)ut, sizeof (struct utmp)); (void)close(w); } (void)lseek(u, (long)((char *)ut-ubuf), L_SET); (void)write(u, (char *)ut, sizeof (struct utmp)); (void)chmod(devname, 0666); (void)chown(devname, 0, gr ? gr->gr_gid : 0); (void)close(p); syslog(LOG_NOTICE, "%s logged out", ut->ut_line); } (void)close(u); exit(0); }