[comp.unix.xenix] ungetty interface

sandy@conexch.UUCP (Sandford Zelkovitz) (06/28/89)

Some time ago, I posted my method of interfacing a "home grown" getty to
SCO's ungetty. Since then, I have received many requests for a repost.
I have also extracted, from my getty, the ungetty interface which I am
including at the tail end of this message.
 
The interface is really pretty simple. Basically, the user code must trap
SIGUSR1 and, if you wish, SIGUSR2. I do not trap SIGUSR2 but go into a
"pause" state since the next signal that getty will receive, hopefully,
will be SIGUSR2. When SIGUSR1 is received, the user code must do the 
following things:

1) Do fcloses on stdin, stdout, and stderr
2) Do closes on 0, 1, and 2
3) Delock the line
4) Update utmp:

                a) Change LOGIN to DIALOUT
                b) Change the type to a user process

5) I update wtmp even though SCO does not to keep a record of call outs
6) I then go into a pause state and wait for a "non-trapped" signal which
   should be SIGUSR2
7) Just exit and let init spawn a new getty

The way ungetty knows that the getty is no longer active is by the change
to utmp.
 
The following is my interface code:

------------------------------ cut here ---------------------------------


int	ungetty_call();
int	ungetty_flag;
char	Line[20];






main(argc,argv)
int argc;
char **argv;
{



/*
.................... initial .............................
................... getty code ...........................
*/

/*      A SIGUSR1 is used to cause getty to start the ungetty handshaking  */


	if(signal(SIGUSR1, ungetty_call) == (int(*)())-1)
		{
		error("getty: Unable to interface with SIGUSR1!.\n");
		exit(1);
		}


/*         More getty code             */

}

/* In some inital subroutine, store the line name into the Line array
   example:    strcpy(Line, line);
*/


int
ungetty_call()
{
	register int ownpid;
	register struct utmp *u;
	extern struct utmp *getutent(), *pututline();
	register FILE *fp;

	if(ungetty_flag) return;   /* If unable to call uugetty, return back */


/*   close the tty streams, 0, 1, and 2       */

	fclose(stdin);
	fclose(stdout);
	fclose(stderr);
	close(0);
	close(1);
	close(2);

	delock(Line);       /*    Remove symbolic lock       */


/* Look in "utmp" file for our own entry and change it to LOGIN. */
	ownpid = getpid();

	while ((u = getutent()) != NULL) {

/* Is this our own entry? */


/*  Change utmp entry from LOGIN to DIALOUT and the type to a USER PROCESS */
/*                           UUGETTY LOOKS FOR THIS!                       */


		if (u->ut_type == LOGIN_PROCESS && u->ut_pid == ownpid) {
			strncpy(u->ut_line,Line,sizeof(u->ut_line));
			strncpy(u->ut_user,"DIALOUT",sizeof(u->ut_user));
			u->ut_type = USER_PROCESS;

/* Write out the updated entry. */
			pututline(u);
			break;
		}
	}

/* If we were successful in finding an entry for ourself in the */
/* utmp file, then attempt to append to the end of the wtmp file. */


/* I also write into /etc/wtmp to keep a log of the call outs.  SCO does not
   do this but they really should                                          */

	if (u != NULL && (fp = fopen(WTMP_FILE,"r+")) != NULL) {
		fseek(fp,0L,2);	/* Seek to end of file */
		fwrite(u,sizeof(*u),1,fp);
		fclose(fp);
	}

/* Close the utmp file. */
	endutent();
/* Pause until ungetty says it is ok! */

/*  Instead of waiting for a SIGUSR2, I just go into a pause since the only
    other signal your getty will receive is a SIGUSR2 <hopefully>       */

	(void)pause();

/*  Just exit and init will spawn a new getty    */

	exit(0);
}