home *** CD-ROM | disk | FTP | other *** search
- Subject: v16i028: Public lineprinter spooler package, Part15/16
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: papowell@julius.cs.umn.edu
- Posting-number: Volume 16, Issue 28
- Archive-name: plp/part15
-
- #! /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 archive 15 (of 16)."
- # Contents: src/lp.h src/utils.c
- # Wrapped by papowell@attila on Wed Aug 10 10:45:12 1988
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'src/lp.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/lp.h'\"
- else
- echo shar: Extracting \"'src/lp.h'\" \(23350 characters\)
- sed "s/^X//" >'src/lp.h' <<'END_OF_FILE'
- X/*************************************************************************
- X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
- X *************************************************************************
- X * MODULE: lp.h
- X * Includes and definitions for all programs
- X *************************************************************************
- X * Revision History: Created Sun Jan 3 15:37:08 CST 1988
- X * $Header: lp.h,v 3.2 88/06/24 17:15:52 papowell Exp $
- X * $Log: lp.h,v $
- X * Revision 3.2 88/06/24 17:15:52 papowell
- X * MODS for VAX 4.3BSD UNIX
- X *
- X *
- X * Revision 3.1 88/06/18 09:34:30 papowell
- X * Version 3.0- Distributed Sat Jun 18 1988
- X *
- X * Revision 2.3 88/05/29 13:09:55 papowell
- X * Added Header string for RCS purposes
- X *
- X * Revision 2.2 88/05/14 10:18:16 papowell
- X * Use long format for job file names;
- X * Added 'fd', no forward flag;
- X * Control file has to have hostname and origination agree.
- X *
- X * Revision 2.1 88/05/09 10:10:48 papowell
- X * PLP: Released Version
- X *
- X * Revision 1.12 88/05/09 10:03:39 papowell
- X * Revised effects of -h option
- X *
- X * Revision 1.11 88/05/05 20:08:53 papowell
- X * Added a NOHEADER option that allows user to suppress banner
- X *
- X * Revision 1.10 88/04/29 07:48:55 papowell
- X * Added USE_LOCKF flags
- X *
- X * Revision 1.9 88/04/28 17:32:47 papowell
- X * fixed Data General Options
- X *
- X * Revision 1.8 88/04/21 21:49:40 papowell
- X * BADSETREUID: this flag is provided for situations where setreuid()
- X * does not allow changing back to root after changing to a user.
- X * This is a problem in security, and should be avoided.
- X *
- X * Revision 1.7 88/04/07 12:29:13 papowell
- X * Removed AF_UNIX socket definitions
- X *
- X * Revision 1.6 88/04/07 09:09:23 papowell
- X * Apollo Workstation Modifications
- X *
- X * Revision 1.5 88/04/06 12:13:40 papowell
- X * Minor updates, changes in error message formats.
- X * Elimination of the AF_UNIX connections, use AF_INET only.
- X * Better error messages.
- X *
- X * Revision 1.4 88/03/25 14:59:54 papowell
- X * Debugged Version:
- X * 1. Added the PLP control file first transfer
- X * 2. Checks for MX during file transfers
- X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
- X * apparently they open files and then assume that they will stay
- X * open.
- X * 4. Made sure that stdin, stdout, stderr was available at all times.
- X *
- X * Revision 1.3 88/03/11 19:29:10 papowell
- X * Minor Changes, Updates
- X *
- X * Revision 1.2 88/03/05 15:02:09 papowell
- X * Minor Corrections, Lint Problems
- X *
- X * Revision 1.1 88/03/01 12:42:54 papowell
- X * Initial revision
- X *
- X *************************************************************************/
- X
- X/*************************************************************************
- X * Make sure that you set the DEBUG flag if XPERIMENT is set
- X *
- X *************************************************************************/
- X#ifdef XPERIMENT
- X#define DEBUG 1
- X#endif XPERIMENT
- X/*************************************************************************
- X * Portability Definitions
- X * Several systems do not have the same definitions for these items.
- X * You will have to add your own local definitions.
- X * Ahh... Dream of the day of a standard set of definitions
- X *************************************************************************/
- X#ifdef IS_SUN
- X#define uid_t int /* keep lint on the sun happy */
- X#endif IS_SUN
- X
- X#ifdef IS_VAX4BSD
- X#define SETREUID4BSD 1
- X#endif IS_VAX4BSD
- X
- X#ifdef IS_DATAGEN
- X#define fd_set int /* keep lint happy */
- X#define uid_t int /* keep lint happy */
- X#define NOSYMLINK /* no symbolic links */
- X#define USE_LOCKF /* use the lockf() function for locking */
- X#define F_TLOCK 2 /* test and lock a section (non-blocking) */
- X#endif IS_DATAGEN
- X
- X#ifdef IS_UMAX
- X#undef B19200
- X#undef B38400
- X#define B19200 EXTA
- X#define B38400 EXTB
- X#define time_t long
- X#define uid_t int
- X#endif IS_UMAX
- X
- X#ifdef IS_APOLLO
- X#undef B19200
- X#undef B38400
- X#define B19200 EXTA
- X#define B38400 EXTB
- X#define uid_t int
- X#define USE_STRINGS /* use <strings.h> instead of <string.h> */
- X#define NO_A_OUT_H /* no a.out.h include file */
- X#endif IS_APOLLO
- X
- X/******************************************************************
- X * System Include Files
- X ******************************************************************/
- X#include <stdio.h>
- X#include <sys/param.h>
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <sys/dir.h>
- X#include <sys/time.h>
- X#include <sys/stat.h>
- X#include <sys/socket.h>
- X#include <sys/resource.h>
- X#include <netinet/in.h>
- X#include <netdb.h>
- X#include <pwd.h>
- X#include <signal.h>
- X#include <sys/wait.h>
- X#include <sgtty.h>
- X#include <ctype.h>
- X#ifdef USE_STRINGS
- X#include <strings.h>
- X#else USE_STRINGS
- X#include <string.h>
- X#endif USE_STRINGS
- X#include <errno.h>
- X#include <grp.h>
- X
- X
- X/******************************************************************
- X * Declare Standard Routines.
- X * Note: most of these are not declared in include files.
- X * This leads to some interesting problems with LINT. Declare these
- X * here. Some specialized routines are declared in the individual
- X * routines that use them.
- X ******************************************************************/
- extern char *malloc(), *realloc();
- extern char *getenv();
- extern char *gets();
- extern int errno, sys_nerr;
- extern char *sys_errlist[];
- extern char *index(), *rindex();
- extern char *sprintf(); /* sigh... sprintf strikes again */
- extern long lseek(), atol();
- X
- extern uid_t getuid(), geteuid();
- extern time_t time(); /* watch this one */
- X
- X/*
- X * This should be declared in <signal.h>
- X */
- X#ifndef sigmask
- X#define sigmask(m) (1 << ((m)-1))
- X#endif
- X
- X/*************************************************************************
- X * PRINTCAP entries and associated variables.
- X * Each printcap entry has a corresponding variable; for example
- X * ":af=accnt:"
- X * -> AF = "accnt";
- X *************************************************************************/
- extern int AB; /* Always have a banner flag, ignore lpr -h option */
- extern char *AF; /* accounting file */
- extern char *BP; /* banner printer filter */
- extern int BK; /* Berkeley compatible remote and local */
- extern int BR; /* baud rate if lp is a tty */
- extern int CO; /* cost of printing in dollars */
- extern char *EP; /* end printer filter */
- extern int FD; /* No forwarding, accept only from original site */
- extern int FO; /* print a form feed when device is opened */
- extern int FC; /* flags to clear if lp is a tty */
- extern char *FF; /* form feed string */
- extern int FJ; /* send control file first to remote site */
- extern int FQ; /* form feed on quitting */
- extern int FS; /* flags to set if lp is a tty */
- extern char *FX; /* allowable formats */
- extern char *LD; /* leader string on opening */
- extern char *LF; /* log file for error messages */
- extern int LH; /* use long host name */
- extern char *LO; /* lock file name */
- extern char *LN; /* group allowed to use links */
- extern char *LP; /* line printer device name */
- extern int MC; /* maximum number of copies allowed */
- extern int MX; /* maximum number of blocks to copy */
- extern int NW; /* Networked file system, do not make copies */
- extern int PL; /* page length */
- extern char *PR; /* pr program name name */
- extern char *PS; /* printer status file name */
- extern int PW; /* page width */
- extern int PX; /* page width in pixels */
- extern int PY; /* page length in pixels */
- extern char *QH; /* queue handler */
- extern char *RG; /* restrict use to group */
- extern char *RM; /* remote machine name */
- extern char *RP; /* remote printer name */
- extern int RT; /* max retries */
- extern int RW; /* open LP for reading and writing */
- extern int SB; /* short banner instead of normal header */
- extern int SC; /* suppress multiple copies */
- extern char *SD; /* spool directory */
- extern int SF; /* suppress FF on each print job */
- extern int SH; /* suppress header page */
- extern char *SS; /* name of queue that the server serves */
- extern char *ST; /* status file name */
- extern char *SV; /* names of servers */
- extern char *TR; /* trailer string to be output when Q empties */
- extern char *TY; /* terminal characteristics, stty options */
- extern int XC; /* flags to clear for local mode */
- extern int XS; /* flags to set for local mode */
- extern char *XT; /* format checked for text only */
- extern char *XU; /* restrict use to users whose names are in file */
- X/*
- X * Filter_name[] is an array of filter names, indexed by the first letter
- X * of the printcap tag. For example:
- X * ":if=/usr/lib/iffilter -n -a:"
- X * -> Filter_name['i'-'a'] = "/usr/lib/iffilter -n -a";
- X */
- extern char *Filter_name[26];
- X#define IF (Filter_name['i'-'a'])
- X#define OF (Filter_name['o'-'a'])
- X/*
- X * Prefilter_name[] is similar to Filter_name[], but for prefilter entries.
- X */
- extern char *Prefilter_name[26];
- X
- X/**********************************************************************
- X * Globally accessed variables and routines
- X **********************************************************************/
- extern char *Name; /* program name */
- extern char *Printer; /* printer name */
- extern char *Person; /* user name */
- extern char Host[64]; /* Host machine name */
- extern char *From; /* client's machine name */
- extern int Debug; /* Debugging level */
- extern int Echo_on_stdout; /* stderr output on stdout as well */
- extern char *First_name; /* first name in printcap entry */
- extern FILE *Lfd; /* lock file */
- extern int Optind, Opterr; /* option index, error message suppression */
- extern char *Optarg; /* option value */
- extern char *Opt_flag; /* option staring flags */
- extern char Lpdlogf[]; /* = DEFLPDLOGF; */
- extern char Masterlock[]; /* = MASTERLOCK; */
- extern int Lpr_port_num; /* port number to connect to */
- extern int Maxportno; /* = MAXPORTNO; */
- extern int Minportno; /* = MINPORTNO; */
- extern char Permfile[]; /* = PERMFILE; */
- extern char Printcap[]; /* = PRINTCAP; */
- extern char Last_errormsg[]; /* last errormessage */
- extern int Request; /* current lpd request code */
- extern int Print_fd; /* output printer FILE */
- extern int Short_format; /* short status format */
- extern int Is_root; /* is this the root user? */
- extern int Is_local; /* doing this locally or remotely? */
- extern struct stat LO_statb; /* used to stat lockfile */
- extern void Print_close(), Link_close(); /* close these things */
- extern int Daemon_uid; /* daemon UID */
- extern int Daemon_gid; /* daemon GID */
- extern char *estrcp(); /* handy form of strcp() */
- extern char *Time_str(); /* ctime with \n removed */
- extern char *Setup_filter(); /* set up argv for a filter */
- extern int Reapchild(); /* wait3() for a child */
- extern int Getopt(); /* get command line option */
- extern char *Errormsg(); /* printable error message */
- extern int Errorcode; /* exit() value on fatal termination */
- extern char *Decode_status(); /* decode a status returned by wait() */
- extern FILE *fopen_daemon(); /* open a file as daemon */
- extern int open_daemon(); /* open a file as daemon */
- X
- X/*******************************************************************
- X * struct queue
- X * used to record entries in the spool directory for printing
- X * and status reporting.
- X * NOTE: control and data file names in spool directory have the form
- X * c f <priority> <job number> <Hostname> <terminating 0>
- X * d f <seq> <job number> <Hostname> <terminating 0>
- X * 1 1 1 3 max 64 1
- X * eg: dfA001attila.cs.umn.edu (attila the SUN, of course)
- X * eg: cfZ001attila.cs.umn.edu (attila the SUN, of course)
- X *******************************************************************/
- X#define CFNAMELEN (sizeof(Host)+8) /* control or data file name length */
- X/*
- X * fields in the name
- X */
- X#define STARTPR 2 /* df[] */
- X#define STARTID 3 /* dfX[] */
- X#define IDLEN 3 /* dfX[NNN] */
- X#define STARTFR 6 /* dfXNNN[] */
- X#define MAXPARMLEN 80
- struct queue {
- X char q_name[CFNAMELEN+1]; /* name of the control file */
- X time_t q_time; /* modification time */
- X time_t q_sp; /* spooled at time */
- X time_t q_unsp; /* unspool at time */
- X int q_priority; /* priority */
- X long q_size; /* size of the data files */
- X char q_user[32]; /* user name */
- X int q_num; /* job number */
- X char q_data[MAXPARMLEN+1]; /* data files name */
- X int q_daemon; /* daemon for this entry */
- X char *q_server; /* server for this entry */
- X};
- X
- X#define q_from q_name[STARTFR]
- extern int Getq(); /* find queue entries */
- extern struct queue *Jobentry; /* current job entry in queue */
- extern struct queue *Queue; /* Getq generates an array of jobs */
- extern int Jobcount; /* and returns the number of jobs */
- X
- extern int Rec_cnt; /* number of files in a job */
- X
- X/********************************************************************
- X * File Permissions
- X ********************************************************************/
- X
- X#define LFMODE 0644 /* log file permissions */
- X#define FILMOD 0600 /* spooling directory file permission */
- X
- X/*
- X * Queue Control is done by using the permissions of the lock file
- X * for the queue. The following permissions are used:
- X * Disable Printing: owner execute or 0100
- X * Disable Queing: group execute or 0010
- X * Queue handler active (antique) 0001
- X */
- X#define DISABLE_PRINT (0100)
- X#define ENABLE_PRINT (0777 & ~ DISABLE_PRINT)
- X#define DISABLE_QUEUE (0010)
- X#define ENABLE_QUEUE (0777 & ~ DISABLE_QUEUE)
- X#define FORCE_REQUE (0001)
- X#define CLEAR_REQUE (0777 & ~ FORCE_REQUE)
- X
- X/*
- X * syslog(8) message priorities. These are defined by the values of
- X * global variables. The variables are initialized either with values
- X * in the <syslog.h> include file, or by a set of default values according
- X * to the NOSYSLOG option in the Makefile.
- X */
- extern int XLOG_ERR; /*4 synonym of LOG_ERROR */
- extern int XLOG_CRIT; /*5 critical information */
- extern int XLOG_WARNING; /*6 warning */
- extern int XLOG_NOTICE; /*7 important information */
- extern int XLOG_INFO; /*8 informational message */
- extern int XLOG_DEBUG; /*9 Debug level info */
- X
- X/*******************************************************************
- X * Printcap Data Structures
- X * The printcap file information is extracted using a single pass of
- X * the printcap database. As each entry is found, it is looked up
- X * in a table which has the entry tag, the type of entry,
- X * a default value, and the variable used to hold the value.
- X *
- X * The table is sorted alphabetically by the tag values and the update
- X * routines use a modified binary search. The time taken to read the
- X * printcap entry is proportional to
- X * K log( M ), where K is the length of the printcap file and M is
- X * the number of printcap variables. Note that this appears to be
- X * a much simpler and easier way to implement printcap information
- X * extraction. The "initialization" of the entire set of variables
- X * is extremely fast, apparently taking about the same time as reading
- X * two variables using the original "termcap" code.
- X *******************************************************************/
- typedef struct pc_entry{
- X char pc_name[3]; /* two character name, and the last char */
- X int kind; /* the kind of entry */
- X# define PC_NUM 0 /* integer */
- X# define PC_FLAG 1 /* integer */
- X# define PC_STRING 2 /* string */
- X int idefault; /* this is the default integer or flag value */
- X char *sdefault; /* this is the default integer or flag value */
- X /*
- X * the variable is assumed to be a pointer to char;
- X * this is cast to pointer to int if neccessary.
- X */
- X char **var;
- X} PC_ENTRY;
- X
- X/*
- X * Routines to look up printer names and printcap entries
- X * char ** All_printers(): reads the printcap database and extracts the
- X * names of all the printer entries.
- X * char *First_printer(): gets name of first printer
- X * Get_pc_entry(): given name of a printer and an array of PC_ENTRIES,
- X * it finds the printcap entry and extracts all the information
- X * for the variables listed in the array.
- X * Set_pc_entry(): same functionality, does not initialize variables.
- X */
- X#define PRNAMELEN 32 /* Maximum of 32 characters for printer name */
- X#define MAXPCNAMES 100 /* Maximum of 100 printers */
- extern int Get_pc_entry( /* char *name; PC_ENTRY *pc_vars; int pc_len */);
- extern int Set_pc_entry( /* char *name; PC_ENTRY *pc_vars; int pc_len */);
- extern char **All_printers(); /* returns array printer names */
- extern char *First_printer(); /* returns array printer names */
- X/*
- X * All_pc_vars[]: all printcap variables, and is used by lpr and lpd;
- X * Status_pc_vars[]: a short set needed by lpq, lprm, and lpc.
- X * Server_pc_vars[]: a few needed by servers only
- X */
- extern PC_ENTRY All_pc_vars[ /* All_pc_len */ ];
- extern int All_pc_len;
- extern PC_ENTRY Status_pc_vars[ /* Status_pc_len */ ];
- extern int Status_pc_len;
- extern PC_ENTRY Server_pc_vars[ /* Server_pc_len */ ];
- extern int Server_pc_len;
- X
- X/***********************************************************************
- X * File Locking Support:
- X * see lockfile.c for details.
- X ***********************************************************************/
- extern FILE *Readlockfile(); /* reads file, returns FILE * */
- extern FILE *Getlockfile(); /* locks file, returns FILE * */
- extern int Checklockfile(); /* checks for lock and daemon */
- extern FILE *Lockcf(); /* lock a control file */
- extern int Exlockcf(); /* create and lock a control file */
- X
- X/***********************************************************************
- X * Parameter List Support
- X * struct parm parmlist[]
- X * is used when parsing a command received from a remote Host
- X * It is also used by lpr to determine the command file, and to keep
- X * track of the file/datafile name correspondence.
- X ***********************************************************************/
- X#define MAXPARMS 50
- struct parm{
- X char *str; /* string parameter */
- X int num; /* number parameter */
- X char filename[CFNAMELEN+1]; /* file name for parameter */
- X long size; /* size of file */
- X};
- extern struct parm Parms[MAXPARMS]; /* array of parmaters */
- extern int Parmcount; /* number of parameters */
- X
- X/***********************************************************************
- X * Request types
- X * A request sent to the LPD daemon has the format:
- X * \Xprinter [options], where \X is a single character or byte value.
- X * The following are the values and commands
- X ***********************************************************************/
- X#define REQ_START 1 /* start printer */
- X#define REQ_RECV 2 /* transfer a job to the Host from a remote site */
- X#define REQ_DSHORT 3 /* print short form of queue status */
- X#define REQ_DLONG 4 /* print long form of queue status */
- X#define REQ_REMOVE 5 /* remove jobs */
- X#define REQ_CONTROL 6 /* do control operation */
- X/**************************************************************************
- X * Control file format
- X * First character is kind of entry, remainder of line is
- X * the argument.
- X *
- X * 1 -- "R font file" for troff -ignore
- X * 2 -- "I font file" for troff -ignore
- X * 3 -- "B font file" for troff -ignore
- X * 4 -- "S font file" for troff -ignore
- X * C -- "class name" on banner page
- X * H -- "Host name" of machine where lpr was done
- X * I -- "indent" amount to indent output
- X * J -- "job name" on banner page
- X * L -- "literal" user's name to print on banner
- X * M -- "mail" to user when done printing
- X * N -- "name" of file (used by lpq)
- X * P -- "Person" user's login name
- X * R -- account id for charging
- X * U -- "unlink" name of file to remove after we print it
- X * W -- "width" page width for PR
- X * X -- "header" header title for PR
- X * Z -- xtra options to filters
- X *
- X * Lower case letters are formats
- X * f -- "file name" name of text file to print
- X * l -- "file name" text file with control chars
- X * p -- "file name" text file to print with pr(1)
- X * t -- "file name" troff(1) file to print
- X * n -- "file name" ditroff(1) file to print
- X * d -- "file name" dvi file to print
- X * g -- "file name" plot(1G) file to print
- X * v -- "file name" plain raster file to print
- X * c -- "file name" cifplot file to print
- X *
- X * CFparm is used to hold the upper case parameters
- X */
- extern char CFparm[26][MAXPARMLEN+1];
- X#define CLASSNAME CFparm['C'-'A']
- X#define WHENSP CFparm['D'-'A']
- X#define FROMHOST CFparm['H'-'A']
- X#define INDENT CFparm['I'-'A']
- X#define JOBNAME CFparm['J'-'A']
- X#define BNRNAME CFparm['L'-'A']
- X#define FILENAME CFparm['N'-'A']
- X#define MAILNAME CFparm['M'-'A']
- X#define LOGNAME CFparm['P'-'A']
- X#define ACCNTNAME CFparm['R'-'A']
- X#define NOHEADER CFparm['S'-'A']
- X#define WHENUNSP CFparm['T'-'A']
- X#define UNLNKFILE CFparm['U'-'A']
- X#define PWIDTH CFparm['W'-'A']
- X#define PRTITLE CFparm['X'-'A']
- X#define ZOPTS CFparm['Z'-'A']
- X
- X/*
- X * printjob return codes
- X */
- X#define JBUSY -1 /* being done by other means */
- X#define JFAIL 0 /* repeat with retry */
- X#define JSUCC 1 /* done */
- X#define JABORT 2 /* done, but problems */
- X
- X/*
- X * Mail program
- X */
- X#ifndef MAIL
- X#define MAIL "/usr/lib/sendmail"
- X#endif MAIL
- X
- X/*
- X * File Transfer Protocol Flags
- X */
- X#define CEND 5 /* last file */
- X#define CNAME 4 /* control file */
- X#define DFILE 3 /* data file */
- X#define CFILE 2 /* control file */
- X
- X/*
- X * Local parameters to the spooling system
- X * Defaults for line printer capabilities data base
- X */
- X#define DEFLOGF "log"
- X#define DEFLOCK "lock"
- X#define DEFSTAT "status"
- X#define DEFACCT "acct"
- X#define DEFFORMATS "flp" /* default formats */
- X#define DEFMX 1000
- X#define DEFRETRY 3 /* maximum number of retries */
- X#define DEFMAXCOPIES 0
- X#define DEFFF "\f"
- X#define DEFWIDTH 132
- X#define DEFLENGTH 66
- X#define DAEMON "daemon" /* daemon user id */
- X#define DEFPRICE 20 /* cost in dollars per thousand pages */
- X#define DEFPRIORITY 'Z' /* default priority level */
- X#define DEFPR "/bin/pr" /* default pr program */
- X
- X/*
- X * REAL, not TEST version
- X */
- X
- X/*
- X * path name of files created by lpd.
- X */
- X#define RMASTERLOCK "/usr/spool/lpd/lpd.lock."
- X#define RDEFLPDLOGF "/usr/spool/lpd/lpd.log."
- X#ifdef ETCPC
- X# define RPRINTCAP ETCPC
- X#else
- X# define RPRINTCAP "/usr/spool/lpd/printcap."
- X#endif
- X/*
- X * connection services to be used
- X */
- X#define SERVERNAME "printer"
- X#define SERVERPROT "tcp"
- X/* name of the printer permissions file */
- X#ifdef ETCPERMS
- X# define RPERMFILE ETCPERMS
- X#else
- X# define RPERMFILE "/usr/spool/lpd/printer_perms."
- X#endif
- X/*
- X * The remote client must call from a port in the following range.
- X * This is used for authentication purposes. The ports less than
- X * IPPORT_RESERVED are accessible only to SU processes.
- X */
- X#define RMINPORTNO (IPPORT_RESERVED/2)
- X#define RMAXPORTNO (IPPORT_RESERVED)
- X
- X/*
- X * DEBUG Version, use to avoid screwing up normal operations
- X * path name of files created by lpd.
- X */
- X#define TMASTERLOCK "/tmp/lpd.lock."
- X#define TDEFLPDLOGF "/tmp/lpd.log."
- X#define TPRINTCAP "/tmp/printcap."
- X/*
- X * connection services to be used
- X */
- X#define TSERVICENAME "testlpr"
- X#define TPORTNUM 1600 /* test port number */
- X/* name of the printer permissions file */
- X#define TPERMFILE "/tmp/printer_perms."
- X/*
- X * The remote client must call from a port in the following range.
- X * This is used for authentication purposes. The ports less than
- X * IPPORT_RESERVED are accessible only to SU processes.
- X */
- X#define TMINPORTNO (IPPORT_RESERVED+1)
- X#define TMAXPORTNO (2*IPPORT_RESERVED)
- END_OF_FILE
- if test 23350 -ne `wc -c <'src/lp.h'`; then
- echo shar: \"'src/lp.h'\" unpacked with wrong size!
- fi
- # end of 'src/lp.h'
- fi
- if test -f 'src/utils.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'src/utils.c'\"
- else
- echo shar: Extracting \"'src/utils.c'\" \(25393 characters\)
- sed "s/^X//" >'src/utils.c' <<'END_OF_FILE'
- X/***************************************************************************
- X * U. Minnesota LPD Software * Copyright 1987, 1988, Patrick Powell
- X ***************************************************************************
- X * MODULE: utils.c
- X * Utility routines used by several programs
- X ***************************************************************************
- X * Revision History: Created Sat Jan 9 15:02:12 CST 1988
- X * $Log: utils.c,v $
- X * Revision 3.2 88/06/24 17:55:27 papowell
- X * MODS for VAX 4.3BSD UNIX
- X *
- X * Revision 3.1 88/06/18 09:35:55 papowell
- X * Version 3.0- Distributed Sat Jun 18 1988
- X *
- X * Revision 2.4 88/05/19 10:34:26 papowell
- X * Fixed open() calls to have a 0 parameter, ie: open(f, perms, 0), where needed
- X *
- X * Revision 2.3 88/05/16 12:09:27 papowell
- X * Spelling mistake in error messages
- X *
- X * Revision 2.2 88/05/14 10:18:31 papowell
- X * Use long format for job file names;
- X * Added 'fd', no forward flag;
- X * Control file has to have hostname and origination agree.
- X *
- X * Revision 2.1 88/05/09 10:10:42 papowell
- X * PLP: Released Version
- X *
- X * Revision 1.7 88/04/27 20:27:34 papowell
- X * Modified to remove unused variables
- X *
- X * Revision 1.6 88/04/15 13:06:55 papowell
- X * Std_environ() call added, to ensure that fd 0 (stdin), 1 (stdout), 2(stderr)
- X * have valid file descriptors; if not open, then /dev/null is used.
- X *
- X * Revision 1.5 88/03/25 15:01:57 papowell
- X * Debugged Version:
- X * 1. Added the PLP control file first transfer
- X * 2. Checks for MX during file transfers
- X * 3. Found and fixed a mysterious bug involving the SYSLOG facilities;
- X * apparently they open files and then assume that they will stay
- X * open.
- X * 4. Made sure that stdin, stdout, stderr was available at all times.
- X *
- X * Revision 1.4 88/03/12 10:03:45 papowell
- X * *** empty log message ***
- X *
- X * Revision 1.3 88/03/11 19:29:25 papowell
- X * Minor Changes, Updates
- X *
- X * Revision 1.2 88/03/05 15:01:28 papowell
- X * Minor Corrections, Lint Problems
- X *
- X * Revision 1.1 88/03/01 11:09:27 papowell
- X * Initial revision
- X *
- X ***************************************************************************/
- X#ifndef lint
- static char id_str1[] =
- X "$Header: utils.c,v 3.2 88/06/24 17:55:27 papowell Exp $ PLP Copyright 1988 Patrick Powell";
- X#endif lint
- X
- X#include "lp.h"
- X/*
- X * Time_str: return ctime() value, but without terminating '\n'
- X */
- char *
- Time_str()
- X{
- X time_t tvec; /* time */
- X char *ctime();
- X static char s[40];
- X
- X (void)time(&tvec);
- X (void)strcpy(s,ctime(&tvec));
- X s[strlen(s)-1] = 0;
- X return( s );
- X}
- X
- X/***************************************************************************
- X * Remove_job( FILE *fp; struct queue *q )
- X * Remove a job and all associated files; if success == JSUCC, remove
- X * U links as well
- X * ACTIONS:
- X * 1. Read the control file
- X * 2. get data file names and unlink them if they match the job
- X * 3. Unlink the control file
- X ***************************************************************************/
- X
- Remove_job( fp, q )
- X FILE *fp;
- X struct queue *q;
- X{
- X char parm[BUFSIZ]; /* line buffer */
- X char *arg; /* pointer to the argument */
- X int c; /* ACME Integers, Inc. */
- X
- X if(Debug>5)log(XLOG_DEBUG,"Remove_job: %s", q->q_name );
- X clearerr( fp );
- X if( fseek( fp, 0L, 0 ) < 0 ){
- X logerr_die( XLOG_INFO,
- X "Remove_job: fseek failed (%s)", q->q_name );
- X } else {
- X /*
- X * read through the file, looking for things to remove
- X */
- X while(fgets( parm, sizeof(parm), fp )){
- X if( (arg = index(parm, '\n')) == 0 ){
- X log( XLOG_INFO, "Remove_job: file bad (%s), no endline",
- X q->q_name);
- X continue;
- X }
- X *arg = 0;
- X arg = parm+1;
- X c = parm[0];
- X /*
- X * is it a format line?
- X */
- X if( !isascii( c ) || !islower( c ) ){
- X continue;
- X }
- X if( Job_match( q->q_name, arg ) == 0){
- X if(Debug>4)log(XLOG_DEBUG,"Remove_job: bad file name '%s'",
- X arg );
- X continue;
- X }
- X (void)unlink_daemon( arg );
- X }
- X }
- X if( unlink_daemon( q->q_name ) < 0 ){
- X logerr( XLOG_INFO, "Remove_job: cannot unlink %s", q->q_name );
- X }
- X}
- X/***************************************************************************
- X * int Getq();
- X * Scan the spool directory and make a list of server files sorted by
- X * priority, creation time, etc.
- X * Returns: the number of entries
- X * Side Effects: sets struct queue *Queue to point to an array of pointers
- X * to queue entries
- X ***************************************************************************/
- static int arraysz; /* number of entries in array */
- static struct queue qb; /* for zeroing purposes */
- X
- Getq()
- X{
- X struct direct *d; /* directory entry */
- X int nitems; /* ACME Integers, Inc. */
- X struct stat stbuf; /* for statting files */
- X int compar(); /* for sorting files */
- X DIR *dirp; /* used by directory routines */
- X char l[BUFSIZ]; /* for reading the control file */
- X char fullname[BUFSIZ]; /* for the full pathname */
- X char *filepart; /* end of the pathname */
- X FILE *cfp; /* control file FP */
- X struct queue *q; /* pointer to queue entry */
- X char *bp, *ep; /* ACME Pointers, Inc. */
- X
- X if (SD == 0 || *SD == 0 ){
- X fatal( XLOG_INFO, "no directory entry" );
- X }
- X if ((dirp = opendir(SD)) == NULL){
- X logerr_die( XLOG_INFO, "cannot open spool directory %s", SD );
- X }
- X
- X /*
- X * get the directory name and copy to buffer
- X */
- X if( strlen(SD) + sizeof(q->q_name) + 2 > sizeof(fullname) ){
- X logerr_die( XLOG_NOTICE,"INTERNAL: Getq, file name too big" );
- X }
- X (void)strcpy(fullname,SD);
- X filepart = &fullname[strlen(fullname)];
- X *filepart++ = '/';
- X /*
- X * assume you have 100 entries to start with
- X */
- X if( arraysz == 0 ){
- X arraysz = 100;
- X Queue = (struct queue *)malloc(
- X (unsigned)(arraysz * sizeof(struct queue)));
- X if (Queue == NULL){
- X logerr_die( XLOG_INFO, "Getq: malloc failed" );
- X }
- X }
- X /*
- X * set the item count to 0 and scan the directory
- X */
- X nitems = 0;
- X while ((d = readdir(dirp)) != NULL) {
- X if(Debug>5)log(XLOG_DEBUG,"Getq: file %s", d->d_name );
- X
- X if (d->d_name[0] != 'c' || d->d_name[1] != 'f'){
- X continue; /* server control files only */
- X }
- X /*
- X * Check to make sure the array has space left and
- X * realloc the maximum size.
- X */
- X if( nitems >= arraysz ){
- X /* try to get another buffer */
- X arraysz = arraysz + 20;
- X Queue = (struct queue *)realloc((char *)Queue,
- X (unsigned)((arraysz)*sizeof(struct queue)));
- X if (Queue == NULL){
- X logerr_die(XLOG_NOTICE,"malloc failed in Getq" );
- X }
- X }
- X /*
- X * get next queue entry and clear it
- X */
- X q = &Queue[nitems];
- X *q = qb; /* zero it out the easy way */
- X
- X if(Debug>5)log(XLOG_DEBUG,"Getq: control file %s", d->d_name );
- X
- X /* copy the name of the file */
- X if( strlen( d->d_name ) >= CFNAMELEN){
- X logerr_die(XLOG_NOTICE,"control file name %s too long", d->d_name );
- X }
- X (void)strcpy(q->q_name, d->d_name);
- X (void)strcpy(filepart,d->d_name);
- X if (stat(fullname, &stbuf) < 0){
- X continue; /* Doesn't exist */
- X }
- X /* get the modification time */
- X q->q_time = stbuf.st_mtime;
- X /* set a priority */
- X q->q_priority = d->d_name[2];
- X /* get the job number */
- X q->q_num = atoi( &d->d_name[3] );
- X
- X /*
- X * now we open the control file and read the information
- X */
- X if( (cfp = fopen_daemon( fullname, "r" )) == NULL ){
- X /* it disappeared */
- X continue;
- X }
- X if(Debug>5)log(XLOG_DEBUG,"Getq: control file %s readable", d->d_name );
- X bp = q->q_data;
- X ep = bp + sizeof(q->q_data);
- X while( fgets( l, sizeof(l), cfp) ){
- X /* clobber the \n */
- X l[strlen(l)-1] = 0;
- X if( islower( l[0] ) ){
- X /* get size of file to be printed */
- X (void)strcpy(filepart, &l[1] );
- X if( stat( fullname, &stbuf) < 0){
- X (void)fclose(cfp);
- X if(Debug>5)log(XLOG_DEBUG,
- X "Getq: data file %s does not exist", l );
- X } else {
- X q->q_size += stbuf.st_size;
- X }
- X } else switch( l[0] ){
- X case 'N': /* name of file */
- X bp = estrcp( bp, &l[1], ep );
- X bp = estrcp( bp, " ", ep );
- X break;
- X case 'P': /* name of user */
- X (void)strncpy( q->q_user, &l[1], sizeof(q->q_user)-1);
- X break;
- X case 'D': /* when spooled */
- X q->q_sp = (time_t)atol( &l[1] );
- X break;
- X case 'T': /* when to be unspooled */
- X q->q_unsp = (time_t)atol( &l[1] );
- X break;
- X default: break;
- X }
- X }
- X if(Debug>5)log(XLOG_DEBUG,"Getq: control file %s is ok", d->d_name );
- X
- X (void)fclose(cfp);
- X ++nitems;
- X }
- X closedir(dirp);
- X
- X /*
- X * sort the queue
- X */
- X if (nitems){
- X qsort((char *)Queue, nitems, sizeof(struct queue), compar);
- X }
- X return(nitems);
- X}
- X
- X
- X/*
- X * Compare queue entries by
- X * 1. Priority
- X * 2. Time
- X */
- static
- compar(c1, c2)
- X char *c1, *c2;
- X{
- X struct queue *p1, *p2;
- X
- X p1 = (struct queue *)c1;
- X p2 = (struct queue *)c2;
- X if ((p1)->q_priority < (p2)->q_priority)
- X return(-1);
- X if ((p1)->q_priority > (p2)->q_priority)
- X return(1);
- X if ((p1)->q_time < (p2)->q_time)
- X return(-1);
- X if ((p1)->q_time > (p2)->q_time)
- X return(1);
- X return(0);
- X}
- X
- X/***************************************************************************
- X * Match_entry( struct queue *q )
- X * check the user name and job number against the parmlist starting at start;
- X * Return: 1 if match found, 0 otherwise
- X ***************************************************************************/
- int
- Match_entry( q )
- X struct queue *q;
- X{
- X int i; /* ACME Integer, Inc. */
- X
- X if(Debug>4)log(XLOG_DEBUG,"Match_entry on %s, %d", q->q_user, q->q_num );
- X for( i = 0; i < Parmcount; ++i ){
- X if( (Parms[i].num >= 0 && Parms[i].num == q->q_num)
- X || strcmp( Parms[i].str, q->q_user ) == 0 ){
- X return(1);
- X }
- X }
- X return(0);
- X}
- X
- X/***************************************************************************
- X * bpread( int fd ; char *buf; int size )
- X * Almost bombproof way to read command line from socket
- X * Returns: -1 if unable to read a line terminated with \n
- X * 0 if 0 length line or first character is null (i.e.- no input)
- X * otherwise: length of line
- X ***************************************************************************/
- bpread( fd, buf, size )
- X int fd;
- X char *buf;
- X int size;
- X{
- X int n; /* ACME Integer, Inc. */
- X int i;
- X
- X /*
- X * Bombproof line reading
- X */
- X for( i = 0; i < size; ++i ){
- X n = read(fd, &buf[i], 1);
- X if( n < 0 ){
- X logerr(XLOG_INFO,"bpread: lost connection");
- X return( -1 );
- X } else if( n == 0 ){
- X log(XLOG_INFO,"bpread: bad format %s", buf );
- X return( 0 );
- X }
- X if( buf[i] == '\n' ){
- X buf[i] = 0;
- X if(Debug>3)log(XLOG_DEBUG,"bpread: '%d' %s", buf[0], &buf[1]);
- X return( i );
- X } else if( buf[i] == 0 && i == 0 ){
- X if(Debug>3)log(XLOG_DEBUG,"bpread: zero byte first");
- X return( i );
- X }
- X }
- X log(XLOG_INFO,"bpread: bad line %s", buf );
- X return( -1 );
- X}
- X/***************************************************************************
- X * estrcp(char *s, *t, *e)
- X * copies t to s, and returns the end position
- X * Returns: end of string if the result is shorter than e, NULL otherwise
- X * Note: this is a very useful routine. Think about adding it to string
- X * functions.
- X ***************************************************************************/
- char *
- estrcp( s,t,e )
- X char *s, *t, *e;
- X{
- X if( s ){
- X while( (*s++ = *t++) && (s < e) );
- X if( s < e ){
- X return( s-1 );
- X } else {
- X return( (char *)0 );
- X }
- X }
- X return( s );
- X}
- X/***************************************************************************
- X * splitline( char *line )
- X * splits a line into tokens, and places them in the Parms[] array.
- X * if firstarg is present then it is set to the first argument
- X * Side Effects: modifies Parms, Parmcount
- X ***************************************************************************/
- X
- splitline( bp )
- X char *bp;
- X{
- X /* find the start */
- X while (*bp) {
- X while( *bp && isspace(*bp))
- X bp++;
- X if( *bp ){
- X if( Parmcount >= MAXPARMS ){
- X fatal(XLOG_INFO,"splitline: too many requests");
- X }
- X Parms[Parmcount].str = bp;
- X if (isdigit(*bp)) {
- X Parms[Parmcount].num = atoi(bp);
- X } else {
- X Parms[Parmcount].num = -1;
- X }
- X Parmcount++;
- X }
- X while( *bp && !isspace(*bp))
- X bp++;
- X if( *bp )
- X *bp++ = 0;
- X }
- X}
- X/**********************************************************************
- X * Shift_parms( int n )
- X * left shift the entries in the Parms[] array by n
- X * Side Effects: modifies Parms and Parmcount
- X **********************************************************************/
- Shift_parms( n )
- X int n;
- X{
- X int i; /* ACME Chain and Integer, Inc. */
- X while( Parmcount > 0 && n > 0 ){
- X for( i = 1; i < Parmcount; ++i ){
- X Parms[i-1] = Parms[i];
- X }
- X --Parmcount;
- X --n;
- X }
- X}
- X
- printstatus()
- X{
- X if( ST && *ST ){
- X if(Debug>4)log(XLOG_DEBUG,"printstatus: ST %s", ST );
- X pr_stat_file( ST );
- X }
- X if( PS && *PS ){
- X if(Debug>4)log(XLOG_DEBUG,"printstatus: PS %s", PS );
- X pr_stat_file( PS );
- X }
- X}
- X
- pr_stat_file( file )
- X char *file;
- X{
- X FILE *fp;
- X char buf[BUFSIZ];
- X
- X if( (fp = fopen_daemon( file, "r" )) != NULL ){
- X while( fgets( buf, sizeof(buf), fp) != NULL ){
- X (void)fprintf(stdout, " %s", buf );
- X }
- X (void)fflush(stdout);
- X (void)fclose( fp );
- X }
- X}
- X/***************************************************************************
- X * char *Sigstr(n)
- X * Return a printable form the the signal
- X ***************************************************************************/
- X
- struct signame{
- X char *str;
- X int value;
- X} signals[] = {
- X{ "SIGHUP", SIGHUP }, { "SIGINT", SIGINT }, { "SIGQUIT", SIGQUIT },
- X{ "SIGILL", SIGILL }, { "SIGTRAP", SIGTRAP }, { "SIGIOT", SIGIOT },
- X{ "SIGEMT", SIGEMT }, { "SIGFPE", SIGFPE }, { "SIGKILL", SIGKILL },
- X{ "SIGBUS", SIGBUS }, { "SIGSEGV", SIGSEGV }, { "SIGSYS", SIGSYS },
- X{ "SIGPIPE", SIGPIPE }, { "SIGALRM", SIGALRM }, { "SIGTERM", SIGTERM },
- X{ "SIGURG", SIGURG }, { "SIGSTOP", SIGSTOP }, { "SIGTSTP", SIGTSTP },
- X{ "SIGCONT", SIGCONT }, { "SIGCHLD", SIGCHLD }, { "SIGTTIN", SIGTTIN },
- X{ "SIGTTOU", SIGTTOU }, { "SIGIO", SIGIO }, { "SIGXCPU", SIGXCPU },
- X{ "SIGXFSZ", SIGXFSZ }, { "SIGVTALRM", SIGVTALRM }, { "SIGPROF", SIGPROF } };
- int nsignals = sizeof( signals )/ sizeof( struct signame );
- char *
- Sigstr( n )
- X int n;
- X{
- X int i;
- X static char buf[40];
- X
- X for( i = 0; i < nsignals; ++i ){
- X if( signals[i].value == n ){
- X return( signals[i].str );
- X }
- X }
- X (void)sprintf(buf,"unknown signal (%d)", n );
- X return( buf );
- X}
- X/***************************************************************************
- X * Decode_status( union wait *status )
- X * returns a printable string encoding return status
- X ***************************************************************************/
- X
- char *
- Decode_status( status )
- X union wait *status;
- X{
- X static char msg[BUFSIZ];
- X
- X (void)sprintf( msg, "user: %d, system: %d%s",
- X status->w_retcode, status->w_termsig,
- X status->w_coredump ? ", core dump, " : ", " );
- X if( status->w_termsig ){
- X (void)sprintf(msg+strlen(msg),"error- %s",
- X Sigstr((int)status->w_termsig));
- X }
- X return( msg );
- X}
- X
- X/*
- X * Checkactive()
- X * find the currently active files in the spool queue.
- X * 1. check for the single server possibility first.
- X * 2. find the Names of the servers
- X * 3. find the active files for each of the servers
- X */
- X
- int
- Checkactive()
- X{
- X int i; /* ACME Integers, Inc. */
- X char buf[BUFSIZ]; /* Name of active file */
- X static char server[BUFSIZ]; /* Name of server file */
- X char *sp, *ep; /* ACME Pointer */
- X int pid;
- X
- X pid = 0;
- X buf[0] = 0;
- X if(Checklockfile(LO,&pid,buf,sizeof(buf),&LO_statb) && buf[0] ){
- X for( i = 0; i < Jobcount; ++i ){
- X if( strcmp( buf, Queue[i].q_name ) == 0 ){
- X Queue[i].q_daemon = pid;
- X Queue[i].q_server = Printer;
- X } else {
- X Queue[i].q_daemon = 0;
- X Queue[i].q_server = 0;
- X }
- X }
- X }
- X /*
- X * check for each of the servers
- X */
- X if( SV && *SV ){
- X (void)strcpy( server, SV );
- X for( sp = server; sp; sp = ep ){
- X if( ep = index( sp, ',' ) ){
- X *ep = 0;
- X ++ep;
- X }
- X /*
- X * get the lock file and the status from the server
- X */
- X buf[0] = 0;
- X if(Checklockfile(sp,&pid,buf,sizeof(buf),(struct stat *)0)
- X && buf[0] ){
- X for( i = 0; i < Jobcount; ++i ){
- X if( strcmp( buf, Queue[i].q_name ) == 0 ){
- X Queue[i].q_daemon = pid;
- X Queue[i].q_server = sp;
- X } else {
- X Queue[i].q_daemon = 0;
- X Queue[i].q_server = 0;
- X }
- X }
- X }
- X }
- X }
- X return(pid);
- X}
- X
- X
- X/***************************************************************************
- X * Get_Daemon()
- X * Get the DAEMON uid and gid
- X * Assume password entry has both values set for the user daemon
- X ***************************************************************************/
- Get_Daemon()
- X{
- X struct passwd *passwd, *getpwnam();
- X if( Daemon_uid == 0 ){
- X if( (passwd = getpwnam(DAEMON)) == 0 ){
- X logerr_die( XLOG_INFO,"Get_Daemon: getpwnam(%s) failed", DAEMON );
- X }
- X Daemon_uid = passwd->pw_uid;
- X Daemon_gid = passwd->pw_gid;
- X if(Debug>4)log(XLOG_INFO,"Get_Daemon: uid=%d, gid=%d",
- X Daemon_uid, Daemon_gid);
- X }
- X}
- X
- X/***************************************************************************
- X * Job_match( char *control, *data)
- X * Check to see if the control and data file names are matching
- X * 1. data file must start with "df"
- X * 2. next must be letter
- X * 3. next must be 3 digit sequence number
- X * 4. control and data file sequence number must match
- X * return 1 if OK, 0 if not
- X ***************************************************************************/
- X
- Job_match( control, data )
- X char *control;
- X char *data;
- X{
- X int c, i, j; /* ACME Chain and Integers, Inc. */
- X
- X i = strlen( data );
- X for( j = 0; j < i ; ++j ){
- X c = data[j];
- X if( !isascii( c ) || !isprint( c ) ){
- X log(XLOG_INFO, "Job_match: bad char in '%s'", data );
- X return( 0 );
- X }
- X }
- X if( index( data, '/' ) ){
- X /*
- X * tried to embed a / in the file name
- X */
- X log(XLOG_INFO, "Job_match: / present '%s'", data );
- X return( 0 );
- X }
- X if( i > CFNAMELEN
- X || i <= STARTFR
- X || i != strlen( control )
- X || index( "cd", data[0] ) == 0
- X || (data[1] != 'f')
- X || !isalpha( data[STARTPR] )
- X || strcmp( control+STARTID, data+STARTID ) ){
- X log(XLOG_INFO, "Job_match: bad match control '%s', data '%s'",
- X control, data );
- X return( 0 );
- X }
- X for( j = 0; j < IDLEN; ++ j ){
- X if( !isdigit( data[j+STARTID] ) ){
- X log(XLOG_INFO, "Job_match: bad sequence control '%s', data '%s'",
- X control, data );
- X return( 0 );
- X }
- X }
- X if(Debug>5)log(XLOG_DEBUG,"Job_match: OK control '%s', data '%s'",
- X control, data );
- X return( 1 );
- X}
- X
- X/***************************************************************************
- X * Std_environ()
- X * Make sure that fd 0, 1, 2 exist by opening /dev/null for them if they
- X * have not been provided.
- X * Set up the Host information as well
- X ***************************************************************************/
- X
- Std_environ()
- X{
- X int fd;
- X struct hostent *host_ent; /* host entry from data base */
- X
- X /*
- X * close all file descriptors up to NOFILE
- X */
- X for (fd = 3; fd < NOFILE; fd++){
- X (void) close(fd);
- X }
- X while( (fd = open( "/dev/null", O_RDWR, 0 )) >= 0 && fd < 3 );
- X if( fd < 0 ){
- X logerr_die( XLOG_CRIT, "Std_environ: cannot open /dev/null" );
- X } else {
- X (void)close(fd);
- X }
- X /*
- X * get the Host computer Name
- X */
- X if( gethostname(Host, sizeof(Host)) < 0 ){
- X logerr_die( XLOG_INFO, "Std_environ: gethostname failed" );
- X }
- X host_ent = gethostbyname( Host );
- X if( host_ent == 0 ){
- X fatal( XLOG_INFO, "Std_environ: host entry for '%' not found", Host );
- X }
- X if( strlen( host_ent->h_name ) > sizeof( Host ) ){
- X fatal( XLOG_INFO, "Std_enviorn: host name is too long: '%s'",
- X host_ent->h_name);
- X }
- X (void)strcpy(Host, host_ent->h_name );
- X /*
- X * Get Daemon UID
- X */
- X Get_Daemon();
- X}
- X
- X/***************************************************************************
- X * int open_daemon()
- X * FILE *fopen_daemon()
- X * int unlink_daemon()
- X * Do the above actions as DAEMON.
- X * Note that this is very difficult to do, and ensure that all the error
- X * conditions are met. What you want to do is perform the following as
- X * an uninterrupted critical section.
- X * 1. setreuid( root, daemon)
- X * 2. perform the action
- X * 3. setreuid( whatever, root )
- X * This will only work if
- X * 1. you are really root
- X * 2. you do not ever get interrupts
- X ***************************************************************************/
- static uid_t ruid, euid; /* real and effective UIDs */
- static int uid_parm; /* must be able to hold -1 */
- static int omask; /* block these signals */
- X
- X
- void
- Set_uid( new_uid )
- X int new_uid;
- X{
- X /*
- X * get the DAEMON UID, GID
- X */
- X omask = sigblock(sigmask(SIGCHLD)|sigmask(SIGHUP)
- X |sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGTERM));
- X ruid = getuid();
- X euid = geteuid();
- X
- X# ifdef SETREUID4BSD
- X uid_parm = euid;
- X# else
- X uid_parm = -1;
- X# endif SETREUID4BSD
- X /*
- X * check to see if we are running without SUID
- X */
- X if( euid && euid != getuid() && euid != new_uid ){
- X log( XLOG_INFO, "Set_uid: euid %d, ruid %d, bad SUID?",
- X euid, getuid() );
- X /*
- X * NOTE: do not try and take normal exit!!!
- X */
- X exit(1);
- X } else if( euid == 0 && setreuid( uid_parm, new_uid ) < 0 ){
- X logerr( XLOG_INFO, "Set_uid: setreuid( %d, %d) failed",
- X uid_parm, new_uid );
- X exit(1);
- X }
- X if(Debug>4)log(XLOG_DEBUG,"Set_uid: uid_parm %d, uid %d, euid %d",
- X uid_parm, getuid(), geteuid());
- X}
- X/*
- X * set the UID to DAEMON
- X */
- void
- Set_daemon()
- X{
- X /*
- X * get the DAEMON UID, GID
- X */
- X Get_Daemon();
- X Set_uid( Daemon_uid );
- X}
- X/*
- X * set UID back to normal. Note that there are two versions of setreuid
- X * available. The VAX 4.2/4.3 version allows you to swap RUID/EUID
- X * and will allow you only to set your UID if you are EUID root.
- X * The SUN 3.X and others will allow you ONE call to the SUID function,
- X * and will allow you to set the UID back to the original. The
- X * uid_parm flag determines which strategy to use.
- X * If uid_parm is -1, then you have to use setreuid( -1, euid )
- X * If it is not, then we have to swap the EUID/UID, then set
- X * the UID and EUID explicitly
- X */
- void
- Clear_uid()
- X{
- X /*
- X * handle the easy one first: set euid back to original
- X */
- X if( uid_parm == -1 ){
- X if( setreuid( -1, euid ) < 0 ){
- X logerr( XLOG_INFO,
- X "Clear_uid: setreuid( %d, %d) from %d, %d failed",
- X -1, euid, getuid(), geteuid() );
- X /*
- X * avoid problems, exit early
- X */
- X exit(1);
- X }
- X (void)sigsetmask(omask);
- X return;
- X }
- X /*
- X * otherwise we swap the UID and EUID, but first make sure that it is
- X * consistent; uid should be the old (original) euid on entry to set_uid
- X */
- X if( getuid() != euid ){
- X logerr( XLOG_INFO,
- X "Clear_uid: uid is %d, euid is %d, and uid should be %d",
- X getuid(), geteuid(), euid );
- X exit(1);
- X }
- X /*
- X * swap the RUID and EUID
- X */
- X if( setreuid( geteuid(), getuid() ) < 0 ){
- X logerr( XLOG_INFO,
- X "Clear_uid: setreuid( %d, %d) from %d, %d failed",
- X geteuid(), getuid(), getuid(), geteuid() );
- X /*
- X * avoid problems, exit early
- X */
- X exit(1);
- X }
- X /*
- X * Set the RUID and EUID explicitly
- X */
- X if( setreuid( ruid, euid ) < 0 ){
- X logerr( XLOG_INFO,
- X "Clear_uid: setreuid( %d, %d) from %d, %d failed",
- X ruid, euid, getuid(), geteuid() );
- X /*
- X * avoid problems, exit early
- X */
- X exit(1);
- X }
- X (void)sigsetmask(omask);
- X}
- X
- X/*
- X * Open a file as daemon.
- X */
- int
- open_daemon( name, flag, perms )
- X char *name;
- X int flag;
- X int perms;
- X{
- X int fd, err;
- X /*
- X * establish UID
- X */
- X Set_daemon();
- X /*
- X * now for the plunge into the unknown
- X */
- X fd = open( name, flag, perms );
- X err = errno;
- X Clear_uid();
- X errno = err;
- X return( fd );
- X}
- X
- X/*
- X * fopen a file; the file has been created, and we want to do this as
- X * daemon for permissions reasons.
- X */
- XFILE *
- fopen_daemon( name, how )
- X char *name;
- X char *how;
- X{
- X int err;
- X FILE *fp;
- X /*
- X * establish UID
- X */
- X Set_daemon();
- X /*
- X * now for the plunge into the unknown
- X * NOTE: we are assuming that we only use this to READ a file already
- X * created.
- X */
- X fp = fopen( name, how );
- X err = errno;
- X /*
- X * done with the daemon stuff
- X */
- X Clear_uid();
- X errno = err;
- X return( fp );
- X}
- X
- X/*
- X * UNLINK a file as DAEMON
- X */
- unlink_daemon( name )
- X char *name;
- X{
- X int f, err;
- X /*
- X * establish UID
- X */
- X Set_daemon();
- X /*
- X * now for the plunge into the unknown
- X */
- X f = unlink( name );
- X err = errno;
- X /*
- X * done with the daemon stuff
- X */
- X Clear_uid();
- X errno = err;
- X return( f );
- X}
- X
- X
- X/*
- X * CHMOD a file as DAEMON
- X */
- chmod_daemon( name, perms )
- X char *name;
- X int perms;
- X{
- X int f, err;
- X /*
- X * establish UID
- X */
- X Set_daemon();
- X /*
- X * now for the plunge into the unknown
- X */
- X f = chmod( name, perms );
- X err = errno;
- X /*
- X * done with the daemon stuff
- X */
- X Clear_uid();
- X errno = err;
- X return( f );
- X}
- X
- X/***************************************************************************
- X * Rename_cf( char *tf )
- X * rename the temporary file to a control file
- X ***************************************************************************/
- X
- Rename_cf( tf )
- X char *tf;
- X{
- X char from[MAXPATHLEN+1];
- X char to[MAXPATHLEN+1];
- X int i, err;
- X
- X (void)sprintf( from, "%s/%s", SD, tf );
- X (void)sprintf( to, "%s/c%s", SD, tf+1 );
- X if(Debug>4)log(XLOG_DEBUG,"Rename_cf: from '%s' to '%s'",from, to);
- X Set_daemon();
- X i = rename( from, to );
- X err = errno;
- X Clear_uid();
- X errno = err;
- X if( i < 0 ){
- X logerr_die(XLOG_INFO,"Rename_cf: rename '%s' to '%s' failed",from, to);
- X }
- X}
- X
- X/***************************************************************************
- X * Tailor_names()
- X * Appends the Host information to several file names.
- X ***************************************************************************/
- static
- append_name( s, t )
- X char *s, *t;
- X{
- X if( (strlen(s) + strlen(t) + 2) > MAXPATHLEN ){
- X fatal( XLOG_INFO,"append_name: names too long 's' + 't'", s, t);
- X }
- X (void)strcat( s, t);
- X}
- Tailor_names()
- X{
- X append_name( Lpdlogf, Host );
- X append_name( Masterlock, Host );
- X append_name( Permfile, Host );
- X append_name( Printcap, Host );
- X}
- END_OF_FILE
- if test 25393 -ne `wc -c <'src/utils.c'`; then
- echo shar: \"'src/utils.c'\" unpacked with wrong size!
- fi
- # end of 'src/utils.c'
- fi
- echo shar: End of archive 15 \(of 16\).
- cp /dev/null ark15isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 16 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-