Ultrix-3.1/src/cmd/lprsetup/lprsetup.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

static char Sccsid[] = "@(#)lprsetup.c	3.0	4/21/86";

/************************************************************
*
*	Printer Installation/Setup  Program
*
*	This program helps system administrators set-up
*	printers for their system.  It guides through the
*	steps in setting up /etc/printcap, makes all of the
*	necessary links and directories for each printer,
*	and insures everything necessary for successful
*	printer operation was specified.
*
************************************************************/

#include "lprsetup.h"
#include "globals.h"
#include <sys/types.h>
#include <sys/stat.h>

long time();
extern int errno;

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

    if (argc != 1)
	usage();

    /**********************
    * check prerequisites
    **********************/
    if (getuid () != 0)
    {
	printf ("\n%s: must be superuser!\n\n", progname);
	leave (ERROR);
    }

    /* for Popen later (in misc.c) */
    for (i = 3; i < 20; i++)
	close(i);
    dup2(1, 3);

    if (fopen (PRINTCAP, "r") == NULL)
    {
	perror (PRINTCAP);
	leave (ERROR);
    }

    printf ("\nULTRIX-11 Printer Setup Program\n");

    /******************
    * loop until done
    ******************/
    for (;;)
    {
        /********************************
        *  clear changable table values
        ********************************/
        for (i = 0; tab[i].name != 0; ++i)
        {
	    tab[i].used = NO;
	    tab[i].nvalue = 0;
        }
	/*
	 * clear modify flag after each time
	 * through, used to keep track of when to
	 * link the filter(s).
	 */
	modifying = FALSE;

	printf ("\nCommand  < add modify delete exit help >: ");

	strcpy(pname, "");
	strcpy(pnum, "");

	switch (getcmd ())
	{
	    case ADD:
		DoAdd ();
		break;
	    case MODIFY:
		DoModify ();
		break;
	    case DELETE:
		DoDelete ();
		break;
	    case QUIT:
		printf("\n");
		leave (OK);
		break;
	    case HELP:
		printf (h_help);
		break;
	    case NOREPLY:
		break;
	    default:
		printf ("\nSorry, invalid choice.  Type '?' for help.\n");
		break;
	}
	freemem ();
    }
}

/*****************************************
*  add new entry to printcap and create
*  corresponding special device
*****************************************/
DoAdd ()
{
    int     done;
    int     status;

    printf("\nAdding printer entry, type '?' for help.\n");

    /***********************
    * get printer number
    ***********************/
    done = FALSE;
    while (!done)
    {
	int c;
	strcpy(pnum, "0");	/* assume zero if the next 9 don't match */
	strcpy(pname, "");

	/*
	 * See what the lowest numbered printer is, then
	 * use that as the default.  Only checks for printers
	 * 0 through 9, even though we support numbers up to 99.
	 * If an empty slot is not found, the printer number
	 * is reset to 0.
	 */
	symbolname[1] = '\0';
	for (c = '0'; c < ':'; c++) {	/* ':' comes after '9' */
		symbolname[0] = c;
		status = pgetent(bp, symbolname);
		if (status == -1) {
			badfile(PRINTCAP);
		}
		if (status == 1)
			continue;	/* this printer exists, try the next */
		else {
			strcpy(pnum, symbolname);
			break;
		}
	}
	if (strchr ("0123456789", pnum[0]) == NULL) {
		strcpy(pnum, "0"); /* should never happen but just in case... */
	}

	printf ("\nEnter printer number to add [%s] : ", pnum);
	switch (getcmd ())
	{
	    case NOREPLY:
		strcpy(symbolname, pnum); /* he entered the default printer # */
		/* no break! ...falls through to case GOT_SYMBOL: */
	    case GOT_SYMBOL:
		if ((status = strchr ("0123456789", symbolname[0])) == 0)
		     printf("\nSorry, bad printer number '%s'.  Enter a single digit [0-9]\n", symbolname);
		else {
		    status = pgetent (bp, symbolname);
		    if (status == -1) {
			badfile(PRINTCAP);
		    }
		    if (status == 1)
			printf("\nSorry, printer '%s' already exists.\n", symbolname);
		    else
			done = TRUE;
		}
		break;
	    case QUIT:
		return (QUIT);
		break;
	    case HELP:
		printf (h_doadd);
		break;
	    default:
		printf ("\nInvalid choice.  Type '?' for help.\n");
		break;
	}
    }
    strcpy (pnum, symbolname);
    sprintf(pname, "lp%s", pnum);

    if (AddField () != QUIT)
    {
	if (AddEntry () == ERROR)
	    printf("\nError in adding printcap entry, try again.\n");
	else
	if (AddDevice () == ERROR)
	    printf("\nError in associating printer files/directories.\n");
    }
    freemem ();
    printf("\n");
    return (OK);
}

/***********************************
*  modify existing printcap entry
************************************/
DoModify ()
{
    int     done = FALSE;
    int     status;

    printf("\nModifying a printer entry, type '?' for help.\n");
    while (!done)
    {
	/*
	 * flag the fact that we are modifying an entry and
	 * don't want to later attempt to link a filter since
	 * the second time around, the filter name is already
	 * linked to the proper filter.
	 */
	modifying = TRUE;

	strcpy(pnum, "");
	strcpy(pname, "");
	strcpy(longname, "");	/* in case of previous modify */

	printf ("\nEnter printer number to modify: ");

	switch (getcmd ())
	{
	    case GOT_SYMBOL:
		if ((status = strchr ("0123456789", symbolname[0])) == 0)
		     printf("\nSorry, bad printer number '%s'.  Enter a single digit [0-9]\n", symbolname);
		else
		{
		    status = pgetent (bp, symbolname);
		    if (status == -1) {
			badfile(PRINTCAP);
		    }
		    if (status == 0)
		        printf ("\nSorry, printer number '%s' is not in %s.\n", symbolname, PRINTCAP);
		    else
		    {
    		        strcpy(pnum, symbolname);
			sprintf(pname, "lp%s", pnum);
			findptype();		/* get correct global ptype */
		        ModifyEntry();
			done = TRUE;	/* get back to main menu */
		    }
		}
		break;
	    case QUIT:
		done = TRUE;
		break;
	    case HELP:
		printf (h_domod);
		break;
	    case NOREPLY:
		break;
	    default:
		printf ("\nInvalid choice, try again.\n");
		break;
	}
    }
    freemem();
    return (OK);
}

/***********************************
*  delete existing printcap entry
************************************/
DoDelete ()
{
    int     done = FALSE;
    int     status;

    printf ("\nDeleting a printer entry, type '?' for help.\n");
    while (!done)
    {
	strcpy(pnum, "");
	strcpy(pname, "");

	printf ("\nEnter printer number to delete: ");
	switch (getcmd ())
	{
	    case GOT_SYMBOL:
		if ((status = strchr ("0123456789", symbolname[0])) == 0)
		     printf("\nSorry, bad printer number '%c'.  Enter a single digit [0-9]\n", symbolname[0]);
		else
		{
		    status = pgetent (bp, symbolname);
		    if (status == -1) {
			badfile(PRINTCAP);
		    }
		    if (status == 0)
		        printf ("\nCannot delete printer %s, entry not found.\n", symbolname);
		    else
		    {
			strcpy(pnum, symbolname);
			sprintf(pname, "lp%s", pnum);
		        done = TRUE;
		    }
		}
		break;
	    case QUIT:
		return (QUIT);
		break;
	    case HELP:
		printf (h_dodel);
		break;
	    case NOREPLY:
		break;
	    default:
		printf ("\nInvalid choice, try again.\n");
	}
    }

    /*********************************
    *  read printcap into tab for
    *  final confirmation
    **********************************/
    CopyEntry ();

    Print (USED);
    printf ("\nDelete %s, are you sure? [n]  ", pname);

    if (YesNo ('n') == TRUE) {
	DeleteEntry ();
    }
    else {
	printf ("\n%s not deleted.\n", pname);
    }

    freemem ();
    printf("\n");
    return (OK);
}

/**************************
*  get fields for DoAdd
**************************/
AddField ()
{
    char    buf[LEN];		/* temp buffer		 */
    int     done;		/* flag			 */
    int     i;			/* temp index		 */

    /********************************
    *  clear changable tab values
    ********************************/
    for (i = 0; tab[i].name != 0; ++i)
    {
	tab[i].used = NO;
	tab[i].nvalue = 0;
    }

    if (MatchPrinter () == QUIT)
	return (QUIT);

    if (AddSyn () == QUIT)
	return (QUIT);

    if (strcmp (ptype, "lp11") != 0)
    {
	do {
	    printf ("\nSet printer baud rate 'br'");
	    sprintf (buf, "%s", "9600");
	} while (SetVal ("br", buf) < 0);

	do {
	    printf ("\nSet device pathname 'lp'");
	    /*
	     * If printer number is a single non-zero digit,
	     * then use that number for terminal line;
	     * otherwise, default to tty00.
	     */
	    if ((pnum[0] != '0') && (pnum[1] == '\0'))
                sprintf (buf, "%s%s", "/dev/tty0", pnum);
            else
                sprintf (buf, "%s", "/dev/tty00");
	} while (SetVal ("lp", buf) < 0);

	do {
	    printf ("\nSet output filter 'of'");
	    sprintf (buf, "%s", "/usr/lib/ulf");
	} while (SetVal ("of", buf) < 0);

	do {
	    printf ("\nSet accounting file 'af'");
            if (pnum[0] == '0' )
                sprintf (buf, "%s", "/usr/adm/lpacct");
            else
                sprintf (buf, "%s%s%s", "/usr/adm/lp", pnum, "acct");
	} while (SetVal ("af", buf) < 0);
    }

    /* These next values are set for ALL printers, including LP11 */

    do {
        printf ("\nSet spooler directory 'sd'");
        if (pnum[0] == '0' )
            sprintf (buf, "%s", "/usr/spool/lpd");
        else
            sprintf (buf, "%s%s", "/usr/spool/lpd", pnum);
    } while (SetVal ("sd", buf) < 0);

    do {
        printf ("\nSet printer error log file 'lf'");
        if (pnum[0] == '0' )
            sprintf (buf, "/usr/adm/lp.err");
        else
            sprintf (buf, "/usr/adm/lp%s.err", pnum);
    } while (SetVal ("lf", buf) < 0);

    /*********************************
    *  modify default field values
    *********************************/
    printf (h_symsel);
    for (i = 0; tab[i].name != 0; ++i)
        printf ("%s ", tab[i].name);
    printf ("\n");

    done = FALSE;
    for (;;)
    {
	while (!done)
	{
		printf ("\nEnter symbol name: ");
		switch (getcmd ())
		{
		    case GOT_SYMBOL:
			DoSymbol ();	/* Don't have to special case sd, the
					 * spooling directory since the entry
					 * is being added. It still can be
					 * changed since it doesn't exist yet.
					 */
			break;
		    case HELP:
			printf (h_symsel);
			for (i = 0; tab[i].name != 0; ++i)
			    printf ("%s ", tab[i].name);
			printf ("\n");
			break;
		    case NOREPLY:
			break;
		    case PRINT:
			Print (USED);
			break;
		    case LIST:
			Print (ALL);
			break;
		    case QUIT:
			done = TRUE;
			break;
		    default:
			printf ("\nInvalid choice, try again.\n");
			break;
		}
	}
	if (Verified () == TRUE)
	    break;
	else
	{
	    printf("Do you wish to continue with this entry?  [y] ");
	    if (YesNo ('y') == FALSE) {
		return(QUIT);		/* no, they wish to abort */
	    }
	    else
	        done = FALSE;
	}
    }
    return (OK);
}

/****************************************************
*  find matching printer by name and copy over fields
*  loop through default table, find match and assign.
*****************************************************/
MatchPrinter ()
{
    int     found, done;	/* flags	*/
    int     length;		/* strlen return */
    char   *addr;		/* malloc return */
    int     i, j, k;		/* temp indices	 */

    /****************************
    *  get printer type
    ****************************/
    found = FALSE;
    while (!found)
    {
	done = FALSE;
	while (!done)
	{
	    printf ("\nEnter printer type: ");
	    switch (getsymbol ())
	    {
		case GOT_SYMBOL:
		default:
		    strcpy (ptype, symbolname);
		    done = TRUE;
		    break;
		case HELP:
		    printf (h_type);
		    for (i = 0; printer[i].name != 0; ++i)
			printf ("%s ", printer[i].name);
		    printf ("\n");
		    break;
		case QUIT:
		    return (QUIT);
		    break;
		case NOREPLY:
		    printf ("\nUsing 'unknown' for printer type, OK? [ n ] ");
		    if (YesNo ('n') == TRUE) {
			strcpy (ptype, UNKNOWN);
		        done = TRUE;
		        found = TRUE;
		    }
		    break;
	    }
	}

	/******************************************
	*  loop through printer table, find match
	******************************************/
	for (i = 0; printer[i].name; ++i)
	    if (strncmp (printer[i].name, ptype, strlen (ptype)) == 0)
	    {
		found = TRUE;
		break;
	    }

	if (!found)
	{
	    printf ("\nDon't know about printer '%s'\n", ptype);
	    printf ("\nEnter 'y' to try again, or 'n' to use 'unknown' [y]: ");
	    if (YesNo ('y') == FALSE)
	    {
		strcpy (ptype, UNKNOWN);
		found = TRUE;
	    } else {
		found = FALSE;
	    }
	}
    }

    /**************************************************************
    * loop thru printer values and assign to corresponding
    * default new values - note: i contains correct printer index
    **************************************************************/
    for (j = 0; printer[i].entry[j].name; ++j)
    {
	/******************************
	*  loop through default table
	*******************************/
	for (k = 0; tab[k].name; ++k)
	{
	    if (strcmp (printer[i].entry[j].name, tab[k].name) == 0)
	    {
		length = strlen (printer[i].entry[j].svalue) + 1;
		if ((addr = malloc (length)) == NULL)
		{
		    printf ("\nmalloc: not enough space for symbols!\n");
		    return (ERROR);
		}
		tab[k].nvalue = addr;
		strcpy (tab[k].nvalue, printer[i].entry[j].svalue);
		tab[k].used = TRUE;
	    }
	}
    }
    return (OK);
}

/*****************************
*  add synonyms
*****************************/
AddSyn ()
{
    int     done, status;

    sprintf (pname, "lp%s", pnum);
    strcat (pname, "|");
    if (pnum[0] == '0')		/* add lp entry if lp0 */
	    strcat(pname, "lp|");
    strcat (pname, pnum);

    done = FALSE;
    while (!done && strlen (pname) < 80)
    {
        printf ("\nEnter printer synonym: ");
	switch (getcmd ())
	{
	    case GOT_SYMBOL:
		status = pgetent (bp, symbolname);
		if (status == -1) {
			badfile(PRINTCAP);
		}
		if (status == 1)
		    printf ("\nSynonym is already in use, try something else.\n");
		else
		    if (strlen (pname) + strlen (symbolname) > 79)
			printf ("\nSynonym too long, truncating to 80 characters.\n");
		    else
		    {
			strcat (pname, "|");
			strcat (pname, symbolname);
		    }
		break;
	    case HELP:
		printf (h_synonym);
		break;
	    case QUIT:
		return (TRUE);
		break;
	    case NOREPLY:
		return (TRUE);
		break;
	    default:
		printf ("\nInvalid choice, try again.\n");
		break;
	}
    }
    return(OK);
}

/*********************************
*  set default values
*  Returns -1 on error, 0 if ok
*********************************/
SetVal (val, buf)
char   *val;			/* two-letter symbol	 */
char   *buf;			/* preset value		 */
{
    int     i;			/* temp index		 */
    char    line[LEN];		/* temp buffer		 */

    /******************
    *  find val
    ******************/
    for (i = 0; tab[i].name; ++i)
	if (strcmp (tab[i].name, val) == 0)
	    break;
    if (tab[i].name == 0) {
	printf("internal error: cannot find symbol %s in table\n", val);
	return (BAD);
    }

    /************************
    *  set by MatchPrinter
    ************************/
    if (tab[i].nvalue != 0)
    {
	if (UseDefault (line, tab[i].nvalue, i) == FALSE)/* 3rd arg is index */
	{
	    if (validate(i, line) < 0) {
		return(BAD);
	    }
	    if ((tab[i].nvalue = malloc (strlen (line) + 1)) == NULL)
	    {
	    	printf ("\nmalloc: no space for %s\n", tab[i].name);
		return (ERROR);
	    }
	    strcpy (tab[i].nvalue, line);
	}
    }
    /************************
    *  use default
    ************************/
    else
    {
	UseDefault (line, buf, i);

	if (validate(i, line) < 0) {
	    return(BAD);
	}
	if ((tab[i].nvalue = malloc (strlen (line) + 1)) == NULL)
	{
	    printf ("\nmalloc: no space for %s\n", tab[i].name);
	    return (ERROR);
	}
	tab[i].used = YES;
	strcpy (tab[i].nvalue, line);
    }
    return(OK);
}

/**********************************************
*  write new printcap entry to printcap file
***********************************************/
AddEntry ()
{
    FILE *ofp, *lfp;		/* ouput and log file pointers */
    long     timeval;		/* time for log file		*/
    char     buf[LEN];		/* temp buffer			*/

    /****************************************
    *  open output and log files
    ****************************************/
    if ((ofp = fopen (PRINTCAP, "a")) == NULL) {
	badfile(PRINTCAP);
    }
    if ((lfp = fopen (LOGCAP, "a")) == NULL) {
	badfile(LOGCAP);
    }

    WriteEntry (ofp);

    /****************************************
    *  write time stamp and entry to log
    ****************************************/
    timeval = time(0);
    strcpy (buf, "\nAdded ");
    strcat (buf, ctime (&timeval));
    fputs (buf, lfp);

    WriteEntry (lfp);

    fclose (ofp);
    fclose (lfp);
    return (OK);
}

/***************************************
*  create special device, if necessary
***************************************/
AddDevice ()
{
    struct passwd  *passwd;	/* password file entry	 */
    char   *device;		/* parameter value ptr	 */
    int     mode;		/* chmod mode		 */
    int     i;			/* temp index		 */

    /*******************************
    *  get daemon id
    *******************************/
    if ((passwd = getpwnam (DAEMON)) == 0)
    {
	printf ("\ngetpwnam: cannot get id for %s\n", DAEMON);
	perror ();
	leave (ERROR);
    }

    /************************************
    *  chown and chmod device to daemon
    ************************************/
    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "lp") == 0)
	    break;

    if (tab[i].name == 0)
    {
	printf ("\nCannot find device pathname in table.\n");
	return (ERROR);
    }

    device = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    mode = 00700;
    if (chmod (device, mode) < 0)
    {
	printf ("\nCannot chmod %s to %o", device, mode);
	perror (device);
	/* continue anyway */
    }
    if (chown (device, passwd->pw_uid, passwd->pw_gid) < 0)
    {
	printf ("\nCannot chown %s to (%o/%o)\n", device,
	    passwd->pw_uid, passwd->pw_gid);
	perror (device);
	/* continue anyway */
    }

    /*******************************
    *  create spooling directory
    *******************************/
    MakeSpool (passwd);

    /***********************************
    *  link printer filter, if not LP11
    ***********************************/
    if (strcmp(ptype,"lp11") != 0)
	LinkFilter();
}

/******************************
*  Modify selected entry
*******************************/
ModifyEntry ()
{
    struct passwd *passwd;	/* passwd entry ptr		 */
    int     done;		/* flag				 */
    FILE    *ifp, *ofp;		/* input/ouput file pointers	 */
    char    keyname[LEN];	/* match name			 */
    char    buf[80];		/* read/write buffer		 */
    int	    i;			/* temp index			 */

    /*******************************
    *  get daemon id
    *******************************/
    if ((passwd = getpwnam (DAEMON)) == 0)
    {
	printf ("\ngetpwnam: cannot find %s uid in passwd file.\n", DAEMON);
	leave (ERROR);
    }

    /**********************
    *  modify fields
    **********************/
    CopyEntry ();	/* affects longname */

    for (;;)
    {
	done = FALSE;
	printf("\nEnter the name of the symbol you wish to change.\n");
	printf("Enter 'p' to print the current values, or 'q' to quit.\n");
	while (!done)
	{
	    printf ("\nEnter symbol name:  ");
	    switch (getcmd ())
	    {
		case GOT_SYMBOL:
		    if (strcmp("sd", symbolname) == 0)
			printf ("\nSorry, you cannot modify '%s'.\n",
				symbolname);
		    else
		    	DoSymbol ();
		    break;
		case HELP:
		    printf (h_symsel);
		    for (i = 0; tab[i].name != 0; ++i)
		        printf ("%s ", tab[i].name);
		    printf ("\n");
		    break;
		case NOREPLY:
		    break;
		case PRINT:
		    Print (USED);
		    break;
		case LIST:
		    Print (ALL);
		    break;
		case QUIT:
		    done = TRUE;
		    break;
		default:
		    printf ("\nInvalid choice, try again.\n");
		    break;
	    }
	}
	if (Verified() == TRUE)
	    break;
	else
	{
	    printf("Do you wish to continue with this entry?  [y] ");
	    if (YesNo ('y') == FALSE) {
		return(QUIT);	/* no, they wish to abort, although at this
			point, the return value (from here) is not checked.
			We just return early without actually do anything. */
	    }
	    else
	        done = FALSE;	/* not done yet */
	}
    }

    /**************************
    * save pname for match
    * and longname to rewrite
    **************************/
    strcpy (keyname, pname);	/* search later for keyname, like "lp2" */
    strcpy (pname, longname);	/* new pname contains the entire first line */

    /******************************
    *  open original and copy
    *******************************/
    if ((ifp = fopen (PRINTCAP, "r")) == NULL) {
	badfile(PRINTCAP);
    }
    if ((ofp = fopen (COPYCAP, "w")) == NULL) {
	badfile(COPYCAP);
    }

    /*************************************
    *  copy printcap to copy until entry
    **************************************/
    while (fgets (buf, 80, ifp) != 0)
    {
	if (strncmp (keyname, buf, strlen (keyname)) != 0)
	    fputs (buf, ofp);
	else
	    while (fgets (buf, 80, ifp) != 0)
		if (buf[strlen(buf) - 2] != '\\')
		{
		    WriteEntry (ofp);
		    break;
		}
    }

    fclose (ofp);
    fclose (ifp);

    /***************************
    * mv new file to old file
    ***************************/
    if (rename (COPYCAP, PRINTCAP) < 0)
    {
	printf ("\nCannot rename %s to %s (errno = %d).\n",
		COPYCAP, PRINTCAP, errno);
	/* don't know what best to do here...*/
    }

    /*******************************
    *  create spooling directory
    *******************************/
    MakeSpool (passwd);

    /***************************************
    * relink printer filter, if necessary
    ***************************************/
    /*
     * don't link filter for lp11 type lines; also, don't
     * want to re-link filter if we are only "modifying" the
     * entry, rather, link the filter only if this is a first
     * time entry creation for this printer.
     */
    if ((strcmp(ptype, "lp11") != 0) || (NOT modifying))
    	LinkFilter();
}


/**********************************
*  delete existing printcap entry
*  unlink printer filter, change tty
*  back to owner root, 666.  Put
*  /etc/ttys file back to 00, disabled.
**********************************/
DeleteEntry ()
{
    FILE *ifp, *ofp, *lfp;	/* input/output file pointers	*/
    char    buf[LEN];		/* read/write buffer		*/
    long    timeval;		/* time in seconds for logfile	*/
    char    tempfile[LEN];	/* file name buffer 		*/
    int     i, mode;
    char   *curval;
    char   *device;

    /*********************************
    *  open original, copy, and log
    **********************************/
    if ((ifp = fopen (PRINTCAP, "r")) == NULL) {
	badfile(PRINTCAP);
    }

    sprintf (tempfile, "%s%d", COPYCAP, getpid());
    if ((ofp = fopen (tempfile, "w")) == NULL)
    {
	printf("\nCannot open intermediate file: %s.\n", tempfile);
	perror (tempfile);
	leave (ERROR);
    }

    if ((lfp = fopen (LOGCAP, "a")) == NULL) {
	badfile(LOGCAP);
    }

    timeval = time(0);
    strcpy (buf, "\nDeleted ");
    strcat (buf, ctime(&timeval));
    fputs (buf, lfp);

    /*****************************************
    *  copy printcap to copy until next entry
    *****************************************/
    while (fgets (buf, 80, ifp) != 0)
    {
	if (strncmp (pname, buf, strlen (pname)) != 0)
	    fputs (buf, ofp);
	else
	{
	    fputs (buf, lfp);
	    while ((fgets (buf, 80, ifp) != 0) && (buf[strlen(buf) - 2] != ':'))
	    {
		    fputs (buf, lfp);
	    }
	    /* write line with colon */
	    fputs (buf, lfp);
	}
    }

    if (rename (tempfile, PRINTCAP) < 0) {
	printf("\nCannot rename %s to %s (errno=%d).\n",
		tempfile, PRINTCAP, errno);
    }
    fclose (ofp);
    fclose (ifp);
    fclose (lfp);

    UnLinkFilter();
    UnLinkSpooler();

    /*
     * Put the /etc/ttys file entry
     * for this line to mode 00, "disabled"
     */
    for (i = 0; tab[i].name != 0; ++i) {
	if (strcmp(tab[i].name, "lp") == 0) {
	    curval=(tab[i].nvalue ? tab[i].nvalue : tab[i].svalue);
	    if (strncmp(curval, "/dev/tty", 8) == 0) {
		curval=index(curval, 't');
		fixtty(curval,"00");	/* yes, it is "/dev/ttyxx" */
		break;
	    }
        }
    }

   /*
    *  chown and chmod device back to root, 0666
    */
    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "lp") == 0)
	    break;

    if (tab[i].name == 0)
	return;		/* early return */

    device = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    if (chown (device, 0, 1) < 0)	/* ID's: root/other */
    {
	printf ("\nCannot chown %s to (0/1)\n", device);
	perror (device);
	return;		/* early return */
    }
    mode = 0666;
    if (chmod (device, mode) < 0)
    {
	printf ("\nCannot chmod %s back to %o", device, mode);
	perror (device);
	/* fall through to return */
    }
    return(OK);
}

/***********************
*  copy entry into tab
************************/
CopyEntry ()
{
    char    line[LEN];		/* read buffer		 */
    char    tmpline[LEN];	/* temporary buffer	 */
    char   *lineptr;		/* read buffer ptr	 */
    char   *ptr;		/* temp pointer		 */
    int     num;		/* pgetnum return	 */
    int     i;			/* temp index 		 */

    /*************************
    *  save names for rewrite
    **************************/
    if ((ptr = index(bp, ':')) > 0) {
	strncpy (longname, bp, ptr - &bp);
    }
    longname[ptr - &bp] = '\0';
/*
 * The first character of the long name should always be 'l'.
 */
    if (longname[0] != 'l') {
    /*	printf("1061: bp[0] is not 'l'\n"); */
	longname[0] = 'l';
    }

    /****************************************************
    * loop thru table, changing values where appropriate
    ****************************************************/
    for (i = 0; tab[i].name != 0; ++i)
    {
	switch (tab[i].stype)
	{
	    case BOOL:
		if (pgetflag (tab[i].name) == TRUE)
		{
		    if ((tab[i].nvalue = malloc (strlen ("on") + 1)) == NULL)
		    {
			printf ("\nCannot malloc space for %s\n", tab[i].name);
		    }
		    else
		    {
		        strcpy (tab[i].nvalue, "on");
		        tab[i].used = YES;
		    }
		}
		break;
	    case INT:
		if ((num = pgetnum (tab[i].name)) >= 0)
		{
		    /* fc, fs, xc, xs are in octal, all others are decimal */
		    if ((strcmp(tab[i].name, "fc") == 0) ||
			(strcmp(tab[i].name, "fs") == 0) ||
			(strcmp(tab[i].name, "xc") == 0) ||
			(strcmp(tab[i].name, "xs") == 0)) {
			sprintf (tmpline, "%o", num);
			strcpy(line, "0");	/* put the zero out in front */
			strcat(line, tmpline);
		    } else {
		    	sprintf (line, "%d", num);
		    }
		    if ((tab[i].nvalue = malloc (strlen (line) + 1)) == NULL)
		    {
			printf ("\nCannot malloc space for %s\n", tab[i].name);
		    }
		    else
		    {
		    	strcpy (tab[i].nvalue, line);
		    	tab[i].used = YES;
		    }
		}
		break;
	    case STR:
		lineptr = line;
		if (pgetstr (tab[i].name, &lineptr) != NULL)
		{
		    *lineptr = 0;
		    if ((tab[i].nvalue = malloc (strlen (line) + 1)) == NULL)
		    {
			printf ("\nCannot malloc space for %s\n", tab[i].name);
		    }
		    else
		    {
		   	strcpy(tab[i].nvalue, line);
		    	tab[i].used = YES;
		    }
		}
		break;
	    default:
		printf ("\nBad type (%d) for %s\n", tab[i].stype, tab[i].name);
		break;
	}
    }
    return(OK);
}

/******************************
*  write single entry to file
*******************************/
WriteEntry (fp)
FILE * fp;
{
    int     i;			/* temp index			 */
    char   *curval;		/* pointer to current value	 */
    char localname[LEN];	/* output filter, lp2 or whatever */

    fprintf (fp, "%s:", pname);	/* here, pname is really the longname */
    for (i = 0; tab[i].name != 0; ++i)
    {
	if (tab[i].used == YES)
	{
	    curval = (tab[i].nvalue ? tab[i].nvalue : tab[i].svalue);
	    switch (tab[i].stype)
	    {
		case BOOL:
		    if (strcmp ("on", curval) == 0)
			fprintf (fp, "\\\n\t:%s:", tab[i].name);
		    break;
		case INT:
		    if (strcmp ("none", curval) != 0)
		        fprintf (fp, "\\\n\t:%s#%s:", tab[i].name, curval);
		    break;
		case STR:
		    if (strlen (curval) > 0) {
			/*
			 * Have to correct for proper 'of' in printcap file
			 */
			if (strcmp (tab[i].name, "of") == 0) {
			    /*
			     * If it's not an LP11, generate the
			     * correct output filter name.
			     */
			    if (strcmp(ptype, "lp11") != 0) {
				sprintf(localname, "/usr/lib/lp%s", pnum);
				curval = localname;
			    }
			}
		    	fprintf (fp, "\\\n\t:%s=%s:", tab[i].name, curval);
		    }
		    break;
		default:
		    printf ("\nbad type (%d) for %s\n", tab[i].stype, tab[i].name);
		    break;
	    }
	}
    }
    fprintf (fp, "\n");
    return(OK);
}

/*******************************
*  create spooling directory
*******************************/
MakeSpool (passwd)
struct passwd  *passwd;		/* password file entry	 */
{
    char   *spool;		/* parameter value ptr	 */
    int    i;			/* temp index	*/
    struct stat sb;

    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "sd") == 0)
	    break;

    if (tab[i].name == 0)
    {
	printf ("\nCannot find spooler directory entry in table!\n");
	printf ("No spooling directory created.\n");
	return (ERROR);
    }
    spool = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    /*
     * If stat fails, and then cannot mkdir, so exit.
     */
    if (stat(spool, &sb) < 0) {
	if (mkdir(spool, DIR) == -1) {
	    printf ("\nCannot make spooling directory %s\n", spool);
	    perror (spool);
	    return (ERROR);
        }
    } else {
	/* spooling directory exists... */
	if ((sb.st_mode&S_IFMT) != S_IFDIR) {
	    printf ("\nSpooling directory %s already exists, but is not a directory!\n", spool);
	    return (ERROR);
	}
    }

    if (chmod (spool, 00755) == -1)
    {
	printf ("\nCannot chmod %s to mode 0755\n", spool);
	perror (spool);
	return (ERROR);
    }

    if (chown (spool, passwd -> pw_uid, passwd -> pw_gid) == -1)
    {
	printf ("\nCannot chown %s to (%o/%o)\n", spool, passwd->pw_uid,
	    passwd->pw_gid);
	perror (spool);
	return (ERROR);
    }
    return(OK);
}

/**************************
*  link printer filter
**************************/
LinkFilter ()
{
    char   *filter;		/* parameter value ptr	 */
    char   *curval;		/* pointer to current value	 */
    char   localname[LEN];	/* temp filter if different */
    int    i;			/* temp index	*/

    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "of") == 0)
	    break;

    if (tab[i].name == 0)
    {
	printf ("\nCannot find value of output filter 'of' in table!\n");
	return (ERROR);
    }

    /***************************
    * link current filter
    ***************************/

    /* filter is the real one to link TO, (e.g.  ulf, lqf, ln01of, ln03of) */
    filter = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    /* localname is the link itself (e.g. /usr/lib/lp2, lp5)  */
    sprintf(localname, "/usr/lib/lp%s", pnum);

    /* see if in modify mode, if so, just return */
    if (modifying == TRUE)
	return(OK);

    printf("\nunlink(%s)\n", localname);
    unlink(localname);

    if (strcmp(filter, localname))
    {
	/* if filters are NOT the same, then link them */
        printf("link(%s, %s)\n", filter, localname);
	if (link (filter, localname) < 0)
	{
	    printf ("\nCannot link(%s, %s)\n", filter, localname);
	    perror (filter);
	    return (ERROR);
	}
    } else {
	/* else filter == localname so use ULF as default */
        printf("\nlink(%s, %s)\n", ULF, localname);
	if (link (ULF, localname) < 0)
	{
	    printf ("\nCannot link(%s, %s)\n", ULF, localname);
	    perror (ULF);
	    return (ERROR);
	}
    }
    /*
     * Change the /etc/ttys file entry
     * for this tty line to mode 30, "local - no logins".
     */
    for (i = 0; tab[i].name != 0; ++i) {
	if (strcmp(tab[i].name, "lp") == 0) {
	    curval=(tab[i].nvalue ? tab[i].nvalue : tab[i].svalue);
	    if (strncmp(curval, "/dev/tty", 8) == 0) {
		curval=index(curval, 't');
		fixtty(curval,"30");	/* yes, it is "/dev/ttyxx" */
		break;
	    }
        }
    }
    return(OK);
}

/**************************
*  unlink printer filter
**************************/
UnLinkFilter ()
{
    int    i;
    char  *filter;

    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "of") == 0)
	    break;

    if (tab[i].name == 0)
	return;		/* filter is just left laying around */

    filter = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    printf("\nunlink(%s)\n", filter);
    if (unlink(filter) < 0) {
	printf("couldn't unlink old printer filter (%s)\n", filter);
    }
}

/**************************
*  unlink spooler directory
**************************/
UnLinkSpooler()
{
    int    i;
    char  *spooler;

    for (i = 0; tab[i].name != 0; ++i)
	if (strcmp (tab[i].name, "sd") == 0)
	    break;

    if (tab[i].name == 0)	/* can't find 'sd' symbol */
	return;		/* spool directory is just left laying around */

    spooler = tab[i].nvalue ? tab[i].nvalue : tab[i].svalue;

    printf("rmdir(%s)\n", spooler);
    if (rmdir(spooler) < 0) {
	printf("couldn't unlink old spooler directory (%s)\n", spooler);
    }
}

/**************************
 * findptype:  get correct
 * value of printer type, most
 * importantly, is it LP11?
 **************************/
findptype()
{
	char s[128];
	char *p;
	int status;

	strcpy(s, pnum);
	status = pgetent(bp, s);
	if (status == -1) {
		badfile(PRINTCAP);
	}
	if (status == 1) {	/* printer exists */
		if ((p = pgetstr("lp", &bp)) == NULL) {
			printf("Warning: Cannot find symbol 'lp' in %s\n", PRINTCAP);
		/*	printf("Warning: using 'unknown' for printer type\n"); */
			strcpy(ptype, "unknown");
		} else
			if (strcmp(p, "/dev/lp") == 0)
				strcpy(ptype, "lp11");
	}
}

/**************************
 * badfile: print "cannot open
 * <filename>", and exit(1).
 **************************/
badfile(s)
char *s;
{
	printf("\nCannot open %s\n", s);
	perror(s);
	leave(ERROR);
}

/******************************************************************************
* end of lprsetup.c
******************************************************************************/