home *** CD-ROM | disk | FTP | other *** search
- /* newmgr: Loop forever, printing a status display and checking the
- Suspend and Resume Keys. Meant to be used on the top line of a Unix-PC
- (7300/3B1) screen that has had the Phone Manager, Status Manager and
- Window Manager disabled. What it shows:
-
- - Phone line states (Idle, Busy)
- - Boot date and time
- - Current run level
- - Current date and time
- - Number of users
-
- Also, when Suspend is hit, it makes the next window current; Resume
- makes the last window current.
-
- This is started by startmgr (which should be included in any
- distribution) so that the fork/exec/open code doesn't have to be
- carried around with this program.
-
- This software is Copyright (c) 1987 by Scott Hazen Mueller.
-
- Permission is hereby granted to copy, reproduce, redistribute or
- otherwise use this software as long as: there is no monetary
- profit gained specifically from the use or reproduction or this
- software, it is not sold, rented, traded or otherwise marketed, and
- this copyright notice is included prominently in any copy
- made.
-
- The author make no claims as to the fitness or correctness of
- this software for any use whatsoever, and it is provided as is.
- Any use of this software is at the user's own risk.
-
- (Copyright notice courtesy of News 2.11 :-)
-
- Additionally: you break it, you bought it. I've listed the problems
- that I know of in comments in the code; if you come up with fixes, I'd
- like to see them, but I'm not planning on supporting anything. It's
- "good enough"; that's all that I'm looking for. */
-
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/phone.h>
- #include <sys/window.h>
- #include <sys/signal.h>
- #include <fcntl.h>
- #include <time.h>
- #include <utmp.h>
-
- #define PHONE1 "ph0"
- #define PHONE2 "ph1"
- #define IDLE 0
- #define BARFORM "%s1 %s2 | Up Since %s | %s | %s | %d Users | w%d \r"
- #define phstat( st ) ( st ? "Busy" : "Idle" )
- #define MAXPATHLEN 255
- #define LOCKDIR "/usr/spool/uucp/"
- #define LOCKPREFIX "LCK.."
- #define TRUE (1)
- #define FALSE (0)
- #define TIMEFORM "%.2d/%.2d %.2d:%.2d"
- #define TICK 15
- #define NOWHERE 0
- #define FORWARD 1
- #define BACKWARD 2
- #define MINWIN 1
- #define MAXWIN 12
-
- main()
- {
- int ph1st, ph2st, nusers;
- char curtime[26], boottime[26], rl[12], line[80], *fmttime();
- struct utmp *ut, *getutent();
- long temp;
-
- /* Open up the utmp file and find the boot time; save for display. */
-
- while ( ( ut = getutent() ) != NULL )
- if ( (int) ut->ut_type == BOOT_TIME ) {
- strcpy( boottime, fmttime( localtime( &( ut->ut_time ) ) ) );
- break;
- }
- endutent();
-
- for (;;) {
-
- /* Scan the utmp file, noting the run level and totting up users.
- Skip the loop for dead processes - we don't want to confuse the
- phone-check code... */
-
- nusers = 0;
- ph1st = IDLE;
- ph2st = IDLE;
- while ( ( ut = getutent() ) != NULL ) {
- switch ( (int) ut->ut_type ) {
- case USER_PROCESS : nusers++; break;
- case RUN_LVL : strcpy( rl, ut->ut_line ); break;
- case DEAD_PROCESS : continue;
- default : break;
- }
- /* Peek at the line field and see if a phone line is mentioned. The answer
- is either yes (1 or many, don't care exactly) or no, so I can get away
- with the 'or'. */
-
- ph1st = ph1st | !strcmp( PHONE1, ut->ut_line );
- ph2st = ph2st | !strcmp( PHONE2, ut->ut_line );
- }
- endutent();
-
- /* The phone check stuff *still* hasn't caught everything, e.g., an outgoing
- uucico started by cron, so we'll now peek and see if we can find a LCK
- file. It's gross and it's nasty, and if anyone can do me better without
- hanging up my voice calls, I'd be happy to replace this stuff... */
-
- ph1st = ph1st | locked( PHONE1 );
- ph2st = ph2st | locked( PHONE2 );
-
- /* Figure out the current time. Temp is needed 'cause localtime wants
- an address. */
-
- temp = time( (long *) 0 );
- strcpy( curtime, fmttime( localtime( &temp ) ) );
-
- /* Format and print. Flush stdout to make it really get printed. */
-
- sprintf( line, BARFORM, phstat( ph1st ), phstat( ph2st ),
- boottime, rl, curtime, nusers, curwinno() );
- printf( "%s", line );
- fflush( stdout );
-
- /* Take care of the window management stuff; also do some sleeping down
- there. */
-
- wcheckz();
- }
- }
-
- /* See if a lock file exists. */
-
- locked( device )
- char *device;
- {
- char temp[MAXPATHLEN];
- int fd;
-
- /* Make up the full path name. */
-
- strcpy( temp, LOCKDIR );
- strcat( temp, LOCKPREFIX );
- strcat( temp, device );
-
- /* Attempt to open the lock file. Assume that if the open fails the lock
- file does not exist. */
-
- fd = open( temp, O_RDONLY );
- if ( fd == -1 )
- return( FALSE );
- close( fd );
- return( TRUE );
- }
-
- /* Format a time structure into a string the way *I* want it. */
-
- char *fmttime( tm )
- struct tm *tm;
- {
- char abuf[26];
-
- sprintf( abuf, TIMEFORM, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min );
- return( abuf );
- }
-
- curwinno()
-
- /* Figure out the current window; we need a starting point, after all.
- Known bug: this sometimes returns the wrong value if it gets into a
- race condition with a terminating/restarting (eg, getty) job. It also
- doesn't check to see if the ioctl fails. */
-
- {
- int foowin, dummy, temp;
-
- foowin = open( "/dev/window", O_RDONLY );
- temp = ioctl( foowin, WIOCGCURR, dummy );
- close( foowin );
- return( temp );
- }
-
- wcheckz()
-
- /* This is where the code to check for change-window keys lives. Also,
- sleep for the main program here. It should return about every TICK
- seconds. */
-
- {
- int tock, newwin, dir;
-
- tock = 0;
-
- do {
- /* Check for a command key. */
-
- if ( ( dir = checkey() ) != NOWHERE ) {
-
- /* Determine which window is next and select it. */
-
- newwin = nexwin( curwinno(), dir );
- ioctl( newwin, WIOCSELECT );
- close( newwin );
- tock = TICK; /* Kludge to force return and redisplay. */
- }
- }
-
- /* Return after TICK tocks. */
-
- while ( tock++ < TICK );
- }
-
- /* Stub routine to "handle" the alarm signal. Doesn't do a lot. */
-
- justgoon()
- {
- return;
- }
-
- checkey()
-
- /* Check and see if one of our keys has been poked. The only keys this window
- is supposed to respond to all generate three character escape sequences.
- The print key gets ignored; I suppose it could be aliased to something
- useful, like system reboot... Set and catch an alarm signal to keep
- from getting hung in the fread(); this probably could be done more
- neatly some other way, but... */
-
- {
- int direction, i;
- FILE *fw;
- char key[3];
-
- /* Set the alarm signal. */
-
- signal( SIGALRM, justgoon );
- alarm( 1 );
- if ( fread( key, 1, 3, stdin ) == 3 ) {
-
- /* Reset the alarm signal to be ignored. */
-
- signal( SIGALRM, SIG_IGN );
- switch ( key[2] ) {
- case 'p' :
- case 'P' : direction = FORWARD; break;
- case 'q' :
- case 'Q' : direction = BACKWARD; break;
- default : direction = NOWHERE; break;
- }
- }
- else
- direction = NOWHERE;
-
- /* Reset the alarm signal to be ignored. */
-
- signal( SIGALRM, SIG_IGN );
- return( direction );
- }
-
- nexwin( winno, dir )
- int winno, dir;
-
- /* Decide what should be the next window. This relies on the fact that
- when you open a window device directly the open call will fail if it has
- not already been opened by someone else; this is how we find the open
- windows. Invisible windows should have their user-text set to "Invisible"
- if they wish to be ignored. */
-
- {
- int wd;
- char windex[12];
- struct utdata wintext;
-
- /* Trivial loop; at worst, we'll wind up back where we started. I suppose
- it's possible to have a system with no windows except those marked as
- "Invisible"; it doesn't seem to useful, though. */
-
- while ( 1 ) {
-
- /* Forward/backward sort-of modulo arithmetic. Real modulo arithmetic
- starts at zero. */
-
- winno += ( dir == FORWARD ? 1 : -1 );
- if ( winno > MAXWIN )
- winno = MINWIN;
- else if ( winno < MINWIN )
- winno = MAXWIN;
-
- /* Generate a window name and test for existence. */
- sprintf( windex, "/dev/w%d", winno );
- if ( ( wd = open( windex, O_RDONLY ) ) != -1 ) {
-
- /* It exists, now look at its user text info. This is where "Invisible"
- gets skipped. */
-
- wintext.ut_num = WTXTUSER;
- ioctl( wd, WIOCGETTEXT, &wintext );
- if ( strcmp( wintext.ut_text, "Invisible" ) )
- return( wd );
- else
- close( wd );
- }
- }
- }
-
-