[net.sources] chttys program

rogers@dadla.UUCP (Roger Southwick) (11/27/84)

<HACKING MAKES ME FEEL GOO-OO-OOD!!>

A few days (a week or two) ago I posted a advertisment
for a nifty little program to change the modes of disabled
tty devices to be 0666.

And as promised (threatened maybe), if I got mode than 5
requests for it, I'd post it.  Well I got the requests, so
here it is!


Thanks to all who responded to my article-

		-Roger


--- cut here and place in it's own directory, then feed to Bourne shell ---

# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# READ_ME chttys.c chttys.8 ttymodes.5 ttymodes

echo x - READ_ME
cat > "READ_ME" << '//E*O*F READ_ME//'


The chttys program

By: Roger S. Southwick
    Logic Analyzers Computer Resource Group
    Tektronix, Inc.

DISCLAIMER:

This software is considered PUBLIC DOMAIN, and may be copied
and/or modified without consent of the author, or Tektronix, Inc.
The author (or Tektronix, Inc), assume no responsibility either
written or implied for the software.


Installation notes:

1a) Edit the file chttys.c, and set MODEFILE to be a location
on your system you'ld like the ttymodes file to be.  This file
is described in the ttymodes.5 man page, and if you change the
location of the ttymodes file, be sure and change the ttymodes.5
and the chttys.8 man page.  This is originally set to be /etc/ttymodes.

1b) Also, change LL to be the path of the "ls -l" for your
system.  This is used under the -l option of the chttys command.
See the chttys.8 man page for description of the option.

2) Compile chttys.c into object: cc -O -s -o chttys chttys.c
This does work on PDP11's (2.8 BSD) and Vaxen (4.1 BSD), so I
assume most all Unixes will work with this code.

3) Move chttys to live in someplace like /etc, as it is intended
for use by the super user (see GENERAL NOTES 1 & 2)

4) Copy the chttys.8 and ttymodes.5 into apropos spots.


GENERAL NOTES: 


1) The chttys program must be run by root (so it can do a chmod() on
the tty devices) although it does check this fact.  One therefore
could make it suid root, but this is not advised.

2) If your system is like ours, we have a shell script 
which does the apropos "kill -N 1" for this system (since
we have 3 PDP's with 2.8 (and use kill -2 1), and a Vax
with 4.1 (and use kill -1 1)).  The rdttys program can be added
to the shell script, and no more mode troubles (except the
MODEFILE editing) should happen.

3) The main reason for using the chttys program over simple
lines of "chmod 0666 /dev/tty??" in the above shell script, is
that the list of ttys is more or less dynamic, and therefore is
a pain to keep track of.  The ttys which you'll describe in the
ttymodes file are probably ones for uucp, printer ports, and so
on, which are turned off and not mode 0666 (i.e. more of the
permanent installation type critters).

4) I have included a sample ttymodes file in this directory for
your enjoyment, but of course our tty names are probably different
than yours.

5) I will be happy to consult (via E-mail) with anyone having
questions and/or problems (within reason).  If any bugs are
discovered, mail them to me as well.


	Good Luck...

	Roger Southwick


UUCP:			HOST!tektronix!dadla!rogers

			Where HOST is any one of:

			masscomp,decvax,allegra,uf-cgrl,mit-eddie,mit-ems,
			uoregon,psu-cs,orstcs,zehntel,ucbcad,ucbvax,purdue,
			uw-beaver,reed,ogcvax,ihnp4,tekred,minn-ua,cbosg

CSnet:			rogers%dadla@tektronix

ARPAnet:		rogers%dadla%tektronix@csnet-relay

BELLnet (phone):	(503)-629-1911

SNAILnet (U.S. Mail):	Roger Southwick
			Tektronix, Inc.
			P.O. Box 4600, D.S. 92-731
			Beaverton, Oregon 97075

//E*O*F READ_ME//

echo x - chttys.c
cat > "chttys.c" << '//E*O*F chttys.c//'
/*-------------------------------------------------------------

The chttys program

By: Roger S. Southwick
    Logic Analyzers Computer Resource Group
    Tektronix, Inc.

November 19, 1984

DISCLAIMER:

This software is considered PUBLIC DOMAIN, and may be copied
and/or modified without consent of the author, or Tektronix, Inc.
The author (or Tektronix, Inc), assume no responsibility either
written or implied for the software.

This program changes the permission modes of /dev/tty?? to
be 666 when it is turned off in the /etc/ttys file.

Usage:  chttys [-v] [-l] [-V]

Where:

  -v	turns on verbose mode, echoing ttys as it changes them.
  -l	does an ls -l of the ttys before and after mode change.
  -V 	turns on the very verbose mode (both -v and -l).

The program will also consult the MODEFILE (usually set to
be /etc/ttymodes), for any ttys described, and use the mode
in the file instead of the default 666 mode.

The format of the MODEFILE is:

/dev/tty?? mode

"mode" is an octal number representing the permission mode
bits ala chmod(1) and chmod(2).

Lines beginning with a ; (semicolon) or a newline are ignored
in the MODEFILE, and can be used for comments.

NOTES: 

1) For your system, set MODEFILE and LL to be paths
you wish. 

2) This program must be run by root, although it does
check this fact.  One therefore could make it suid, but
this is not advised.

3) If your system is like ours, we have a shell script 
which does the apropos "kill -N 1" for this system (since
we have 3 PDP's with 2.8 (and use kill -2 1), and a Vax
with 4.1 (use kill -1 1)).  The rdttys program can be added
to the shell script, and no more mode troubles (except the
MODEFILE editing) should happen.

---------------------------------------------------------------
 *
 * MODIFICATION HISTORY:
 *
 * $Log$
 *
-------------------------------------------------------------*/

#include <stdio.h>

#define MODEFILE	"/etc/ttymodes"		/* location of ttymodes */
#define LL		"/usr/ucb/ls -l"	/* location of ll cmd	*/

/*
 * ttymodes structure.  Read from MODEFILE and stored in this linked list
 */

struct ttymode {
   char *t_tname;		/* The tty name		*/
   int t_tmode;			/* The tty mode		*/
   struct ttymode *t_next;	/* Next tty structure	*/
};

/*
 * tty structure.  Disabled ttys in /etc/ttys.
 */

struct ttys {
   char *tty_name;		/* The tty name (minus /dev)	*/
   struct ttys *tty_next;	/* The next tty name		*/
};

main(argc, argv)

int argc;
char *argv[];
{
   int strcmp(), chmod();
   struct ttys *rdttys();
   struct ttymode *rdmodes();

   register struct ttys *tty_top, *tt;
   register struct ttymode *tm_top, *tm;
   register int mode, verbose, list;
   register char *cp;
   char buf[BUFSIZ];

   /*
    * Process the arguments.
    */

   for(list = 0, verbose = 0; --argc > 0 && (*++argv)[0] == '-'; ){
      for(cp = argv[0] + 1; *cp != '\0'; cp++){
         switch(*cp){
	    case 'v':
	       verbose = 1;
	       break;

	    case 'l':
	       list = 1;
	       break;

	    case 'V':
	       list = 1;
	       verbose = 1;
	       break;

            default:
	       usage();
         }
      }
   }

   if(argc != 0)
      usage();

   tty_top = rdttys();
   tm_top = rdmodes();

   /*
    * Set up command for performing ls -l (if list flag is set)
    */

   if(list == 1){
      for(strcpy(buf, LL), tt = tty_top; tt != NULL; tt = tt->tty_next){
         strcat(buf, " ");
         strcat(buf, tt->tty_name);
      }

      system(buf);
   }

   /*
    * For each tty in /etc/ttys which is turned off, compare
    * it to ones in MODEFILE.  If in MODEFILE, use mode from
    * the file.  Otherwise, use default 0666 mode.
    */

   for(tt = tty_top; tt != NULL; tt = tt->tty_next){
      for(mode = 0666, tm = tm_top; tm != NULL; tm = tm->t_next){
         if(strcmp(tt->tty_name, tm->t_tname) == 0){
	    mode = tm->t_tmode;
	    break;
	 }
      }

      if(verbose == 1)
         printf("chttys: chmod(%s, 0%o) %s",tt->tty_name,mode,(mode != 0666)? "(special)\n" : "\n");


      if(chmod(tt->tty_name, mode) == -1){
	 fprintf(stderr,"chttys: chmod(%s, 0%o) failed - ",tt->tty_name, mode);
	 perror("chttys");
      }
   }

   if(list == 1)
      system(buf);

   exit(0);
}

/*
 * Print usage, then die.
 */

usage()
{
   fprintf(stderr,"usage: chttys [-v] [-l] [-V]\n");
   exit(1);
}


/*
 * Read the /etc/ttys file into linked list, and return pointer
 * to the top of the linked list.
 */

struct ttys *
rdttys()
{
   FILE *fopen();
   int fscanf();
   struct ttys *ttylink();

   register FILE *fp;
   register struct ttys *top = NULL;
   register int fi;

   char buf[30], buf2[60];

   if((fp = fopen("/etc/ttys", "r")) == NULL){
      fprintf(stderr,"chttys: could not open /etc/ttys\n");
      exit(1);
   }

   while((fi = fscanf(fp, "%s", buf)) != EOF){
      if(fi != 1){
	 fprintf(stderr,"chttys: format error in /etc/ttys\n");
	 continue;
      }

      if(buf[0] != '0')		/* Ignore any enabled ttys	*/
	 continue;

      strcpy(buf2,"/dev/");
      strcat(buf2, &buf[2]);	/* Skip first 2 chars		*/

      top = ttylink(top, buf2);
   }

   fclose(fp);
   return(top);
}

/*
 * Read MODEFILE into a linked list, and return pointer to top.
 * The MODEFILE may contain ; as leading character comment lines
 * (or blank lines), and they are ignored.
 */

struct ttymode *
rdmodes()
{
   FILE *fopen();
   char *fgets();
   int sscanf(), access();
   struct ttymode *tlink();

   register FILE *fp;
   register struct ttymode *top = NULL;
   register int fi;

   char buf[BUFSIZ], tbuf[30];
   int mode;

   if(access(MODEFILE, 4) == -1){
      return(NULL);
   }

   if((fp = fopen(MODEFILE, "r")) == NULL){
      fprintf(stderr,"chttys: could not open %s\n",MODEFILE);
      exit(1);
   }

   while(fgets(buf, BUFSIZ, fp) != NULL){
      if(buf[0] == '\n' || buf[0] == ';')	/* Ignore comments	*/
	 continue;

      if(sscanf(buf, "%s %o", tbuf, &mode) != 2){
	 fprintf(stderr,"chttys: format error in %s\n",MODEFILE);
	 continue;
      }

      top = tlink(top, tbuf, mode);
   }

   fclose(fp);
   return(top);
}

/*
 * Build a linked list of ttymode structures.
 */

struct ttymode *
tlink(tm, name, mode)

register struct ttymode *tm;
register char *name;
register int mode;
{
   char *malloc(), *strsave();

   if(tm == NULL){
      tm = (struct ttymode *)malloc(sizeof(struct ttymode));
      tm->t_tname = strsave(name);
      tm->t_tmode = mode;
      tm->t_next = NULL;
   }
   else
      tm->t_next = tlink(tm->t_next, name, mode);

   return(tm);
}

/*
 * Build a linked list of ttys structures.
 */

struct ttys *
ttylink(tt, name)

register struct ttys *tt;
register char *name;
{
   char *malloc(), *strsave();

   if(tt == NULL){
      tt = (struct ttys *)malloc(sizeof(struct ttys));
      tt->tty_name = strsave(name);
      tt->tty_next = NULL;
   }
   else
      tt->tty_next = ttylink(tt->tty_next, name);

   return(tt);
}

/*
 * The strsave routine allocates some memory for the string
 * str, copies the string to that place and returns a pointer
 * to the place in memory.  If passed a NULL pointer, a NULL
 * pointer is returned.
 */

char *
strsave(str)

register char *str;

{
   int strlen();
   char *malloc();

   register char *cp;

   if(str == NULL)
      return(NULL);

   if((cp = (char *)malloc(strlen(str) + 1)) != NULL)
      strcpy(cp, str);

   return(cp);
}
//E*O*F chttys.c//

echo x - chttys.8
cat > "chttys.8" << '//E*O*F chttys.8//'
.TH CHTTYS 8
.UC 4
.SH NAME
chttys \- change modes of ttys
.SH SYNOPSIS
.B chttys [-vlV]
.SH DESCRIPTION
.PP
.I Chttys
changes the modes of the ttys which have been made non-loginable
in the /etc/ttys file to be 0666 (rw-rw-rw-).  The mode can be
made to be any value by placing an entry in the /etc/ttymodes file,
discussed below.
.PP
.I Chttys
will do it's work silently, unless one (or more) of the options
are given.  The options are:
.IP
.B \-v
verbose mode:  This basically will output a message showing which
ttys are changing and to what mode they will be.  The text
.B (special)
denotes the mode was described in the /etc/ttymodes file.
.IP 
.B \-l
list mode:  This makes the program provide an ls -l of the ttys
before and after the mode change happens.
.IP
.B \-V
very verbose mode: This makes the program do both the 
.B \-v
and the
.B \-l
option.
.PP
The 
.I chttys
program can also change the modes on the disabled ttys to be a mode
other than 0666.  This is done by reading the file
.B /etc/ttymodes
and using the listed devices and their corresponding modes.
.PP
The
.B /etc/ttymodes
file consists of two fields, one with the complete path of
the device, and the OCTAL mode for the device.
.PP
The
.B /etc/ttymodes
file is described and exampled in ttymodes(5).
.SH FILES
/etc/ttys
.br
/etc/ttymodes
.SH AUTHOR
Roger Southwick
.br
Logic Analyzers
Computer Resource Group
.br
Tektronix, Inc.
.SH BUGS
To be discovered.
.SH "SEE ALSO"
chmod(1), chmod(2), ttymodes(5)
//E*O*F chttys.8//

echo x - ttymodes.5
cat > "ttymodes.5" << '//E*O*F ttymodes.5//'
.TH TTYMODES 5
.UC 4
.SH NAME
ttymodes \- permission modes for tty devices
.SH DESCRIPTION
.PP
The
.I ttymodes
file is read by the
.B chttys
program and specifies the permission modes to which ttys are
changed.
.PP
The file consists of either comment lines or information lines.
Comment lines are defined as lines beginning with a semicolon
or a newline character.  Information lines have two fields
with the complete path of the tty, and the OCTAL mode the
tty should be.
.PP
It is important to note that only terminals which are
disabled (i.e non-loginable) need be in this file, as all 
other entries are ignored.
.PP
Here is an example
.I ttymodes
file:
.RS

.br
;
.br
; This file is read by the chttys program to set modes
.br
; for terminals to be other than the default 0666.
.br
;
.br
; Note that the format is 2 fields, one of the device
.br
; name (complete path), and the other an OCTAL number
.br
; which will become the device's mode.
.br
;
.br
; Lines starting with a semicolon or a newline are
.br
; ignored and can be used as comments.
.br
;
.br

.br
/dev/ttyv3 0600
.br
/dev/ttyu6 0622
.br
/dev/ttyu7 0622
.RE
.SH FILES
/etc/ttymodes
.SH AUTHOR
Roger Southwick
.br
Logic Analyzers
Computer Resource Group
.br
Tektronix, Inc.
.SH BUGS
To be discovered.
.SH "SEE ALSO"
chmod(1), chmod(2), chttys(8)
//E*O*F ttymodes.5//

echo x - ttymodes
cat > "ttymodes" << '//E*O*F ttymodes//'
;
; This file is read by the chttys program to set modes for
; terminals to be other than the default 0666.
;
; Note that the format is 2 fields, one of the device name
; (complete path), and the other an OCTAL number which will
; become the device's mode.
;
; Lines starting with a semicolon or a newline are ignored
; and can be used as comments.
;

/dev/ttyv3 0600
/dev/ttyu6 0622
/dev/ttyu7 0622
//E*O*F ttymodes//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
     93    484   2973 READ_ME
    353   1047   7344 chttys.c
     65    263   1481 chttys.8
     72    239   1314 ttymodes.5
     15     79    400 ttymodes
    598   2112  13512 total
!!!
wc  READ_ME chttys.c chttys.8 ttymodes.5 ttymodes | sed 's=[^ ]*/==' | diff -b $temp -
exit 0