[unix-pc.sources] Login Initialization program: logininit

lenny@icus.islp.ny.us (Lenny Tropiano) (01/23/89)

See the enclosed README files for more of a description...

-- cut here -- -- cut here -- -- cut here -- -- cut here -- -- cut here -- 
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  Makefile README1.0 README2.0 chtime.c fsinfo.sample
#   logininit.c
# Wrapped by lenny@icus on Mon Jan 23 00:00:07 1989
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(681 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile to compile logininit.c  (Login Information)
X# By Lenny Tropiano
X# (c)1988,1989 ICUS Software Systems UUCP: ...icus!lenny (lenny@icus.islp.ny.us)
X# All rights reserved
X#
XCFLAGS=-v -O -DMAXPERCENT=10 -DMAXINODES=500
XLDFLAGS=-s
XLIBS=/lib/crt0s.o /lib/shlib.ifile
XDEST=/usr/lbin/
X#
Xlogininit:  logininit.o chtime.o
X	@echo "Loading ..."
X	$(LD) $(LDFLAGS) -o logininit logininit.o chtime.o $(LIBS) 
X#
Xlogininit.o:
X	$(CC) $(CFLAGS) -c logininit.c
X#
X# You need to be super-user to do this.
X#
X$(DEST):
X	mkdir $(DEST)
X	chmod 755 $(DEST)
X#
Xinstall: logininit $(DEST)
X	cp logininit $(DEST)
X	chown root $(DEST)/logininit
X	chgrp bin  $(DEST)/logininit
X	chmod 4755 $(DEST)/logininit
END_OF_Makefile
if test 681 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README1.0 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README1.0\"
else
echo shar: Extracting \"README1.0\" \(1989 characters\)
sed "s/^X//" >README1.0 <<'END_OF_README1.0'
X
XThis is a little ditty I whipped up one day... Basically it tells you all
Xkinds of neat stuff when you login.  It can be called from inside 
X/etc/profile and will print this kind of information...
X---
XIt's Tuesday, May 31, 1988 at 8:00pm ... 
XNode: icus, up for 22 hours, 38 minutes, and 27 seconds.
X21% available disk storage in the root filesystem. (26968 blocks, 8692 i-nodes)
X1.29MB of main memory currently available. (48%)
X
XNo mail.
X---
XIt's Tuesday, May 31, 1988 at 11:02pm ... 
XNode: icus, up for 1 day, 2 hours, 36 minutes, and 1 second.
X21% available disk storage in the root filesystem. (24968 blocks, 8777 i-nodes)
X1.45MB of main memory currently available. (54%)
X
X       **************************************************************
X       * This is my message of the day.  It can say whatever I like *
X       **************************************************************
X
XYou have mail! (13 mail messages in your mailbox)
X
X---
XIt will tell you when you have mail (and how many mail messages you have). It
Xprints the /etc/motd out so the call to "cat /etc/motd" can be removed from
X/etc/profile.
X
XAnother nice feature is that it monitors the space left on the hard disk
Xwhen you login.  It checks the percentage (%) left to MAXPERCENT (compile
Xtime option [defaults to 10%]) and the inodes left with MAXINODES [defaults
Xto 500].
X
XSnipped from /etc/profile
X
X...
X# Print login initialization information
X/usr/lbin/logininit
X
X#The following line (if uncommented) will set TERM and TERMCAP (see ttytype)
X#eval `tset -s -Q`
X#For now, just set TERM to s4
XNAME=`tty`
Xif [ \( "`expr $NAME : '/dev/w' `"      != "0" -o \
X	"`expr $NAME : '/dev/sys' `"    != "0" \) ]
Xthen
X...
X
Xlogininit is called before the question to ask what terminal you are
Xrunning on...  It can be put almost anywhere... Even in your /etc/localprofile
Xor wherever.   Remember to take out redundant processing from /etc/profile
Xlike the "if..fi" statement to check the mailbox status, and the 
X"cat /etc/motd"
X
END_OF_README1.0
if test 1989 -ne `wc -c <README1.0`; then
    echo shar: \"README1.0\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f README2.0 -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"README2.0\"
else
echo shar: Extracting \"README2.0\" \(2877 characters\)
sed "s/^X//" >README2.0 <<'END_OF_README2.0'
X
XIn version 2.0 of logininit, I modified it to handle multiple filesystems
Xthat are mounted on the hard disk.   This is done by looking up in /etc/mnttab
Xfor the currently mounted partitions and displaying the information.  Also
Xyou can describe the partition (up to 25 characters by putting it in a file
Xcalled /etc/fsinfo [which can be changed]).
X
X/etc/fsinfo:
Xfp002	/		HD1 : System Partition
Xfp003	/mnta		HD1 : Partition 2
Xfp003	/mntb		HD1 : Partition 2
Xfp011	/tmp		HD2 : Temporary Partition
Xfp011	/mnta		HD2 : Partition 1
Xfp011	/mntb		HD2 : Partition 1
Xfp012	/usr/spool	HD2 : Spool Partition
Xfp012	/mnta		HD2 : Partition 2
Xfp012	/mntb		HD2 : Partition 2
Xfp021	/mnt		FD  : Floppy Partition
Xfp021	/floppy		FD  : Floppy Partition
X
XI have two hard disks installed, so that is why fp01[12] is being accessed.
XThis is what ultimately pushed me to modify my older logininit.c.
X
XI also changed the output slightly, it looks nicer now. 
X
XNOTES:  The program looks at /etc/mnttab, and reads it backwards, much like
Xwhat "df(1)" does.  To get the partitions in the correct order, you basically
Xhave to set up the /etc/mnttab in reverse order.
X
X# devnm /usr/spool /tmp / | setmnt 
X# df 
X/         (/dev/fp002):    44596 blocks   11558 i-nodes
X/tmp      (/dev/fp011):     9788 blocks    1481 i-nodes
X/usr/spool(/dev/fp012):    25786 blocks   11672 i-nodes
X
X# devnm / /tmp /usr/spool | setmnt 
X# df 
X/usr/spool(/dev/fp012):    25786 blocks   11672 i-nodes
X/tmp      (/dev/fp011):     9788 blocks    1481 i-nodes
X/         (/dev/fp002):    44596 blocks   11558 i-nodes
X
XNew output format:
X------------------
XIt's Sunday, January 22, 1989 at 11:48pm ... 
XNode: icus, up for 3 hours, 41 minutes, and 4 seconds.
X/          HD1 : System Partition   : 21.8MB,  44618 blocks, 11562 i-nodes, 37%
X/tmp       HD2 : Temporary Partition:  4.8MB,   9794 blocks,  1482 i-nodes, 98%
X/usr/spool HD2 : News Partition     : 12.6MB,  25786 blocks, 11672 i-nodes, 36%
X/floppy    FD  : Floppy Partition   :  0.0MB,     64 blocks,     7 i-nodes,  9%
X           WARNING: Filesystem disk space is low.
X           WARNING: Filesystem i-nodes are low.
X           Total Storage Available  : 39.2MB,  80262 blocks
X                            out of  : 99.4MB, 203514 blocks, 39% free
X1.71MB of main memory currently available. (54%)
X
X        *****************************************************************
X        * Display the /etc/motd (Message-of-the-day) here, if it exists *
X        *****************************************************************
X
XYou have mail! (32 mail messages in your mailbox)
X
X----
XLenny Tropiano             ICUS Software Systems         [w] +1 (516) 582-5525
Xlenny@icus.islp.ny.us      Telex; 154232428 ICUS         [h] +1 (516) 968-8576
X{talcott,decuac,boulder,hombre,pacbell,sbcs}!icus!lenny  attmail!icus!lenny
X        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752
END_OF_README2.0
if test 2877 -ne `wc -c <README2.0`; then
    echo shar: \"README2.0\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f chtime.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"chtime.c\"
else
echo shar: Extracting \"chtime.c\" \(1648 characters\)
sed "s/^X//" >chtime.c <<'END_OF_chtime.c'
X/*
X * ch_time - format elapsed time into a character string.
X *
X * Mikel Manitius - 85-01-08 - (mikel@codas.att.com.uucp)
X * Lenny Tropiano - 88-04-14 - (lenny@icus.UUCP) - modified slightly
X *
X */
X
X#define			NULL		(0)
X#define			SECOND		1L
X#define			MINUTE		60L
X#define			HOUR		(60L * 60L)
X#define			DAY		(24L * 60L * 60L)
X#define			WEEK		(7L  * 24L * 60L * 60L)
X#define			BUFSIZE		1024
X
Xchar	*malloc();
X
Xchar	*day[] =
X{
X	"Sunday", "Monday", "Tuesday",
X	"Wednesday", "Thursday", "Friday",
X	"Saturday", 0
X};
X
Xchar	*mon[] =
X{
X	"January", "February", "March", "April", "May",
X	"June", "July", "August", "September", "October",
X	"November", "December", 0
X};
X
X
Xchar *ch_time(sec)
Xint	sec;
X{
X	unsigned long	hrs = 0L;
X	unsigned long	days = 0L;
X	unsigned long	mins = 0L;
X	unsigned long	weeks = 0L;
X	char	*buff;
X
X	buff = malloc(BUFSIZE);
X	if(buff == NULL)
X		return(NULL);
X	weeks = sec / WEEK;
X	sec -= WEEK * weeks;
X	days = sec / DAY;
X	sec -= DAY * days;
X	hrs = sec / HOUR;
X	sec -= HOUR * hrs;
X	mins = sec / MINUTE;
X	sec -= MINUTE * mins;
X
X	if(weeks)
X		sprintf(buff, "%d week%s, ", weeks, (weeks == 1) ? "" : "s");
X	if(days)
X		sprintf(buff, "%s%d day%s, ", (weeks) ? buff : "",
X			days, (days == 1L) ? "" : "s");
X	if(hrs || days || weeks)
X		sprintf(buff, "%s%d hour%s, ", (days || weeks) ? buff : "",
X			hrs, (hrs == 1L) ? "" : "s");
X	if(mins || hrs || days || weeks)
X		sprintf(buff, "%s%d minute%s, ",
X			(hrs || days || weeks) ? buff : "",
X			mins, (mins == 1L) ? "" : "s");
X	sprintf(buff, "%s%s%d second%s.",
X			(mins || hrs || days || weeks) ? buff : "",
X			(mins || hrs || days || weeks) ? "and " : "",
X			sec, (sec == 1L) ? "" : "s");
X	return(buff);
X}
END_OF_chtime.c
if test 1648 -ne `wc -c <chtime.c`; then
    echo shar: \"chtime.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f fsinfo.sample -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"fsinfo.sample\"
else
echo shar: Extracting \"fsinfo.sample\" \(368 characters\)
sed "s/^X//" >fsinfo.sample <<'END_OF_fsinfo.sample'
Xfp002	/		HD1 : System Partition
Xfp003	/mnta		HD1 : Partition 2
Xfp003	/mntb		HD1 : Partition 2
Xfp011	/tmp		HD2 : Temporary Partition
Xfp011	/mnta		HD2 : Partition 1
Xfp011	/mntb		HD2 : Partition 1
Xfp012	/usr/spool	HD2 : Spool Partition
Xfp012	/mnta		HD2 : Partition 2
Xfp012	/mntb		HD2 : Partition 2
Xfp021	/mnt		FD  : Floppy Partition
Xfp021	/floppy		FD  : Floppy Partition
END_OF_fsinfo.sample
if test 368 -ne `wc -c <fsinfo.sample`; then
    echo shar: \"fsinfo.sample\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f logininit.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"logininit.c\"
else
echo shar: Extracting \"logininit.c\" \(8666 characters\)
sed "s/^X//" >logininit.c <<'END_OF_logininit.c'
X/************************************************************************\
X**                                                                      **
X** Program name: logininit.c (Login Initialization)                     **
X** Programmer:   Lenny Tropiano            UUCP: ...icus!lenny          **
X** Organization: ICUS Software Systems     (c)1989 All rights reserved  **
X** Date:         April 3, 1988                                          **
X** Revision 2.0: January 19, 1989  - temporary for more partitions      **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X** Program use:  Program is run as information apon login called from   **
X**               the /etc/profile. This program the filesystem          **
X**               information, available main memory and mail messages.  **
X**                                                                      **
X**   This programs must be setuid root (ie. 4755) and can be placed     **
X**   in any directory you choose.                                       **
X**                                                                      **
X**************************************************************************
X**                                                                      **
X**   Credits:  Thanks to Gil Kloepfer, Jr. (gil@limbic) for his insight **
X**   and suggestions about adding the capability of /etc/fsinfo         **
X**                                                                      **
X**************************************************************************
X** Permission granted to redistribute without profit in the public      **
X** domain only.  This header must remain in-tact as is.  This program   **
X** carries no warranties, express or implied, and all consequences      **
X** resulting from the use of this program are the sole responsibility   **
X** of the user.                                                         **
X\************************************************************************/
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <errno.h>
X#include <signal.h>
X#include <sys/types.h>
X#include <sys/filsys.h>
X#include <mnttab.h>
X#include <sys/utsname.h>
X#include <utmp.h>
X#include <time.h>
X#include <nlist.h>
X
X#ifndef ctob			
X#include <sys/sysmacros.h>
X#endif
X
X#define UNIX	"/unix"
X#define KMEM	"/dev/kmem"
X#define FSINFO	"/etc/fsinfo"
X#define MNTTAB	"/etc/mnttab"
X
Xstruct nlist unixsym[] = {
X#define X_MAXMEM	0
X	{ "maxmem" },
X#define X_FREEMEM	1
X	{ "freemem" },
X	{ NULL }
X};
X
X#define MEGABYTE 1048576.0
X
X#ifndef MAXPERCENT
X# define MAXPERCENT	10
X#endif
X
X#ifndef MAXINODES
X# define MAXINODES	500
X#endif
X
Xchar	*progname;			/* program name			*/
Xchar	mailfile[30];			/* mailbox file name            */
Xstruct  filsys fs;			/* Filesystem superblock struct */
Xstruct	tm	*today, *localtime();
X
X/************************************************************************/
X
Xmain(argc,argv)
Xint	argc;
Xchar	*argv[];
X{
X	char	*getenv();
X
X    	progname = *argv;
X	sprintf(mailfile,"%s",getenv("MAIL"));
X
X	printf("\n");
X
X	showtime();		/* what time is it?    */
X	uptime();		/* get system uptime   */
X	filestatus();		/* get filesystem info */
X	memory();		/* get current memory  */
X	show_motd();		/* print the /etc/motd */
X	mailcheck();		/* get mailbox status  */
X
X	printf("\n");
X	exit(0);
X}
X
Xfilestatus()
X{
X	int	mntfd, fsfd, 
X		nmount, percleft;
X	float	megs, totmegs, maxmegs;
X	long	totblocks, maxblocks;
X	struct	mnttab	mtable;
X	char	rawdevice[12];
X
X	/* initialize */
X	nmount = totblocks = maxblocks = 0;
X	totmegs = maxmegs = 0.0;
X
X	if ((mntfd = open(MNTTAB, O_RDONLY)) == -1) {
X		fprintf(stderr,"%s: cannot open %s for read\n",
X			progname, MNTTAB);
X		exit(1);
X	}
X
X	/* move to EOF */
X	if (lseek(mntfd, sizeof(struct mnttab) * -1, 2) == -1) {
X		fprintf(stderr,"%s: cannot lseek to end of file: %s\n",
X			progname, MNTTAB);
X		exit(1);
X	}
X
X	do  {
X
X	    read(mntfd, &mtable, sizeof(struct mnttab));
X
X	    sprintf(rawdevice,"/dev/r%s", mtable.mt_dev);
X	    if ((fsfd = open(rawdevice, O_RDONLY)) != -1) {
X	 	if (lseek(fsfd, 512, 0) == -1) {
X		    fprintf(stderr,"%s: cannot lseek to superblock\n", 
X			progname);
X		    exit(1);
X	        }
X
X	        if (read(fsfd, &fs, sizeof(struct filsys)) == -1) {
X		    fprintf(stderr,"%s: cannot read the superblock\n", 
X			progname);
X		    exit(1);
X	        }
X
X	    	close(fsfd);
X
X	    	percleft = (int)((((float)fs.s_tfree / (float)fs.s_fsize) 
X			+ 0.005) * 100.0);
X	    	megs = (fs.s_tfree * 1024) / MEGABYTE;
X	    	totmegs += megs;
X	    	totblocks += (fs.s_tfree * 2);
X	    	maxblocks += (fs.s_fsize * 2);
X
X	    	nmount++;
X
X	    	describe(mtable.mt_dev, mtable.mt_filsys);
X	    	printf(":%5.1fMB, %6d blocks, %5d i-nodes, %2d%%\n",
X			megs, fs.s_tfree * 2, fs.s_tinode, percleft);
X
X	    	if (percleft < MAXPERCENT)
X			printf("           WARNING: Filesystem disk space is low.\007\n");
X
X	    	if (fs.s_tinode < MAXINODES) 
X			printf("           WARNING: Filesystem i-nodes are low.\007\n");
X	    } /* cannot open device */
X
X	} while (lseek(mntfd, sizeof(struct mnttab) * -2, 1) != -1);
X
X	close(mntfd);
X
X	if (nmount > 1) {	/* more than on filesystem mounted */
X	    maxmegs = (maxblocks * 512) / MEGABYTE;
X	    percleft = (int)((((float)totblocks / maxblocks) + 0.005) 
X			* 100.0);
X	    printf("           Total Storage Available  :%5.1fMB, %6d blocks\n",
X		totmegs, totblocks);
X	    printf("                            out of  :%5.1fMB, %6d blocks, %2d%% free\n",
X		maxmegs, maxblocks, percleft);
X	}
X
X}
X
Xdescribe(device, filesys)
Xchar *device, *filesys;
X{
X	FILE	*infofp;
X	int	devlen, fslen;
X	char	devbuf[12], fsbuf[12], infobuf[26];
X
X	devlen = strlen(device);
X	fslen  = strlen(filesys);
X
X	if ((infofp = fopen(FSINFO, "r")) != NULL) {
X	    while (fscanf(infofp, "%s %s %[\ -~]\n", 
X		devbuf, fsbuf, infobuf) > 0) {
X		if (strncmp(devbuf, device, devlen) == 0 &&
X		    strncmp(fsbuf, filesys, fslen) == 0) {
X			fclose(infofp);
X			printf("%-10.10s %-25.25s", filesys, infobuf);
X			return;
X		}
X	    }
X	    fclose(infofp);
X	}
X	printf("%-10.10s %-25.25s", filesys, " "); /* just blank info */
X}
X
Xmailcheck()
X{
X	FILE	*fp;
X	char	buffer[BUFSIZ], *strrchr();
X	int	msgs = 0, forward = 0, line = 0;
X
X	if (access(mailfile,4) == 0) {
X		msgs = 0;
X		if ((fp = fopen(mailfile,"r")) != NULL) {
X			while (fgets(buffer, BUFSIZ, fp) != NULL) {
X				line++;
X				if (line == 1 &&
X				    strncmp(buffer,"Forward",7) == 0) {
X					forward = 1;
X					break;
X				}
X				if (strncmp(buffer,"From ",5) == 0)
X					msgs++;
X			}
X		}
X		fclose(fp);
X	} else  msgs = 0;
X
X	if (forward)
X		printf("Your mail is being forwarded to%s\n",
X			strrchr(buffer,' '));
X	else if (msgs != 0)
X		printf("You have mail! (%d mail message%s in your mailbox)\007\n",
X			msgs, (msgs == 1) ? "" : "s");
X	else
X		printf("No mail.\n");
X}
X
X
Xmemory()
X{
X	int	kmem;
X	int	maxmem, freemem;
X	float	megs, max, free, perc;
X
X	if (nlist(UNIX, unixsym) < 0) {
X		fprintf(stderr, "%s: no namelist.\n", UNIX);
X		exit(1);
X	}
X
X	if ((kmem = open(KMEM, 0)) < 0) {
X		perror(KMEM);
X		exit(1);
X	}
X
X	lseek(kmem, (long) unixsym[X_MAXMEM].n_value, 0);
X	read(kmem, (char *) &maxmem, sizeof(int));
X	lseek(kmem, (long) unixsym[X_FREEMEM].n_value, 0);
X	read(kmem, (char *) &freemem, sizeof(int));
X
X	close(kmem);
X
X	free = ctob(freemem);
X	max  = ctob(maxmem);
X	perc = free / max;
X	perc *= 100.0;
X
X	printf("%4.2fMB of main memory currently available. (%-2.0f%%)\n",
X		(ctob(freemem) / MEGABYTE), perc);
X		
X}
X
Xuptime()
X{
X	int	now, boottime;
X	char	*up, *ch_time();
X	struct	utmp	*utent, *getutent();
X	struct	utsname	utsname;
X
X	time(&now);
X	today = localtime(&now);
X
X	setutent();
X	while ((utent = getutent()) != (struct utmp *)NULL) {
X		if (utent->ut_type == BOOT_TIME) {
X			boottime = utent->ut_time;
X			break;
X		}
X	}
X	endutent();
X
X	up = ch_time(now - boottime);
X	uname(&utsname);
X	printf("Node: %s, up for %s\n", utsname.nodename, up);
X
X}
X
Xshowtime()
X{
X	int	now, ampm;
X	extern	char	*day[], *mon[];
X
X	time(&now);
X	today = localtime(&now);
X
X	if (today->tm_hour == 0) {
X		ampm = 0;
X		today->tm_hour += 12;
X	} else if (today->tm_hour > 12) {
X		ampm = 1;
X		today->tm_hour -= 12;
X	} else  if (today->tm_hour == 12)
X		ampm = 1;
X	else	ampm = 0;
X
X	printf("It's %s, %s %d, %d at %2d:%.2d%s ... \n",
X		day[today->tm_wday], mon[today->tm_mon], today->tm_mday,
X		today->tm_year + 1900, today->tm_hour, today->tm_min,
X		(ampm == 0) ? "am" : "pm");
X
X}
X
Xshow_motd()
X{
X	FILE	*fp;
X	char	buffer[BUFSIZ];
X
X	printf("\n");
X	if ((fp = fopen("/etc/motd","r")) != NULL) {
X		while (fgets(buffer, BUFSIZ, fp) != NULL) 
X			printf("%s", buffer);
X	
X		fclose(fp);
X	}
X	printf("\n");
X}
END_OF_logininit.c
if test 8666 -ne `wc -c <logininit.c`; then
    echo shar: \"logininit.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0
-- 
Lenny Tropiano             ICUS Software Systems         [w] +1 (516) 582-5525
lenny@icus.islp.ny.us      Telex; 154232428 ICUS         [h] +1 (516) 968-8576
{talcott,decuac,boulder,hombre,pacbell,sbcs}!icus!lenny  attmail!icus!lenny
        ICUS Software Systems -- PO Box 1; Islip Terrace, NY  11752