SOLARIS 2.3: Looking for program to clean utmp

SOLARIS 2.3: Looking for program to clean utmp

Post by Budi Rahard » Mon, 21 Mar 1994 01:30:20



I am looking for the programs/[perl]scripts that can clean utmp for Solaris 2.3.
For some reasons, userid(s) is still there even the user has logout.
I am planning to run this program periodically.

Also I am looking for admin stuff, e.g. program that can trim
adm/wtmpx, various log files, messages, etc.

Sorry if this topic has been beaten to death.
E-mail reply is preffered, but posting is also okay.
Thanks.

-- budi
--
Budi Rahardjo

Electrical Engineering - University of Manitoba - Canada

 
 
 

SOLARIS 2.3: Looking for program to clean utmp

Post by Ian Donalds » Tue, 22 Mar 1994 09:02:40


rah...@eeserv.ee.umanitoba.ca (Budi Rahardjo) writes:
>I am looking for the programs/[perl]scripts that can clean utmp for Solaris 2.3.
>For some reasons, userid(s) is still there even the user has logout.
>I am planning to run this program periodically.
>Also I am looking for admin stuff, e.g. program that can trim
>adm/wtmpx, various log files, messages, etc.
>Sorry if this topic has been beaten to death.
>E-mail reply is preffered, but posting is also okay.
>Thanks.

Ok, here's mine.  Written years ago originally for SunOS 3.5, but ported
to SunOS 4, Solaris 2.3 and SVR4.0.  Why does *everybody* screw this up?

Not a shar file, unfortunately.  Strip leading X's, write to given file.

For SVR4.0 and Solaris, there are two programs, cleanutmp, and cleanutmpx,
which must be run one after the other, immediately via cron.
Run them both once every 15 mins or so.

No warranty...  and totally unsupported by me.

Ian M. Donaldson

Systems Programmer
Labtam Australia Pty Ltd,
41-43 Malcolm Rd. Braeside
P.O. Box 297, Mordialloc, 3915
Melbourne, Australia

Email:  i...@labtam.labtam.oz.au
Phone:  +61-3-587-1444
Fax:    +61-3-580-5581

----Makefile------
XCPPFLAGS=-DUSG -DSVR4
XCFLAGS=-O $(CPPFLAGS)
XLDFLAGS=
XLIBS=
X
XCSRCS= cleanutmp.c cleanutmpx.c
X
Xall: cleanutmp cleanutmpx
X      
Xcleanutmp: cleanutmp.c
X       $(CC) $(LDFLAGS) -o cleanutmp cleanutmp.c $(LIBS) $(CFLAGS)
X
Xcleanutmpx: cleanutmpx.c
X       $(CC) $(LDFLAGS) -o cleanutmpx cleanutmpx.c $(LIBS) -DFIDDLE_UTMPX $(CFLAGS)
X
Xsvr3:
X       $(MAKE) LIBS="-lbsd" CPPFLAGS="-DUSG" cleanutmp
X
Xsunos:
X       $(MAKE) LIBS="" CPPFLAGS="" cleanutmp
X
X
Xcleanutmpx.c: cleanutmp.c
X       $(RM) $@
X       ln $? $@
X
Xclean:
X       rm -f cleanutmp.o cleanutmpx.c
X
Xclobber: clean
X       rm -f cleanutmp cleanutmpx
X
Xlint: $(CSRC)
X       lint $(CPPFLAGS) $(CSRCS)
----Makefile------

----cleanutmp.c----
X/*
X * cleans /etc/utmp of bogus crap (due to suntools/xterm mainly)
X */
X#include <sys/types.h>
X#include <fcntl.h>
X#ifndef USG
X#include <sys/file.h>
X#endif
X#include <sys/ioctl.h>
X#include <sys/stat.h>
X#ifdef FIDDLE_UTMPX
X#include <utmpx.h>
X#else
X#include <utmp.h>
X#endif
X#include <stdio.h>
X#ifdef __STDC__
X#include <stdlib.h>
X#endif
X#include <signal.h>
X#ifdef USG
X#include <string.h>
X#include <unistd.h>
X#else
X#include <strings.h>
X#endif
X#include <time.h>
X#include <errno.h>
X
X#ifdef USG
X#ifdef FIDDLE_UTMPX
X#define UTMP UTMPX_FILE
X#else
X#define UTMP UTMP_FILE
X#endif
X#define L_INCR SEEK_CUR
X#else
X#define UTMP "/etc/utmp"
X#endif
X
X#ifdef FIDDLE_UTMPX
X#define UTMPS utmpx
X#else
X#define UTMPS utmp
X#endif
X
X#ifndef SVR4
X#ifdef sun
X#define NEED_STRERROR
X#endif
X#endif
X
X#ifndef SVR4
Xextern long    lseek();
Xextern time_t  time();
Xextern char    *strerror();
Xextern int     errno;
Xextern void    exit();
Xextern void    perror();
X#endif
X
Xstatic char    *program;
X
Xstatic int     not_really = 0;
X
X
X#ifdef __STDC__
Xstatic void
Xzap(int utmp, struct UTMPS *ut, const char *tty)
X{
X#else
Xstatic void
Xzap(utmp, ut, tty)
Xstruct UTMPS *ut;
Xchar *tty;
X{
X#endif
X       (void) fprintf(stderr, "%s: %s: bogus, zapped\n", program, tty);
X       if(not_really)
X               return;
X       /*
X        * clear it
X        */
X#ifdef USG
X       ut->ut_type = DEAD_PROCESS;
X#ifdef FIDDLE_UTMPX
X       (void) gettimeofday(&ut->ut_tv, (struct timezone *)0);
X#else
X       ut->ut_time = time(0);
X#endif
X#else
X       bzero((char *)ut, sizeof(struct utmp));
X#endif
X       (void) lseek(utmp, (off_t) -(sizeof(struct UTMPS)), L_INCR);
X       (void) write(utmp, (char *)ut, sizeof(struct UTMPS));
X}
X
X#ifdef __STDC__
Xstatic void
XUsage(void)
X#else
Xstatic void
XUsage()
X#endif
X{
X       (void) fprintf(stderr, "Usage: %s [-n]\n", program);
X       exit(1);
X       /*NOTREACHED*/
X}
Xmain(argc, argv)
Xchar *argv[];
X{
X       register int utmp;
X       struct UTMPS ut;
X       int pgrp;
X
X       program = argv[0];
X       argv++;
X       argc--;
X
X       while(argc > 0 && argv[0][0] == '-') {
X               switch(argv[0][1]) {
X               case 'n':
X                       not_really = 1;
X                       break;
X               default:
X                       Usage();
X               }
X               argv++;
X               argc--;
X       }
X       if(argc)
X               Usage();
X
X       if((utmp = open(UTMP, not_really ? O_RDONLY : O_RDWR)) == -1) {
X               perror(UTMP);
X               exit(1);
X               /*NOTREACHED*/
X       }
X
X       /*
X        * ignore SIGHUP's that come from the system when we close a pty (below)
X        */
X       (void) signal(SIGHUP, SIG_IGN);
X#ifdef SVR4
X       pgrp = getpgid(0);
X#else
X       pgrp = getpgrp(0);
X#endif
X       if(pgrp == 0) {
X               pgrp = getpid(); /* pgrp to for the system to send SIGHUP's */
X#ifdef USG
X               (void) setpgrp();
X#else
X               (void) setpgrp(0, pgrp);
X#endif
X       }
X
X       while(read(utmp, (char *)&ut, sizeof(ut)) == sizeof(ut)) {
X               char tty[100], pty[100];
X
X               if(ut.ut_line[0] == 0 || ut.ut_name[0] == 0)
X                       continue;
X#ifdef USG
X               if(ut.ut_type != USER_PROCESS)
X                       continue;
X#endif
X               (void) strcpy(tty, "/dev/");
X               (void) strncat(tty, ut.ut_line, sizeof(ut.ut_line));
X               tty[sizeof("/dev/") + sizeof(ut.ut_line) - 1] = 0;
X
X               if((strncmp(tty, "/dev/tty", 8) == 0 &&
X                   (tty[8] == 'p' ||
X                    tty[8] == 'q' ||
X                    tty[8] == 'r' ||
X                    tty[8] == 's'))
X#ifdef USG
X                       || strncmp(tty, "/dev/pts", 8) == 0
X              
X#endif
X                    ) {
X
X                       /*
X                        * its a pty entry
X                        */
X                       int t;
X                       struct stat st;
X                       time_t now;
X
X
X#ifdef USG
X                       if(kill((pid_t)ut.ut_pid, 0) == -1 &&
X                           errno == ESRCH) {
X                               (void) fprintf(stderr,
X                                       "%s: %s: pid %d gone\n",
X                                       program, tty, ut.ut_pid);
X                               zap(utmp, &ut, tty);
X                               continue;
X                       }
X#endif
X
X                       (void) time(&now);
X
X                       if(stat(tty, &st) == -1) {
X                               perror(tty);
X                               continue;  /* Hmmm. Very strange */
X                       }
X
X                       if((now - st.st_atime) < 360) {
X                               (void) fprintf(stderr,
X                                       "%s: %s: still being accessed\n",
X                                       program, tty);
X                               continue; /* accessed within 6 minutes */
X                       }
X
X                       (void) fprintf(stderr,
X                               "%s: %s: idle for at least 6 mins\n",
X                               program, tty);
X#ifdef USG
X                       if(strncmp(tty, "/dev/pts", 8) == 0) {
X                               /*
X                                * stream's pty's give EACCES when you
X                                * open the slave and the master
X                                * isn't open.
X                                */
X                               if((t = open(tty, O_RDONLY|O_NDELAY)) == -1
X                                   && errno == EACCES)
X                                       zap(utmp, &ut, tty);
X                               else
X                                       (void) close(t);
X                               continue;
X                       }
X#endif
X                       (void) strcpy(pty, tty);
X                       pty[5] = 'p'; /* /dev/tty?? -> /dev/pty?? */
X
X                       if((t = open(pty, O_RDONLY|O_NDELAY)) != -1) {
X                               /*
X                                * we opened it, so its not otherwise
X                                * open; thus bogus
X                                */
X                               int r;
X
X                               /*
X                                * Open they tty too, and set the pgrp
X                                * to zero so that when the pty is closed
X                                * a SIGHUP sent by the system won't kill
X                                * some random process...
X                                */
X                               if((r = open(tty, O_RDWR|O_NDELAY)) == -1)
X                                       (void) fprintf(stderr,
X                                           "%s: %s: cannot open: %s\n",
X                                           program, tty, strerror(errno));
X                               else {
X#ifdef TIOCSPGRP
X                                       (void) ioctl(r, TIOCSPGRP,
X                                               (char *)&pgrp);
X#endif
X                                       (void) close(r);
X                               }
X                               (void) close(t);
X                               zap(utmp, &ut, tty);
X                       }
X               }
X       }
X       (void) close(utmp);
X       exit(0);
X       /*NOTREACHED*/
X}
X
X
X#ifdef NEED_STRERROR
Xstatic char *
Xstrerror(e)
X{
X       extern char *sys_errlist[];
X
X       return(sys_errlist[e]);
X}
X#endif
----cleanutmp.c----

 
 
 

SOLARIS 2.3: Looking for program to clean utmp

Post by Rob Kroeg » Tue, 22 Mar 1994 23:35:30


: I am looking for the programs/[perl]scripts that can clean utmp for Solaris 2.3.
: For some reasons, userid(s) is still there even the user has logout.
: I am planning to run this program periodically.

I noticed that on our Sol2.3 machines, utmp has only been wangled by system
crashes.  On the other hand, I have seen that wtmpx seems up to a day behind
some times.  This means that last output is frequently out of date.

The funny thing is that it catches up after a few login/logouts.  Is the
kernel buffering the wmptx entries?  Perhaps this problem is affecting
Mr. Rahardjo as well.

Rob Kroeger
CGL
University of Waterloo

 
 
 

SOLARIS 2.3: Looking for program to clean utmp

Post by John Caru » Wed, 23 Mar 1994 09:03:19




>>I am looking for the programs/[perl]scripts that can clean utmp for
>> Solaris 2.3.

>For SVR4.0 and Solaris, there are two programs, cleanutmp, and cleanutmpx,
>which must be run one after the other, immediately via cron.

Actually I've been testing the utmp cleaner someone else posted several
days ago (original author unknown), and although it only updates utmp
the entries in utmpx appear to be updated as well.  I'd suspect this
is a function of the ut system calls.  I rewrote the program to modify
utmpx rather than utmp and found that the reverse also applied--when I
ran the utmpx fixer, it would automagically propagate the changes back
to the utmp file.

Here's the (very compact, very useful) source again, in case anyone
missed it:

/*
 *  TITLE:      cleanutmp
 *  SYNOPSIS:   eliminate entries from /var/adm/utmp for dead processes
 */

#include <sys/types.h>
#include <utmp.h>
#include <errno.h>
#include <time.h>

extern int errno;

main(int argc, char **argv)
{
  struct utmp *current;
  char *ent_time;

  while (current = getutent()) {
    if (current->ut_type == USER_PROCESS
        && kill((pid_t) current->ut_pid, 0) == -1
        && errno == ESRCH) {
      ent_time = asctime(localtime(&current->ut_time));
      printf("%-8.8s %-4.4s %-12.12s %5d %24.24s",
             current->ut_user, current->ut_id,
             current->ut_line, current->ut_pid,
             ent_time);
      current->ut_type = DEAD_PROCESS;
      current->ut_exit.e_termination = ~0;
      current->ut_exit.e_exit = ~0;
      current->ut_time = time(0);
      pututline(current);
      printf(" marked DEAD\n");
    }
  }

Quote:}

---------------------------------------------------------------------


 University of Maryland University College      (301) 985-7447
---------------------------------------------------------------------
 
 
 

SOLARIS 2.3: Looking for program to clean utmp

Post by Ian Donalds » Wed, 23 Mar 1994 09:21:07




>: I am looking for the programs/[perl]scripts that can clean utmp for Solaris 2.3.
>: For some reasons, userid(s) is still there even the user has logout.
>: I am planning to run this program periodically.
>I noticed that on our Sol2.3 machines, utmp has only been wangled by system
>crashes.  On the other hand, I have seen that wtmpx seems up to a day behind
>some times.  This means that last output is frequently out of date.
>The funny thing is that it catches up after a few login/logouts.  Is the
>kernel buffering the wmptx entries?  Perhaps this problem is affecting
>Mr. Rahardjo as well.

No, the kernel doesn't touch utmp (other than perfoming I/O on it on behalf
of non-kernel processes).

The utmp managment library routines (see getutent(3C), getutxent(3C))
try to keep the two files in sync, based on the last mod time.

It probably doesn't make much sense on Solaris 2 as they already had
a BSD style utmp (with ut_host field), but the idea was that for SVR3 binary
applications running on SVR4 that if they updated utmp, then utmpx would
eventually reflect the change.

Since SunOS 4 had a BSD style struct utmp which looks nothing like
Solaris 2's SVR3 compatability style struct utmp, this concept probably
doesn't work like the original SVR4 concept did (or at all even, given
there was no ut_pid or ut_id in the BSD utmp).

Ian D

 
 
 

1. utmp woes under Solaris 2.3

Forgive me if this has already been talked about a million times.

It seems that under 2.3 (I don't know about 2.2) that the
/var/adm/utmp file has _completely_ erroneous information in it.

For instance:

smcdow   pts/1         7:59am       6839:12 3330:16  
debbiek  pts/1         9:40am            8      1  more ChangeLog

Wow!! Two people logged in to the same to the same tty!!!! Neat-O!!!

I called Sun about it, and they gave me the party line: something to
the effect of abnormally terminated shells will leave its skin in the
utmp file. And they weren't going to do anything about it.

What the hell? I mean really!

Any guidance/info/complaints/flames?

Thanks.

--

| Applied Research Laboratories          |          +1 512 835 3672 w          |
| The University of Texas at Austin      |                                     |
| 10000 Burnet Rd., Austin, Texas 78758  |                                     |

2. ppp connection on demand

3. utmp & wtmp problems in Solaris 2.3 - HELP!

4. ORACLE Forms 3.0 / AIX / aixterm

5. UTMP problem with Solaris 2.3 & tcsh.

6. BPI of a Maxell 4mm Helical DAT tape.....

7. utmp/wtmp problems in Solaris 2.3

8. Cirrus Logic CL-GD 6410 support for Linux -- anyone got a patch?

9. "Stop-A" instead of clean shutdown (was Re: solaris 2.3 on a sparc 1)

10. Solaris 2.3: init doesn't clean up zombies

11. HELP: Solaris 2.3 <---> Solaris 2.3 PPP link problems

12. HELP: Solaris 2.3 <---> Solaris 2.3 PPP link Problems

13. Looking for a mail purge program for 2.3