RJE print spool manager -- Part1

Art Neilson art at pilikia.pegasus.com
Tue Feb 19 13:02:40 AEST 1991


This is the second part of my RJE print spool manager.  It is written
for SNA RJE on the NCR Tower platform, running NCR's SNA RJE V product.
This application is targeted at the end user, and allows him to easily
maintain large numbers of files received on the RJE logical print device.
The included shar file below contains all the source needed to build the
program, cut at the line and save.

-----8<----- cut here -----8<----- cut here -----8<----- cut here -----8<-----
#! /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 1 (of 1)."
# Contents:  MANIFEST Makefile README funcs.c job.c main.c main.h
#   mass.c node.c node.h support.c tag.c
# Wrapped by art at pilikia on Mon Feb 18 15:57:50 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(785 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
X   File Name		Archive #	Description
X-----------------------------------------------------------
X MANIFEST                   1	This shipping manifest
X Makefile                   1	Makefile to build the program
X README                     1	Installation and other information
X funcs.c                    1	Functions for single operations
X job.c                      1	Functions for retrieving job info
X main.c                     1	Main program logic
X main.h                     1	Header needed by everyone
X mass.c                     1	Functions for mass operations
X node.c                     1	Node handling functions
X node.h                     1	Header describes the node
X support.c                  1	Support functions
X tag.c                      1	Functions for node tag handling
END_OF_FILE
if test 785 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1301 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
X# @(#)Makefile - makefile for rje print spool manager 02-07-91
X# Arthur W. Neilson III
X# art at bohtsg.pegasus.com
X
XSHELL = /bin/sh
X
X# your c compiler, gcc maybe ?
XCC = cc
X
X# where shall we install ?
XBINDIR = /usr/local/bin
X
X# directory routine library ?
XDIRLIB = #-ldir
X
X# HASVOID  define this if your compiler understands the void type
X# SIGVOID  define this if your signal() returns void
X# LPR      define this if your print spooler is lpr 
X# SYSERR   define this if your errno.h doesn't declare sys_errlist
XDEFS = -DHASVOID -DSIGVOID -DSYSERR
X
XCFLAGS = -O $(DEFS)
XLIBES  = -lcurses $(DIRLIB)
X
XHFILES = main.h node.h
XCFILES = main.c node.c funcs.c mass.c tag.c support.c job.c
XOFILES = main.o node.o funcs.o mass.o tag.o support.o job.o
X
Xall: splmgr
X
Xsplmgr: $(OFILES)
X	$(CC) $(CFLAGS) -o $@ $(OFILES) $(LIBES)
X	strip $@
X	mcs -d $@
X	chmod u+s $@
X
X	rm -f splmgr *.o *.BAK tags MANIFEST Part* core
X
X	@for f in $(CFILES); do \
X		echo "\tformatting $$f"; \
X		indent $$f; \
X	done
X
X	ctags $(HFILES) $(CFILES)
X
X	tar cvf splmgr.tar Makefile $(CFILES) $(HFILES)
X
X	makekit -m
X
X# dependency rules
Xmain.o:		main.c $(HFILES)
Xnode.o:		node.c $(HFILES)
Xfuncs.o:	funcs.c $(HFILES)
Xmass.o:		mass.c $(HFILES)
Xtag.o:		tag.c $(HFILES)
Xsupport.o:	support.c $(HFILES)
Xjob.o:		job.c $(HFILES)
END_OF_FILE
if test 1301 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(1699 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
X	splmgr - SNA RJE print spool manager
X
X	This is a interactive utility for SNA RJE print spool management.
X	It presents print files in list format to the user, displaying
X	pertinent information about the file such as jobname, date, time,
X	line count, etc.  The user may perform a variety of functions
X	on the file such as print, view and delete.  Additionally, many
X	of these singular operations may be done en masse on "tagged" or
X	"untagged" files.
X
X	Currently this distribution supports SNA RJE print files,
X	I have diffs for BSC RJE if anyone wants them.  The JES2
X	job information retrieved from the 1st banner line with each
X	print file may vary between IBM hosts.  Hack as you see fit.
X
X	This software was developed and tested on an NCR Tower 32/650
X	running OS 3.00.01 (SYS5R3).  If you are running on OS 2.xx 
X	(SYS5R2) you will need to get Doug Gwyn's portable directory
X	routines (opendir, closedir et al) and install them prior to
X	building this application.
X
X	Currently this distribution supports SNA RJE print files,
X	I have diffs for BSC RJE if anyone wants them.  The JES2
X	job information retrieved from the 1st banner line with each
X	print file may vary between IBM hosts.  Hack as you see fit.
X
X	The program is built thru the provided Makefile, edit it to
X	fit your needs and just 'make'.  The program runs setuid to
X	root, and does a chdir to the directory where your print files
X	live.  RJE print files are normally owned by srje and users
X	therefore delete them, hence the need for setuid permissions.
X	If you don't have root permissions on your system, request
X	your administrator to install this program.
X
X	Arthur W. Neilson III
X	art@{bohtsg|pilikia}.pegasus.com
X	Feb 7, 1991
END_OF_FILE
if test 1699 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'funcs.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'funcs.c'\"
else
echo shar: Extracting \"'funcs.c'\" \(646 characters\)
sed "s/^X//" >'funcs.c' <<'END_OF_FILE'
X/*
X**	f u n c s . c
X**
X**	functions for performing single operations
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1990
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X/*
X**	d e l
X**
X**	delete file
X**
X*/
XNode   *
Xdel(node)
XNode   *node;
X{
X	if (access(node->name, W_OK) == 0)
X		if (execute(RM, RM, "-f", node->name, NULL) == 0) {
X			if (--total == 0)
X				quit(1);
X			bytes -= node->st->st_size;
X			if (node == tail)
X				tail = node->prev;
X			node = rmnode(node);
X		}
X	return (node);
X}
X
X/*
X**	p r i n t
X**
X**	print a file
X**
X*/
XVOID
Xlp(name)
Xchar   *name;
X{
X	if (access(name, R_OK) == 0) {
X		execute(LP, LP, LPOPTS, name, NULL);
X	}
X}
END_OF_FILE
if test 646 -ne `wc -c <'funcs.c'`; then
    echo shar: \"'funcs.c'\" unpacked with wrong size!
fi
# end of 'funcs.c'
fi
if test -f 'job.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'job.c'\"
else
echo shar: Extracting \"'job.c'\" \(1127 characters\)
sed "s/^X//" >'job.c' <<'END_OF_FILE'
X/*
X**	j o b . c
X**
X**	functions for retrieving job information
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X#define MAXLINE		133
X
XVOID
Xjobinfo(name, job)
Xchar   *name;
XJob    *job;
X{
X	FILE   *fp;
X	char   *getfield(), *ptr;
X	char    buf[MAXLINE];
X	int     i;
X
X	/* open print file */
X	if ((fp = fopen(name, "r")) == NULL)
X		return;
X
X	/* retrieve first banner line */
X	if (fread(buf, sizeof(buf), 1, fp) < 1) {
X		fclose(fp);
X		return;
X	}
X	fclose(fp);
X
X	/* skip fields 1 thru 4 */
X	if ((ptr = strtok(buf, " ")) == NULL)
X		return;
X	for (i = 2; i <= 4 && strtok(NULL, " ") != NULL; i++)
X		;
X
X	/* and get jobname from field 5 */
X	strcpy(job->name, strtok(NULL, " "));
X
X	/* search for time field */
X	while ((ptr = strtok(NULL, " ")) != NULL)
X		if (strchr(ptr, '.') != NULL)
X			break;
X
X	/* get time */
X	if (at(ptr, '.') == 2)
X		sprintf(job->time, "0%7s", ptr);
X	else
X		strcpy(job->time, ptr);
X	strcpy(job->ampm, strtok(NULL, " "));
X
X	/* and date */
X	strcpy(job->day, strtok(NULL, " "));
X	strcpy(job->month, strtok(NULL, " "));
X	strcpy(job->year, strtok(NULL, " "));
X}
END_OF_FILE
if test 1127 -ne `wc -c <'job.c'`; then
    echo shar: \"'job.c'\" unpacked with wrong size!
fi
# end of 'job.c'
fi
if test -f 'main.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.c'\"
else
echo shar: Extracting \"'main.c'\" \(4663 characters\)
sed "s/^X//" >'main.c' <<'END_OF_FILE'
X/*
X**	m a i n . c
X**
X**	This is a interactive utility for RJE print spool management.
X**	It presents print files in list format to the user, displaying
X**	pertinent information about the file such as jobname, date, time,
X**	line count, etc.  The user may perform a variety of functions
X**	on the file such as print, view and delete.  Additionally, many
X**	of these singular operations may be done en masse on "tagged" or
X**	"untagged" files.
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
XNode   *head, *tail;
X
XWINDOW *hlpscr, *jobscr;
X
XUINT    total, bytes;
X
X/* keys allowed on main prompt */
Xstatic char valid_keys[] = {
X	' ', '\n', 'b', 'f', 'j', 'd', 'v', 'p',
X	't', 'u', 'a', 'x', 'T', 'U', 'W', 'M',
X	KEY_UP, KEY_DOWN
X};
X
Xmain(argc, argv)
Xint     argc;
Xchar   *argv[];
X{
X	int     c, op;
X	int     row, col;
X	int     i = 1;
X
X	char    buf[MAXNAMLEN];
X
X	Node   *node;
X
X	/* initialize curses */
X	initcurses();
X
X	/* trap signals */
X	trapsigs();
X
X	/* set user id */
X	setuserid();
X
X	/* change directory */
X	echdir(JOBDIR);
X
X	/* build linked list */
X	node = head = thread(mklist("."));
X
X	/* display help */
X	help(hlpscr);
X
X	/* infinite loop */
X	for (;;) {
X
X		/* display printline and  */
X		/* get user keystroke */
X		printline(jobscr, node, i);
X		getyx(jobscr, row, col);
X		wmove(jobscr, row, col - 2);
X		wrefresh(jobscr);
X		c = getkey(jobscr, valid_keys);
X		echokey(jobscr, ECHOKEYS, c);
X		wmove(jobscr, row, col);
X
X		/* handle user keystroke */
X		switch (c) {
X		case KEY_DOWN:
X		case '\n':
X		case ' ':	/* forward */
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case KEY_UP:
X		case 'b':	/* backward */
X			wprintw(jobscr, "ack");
X			docntb(jobscr);
X			newline(jobscr);
X			break;
X		case 'd':	/* delete file */
X			if (access(node->name, W_OK) != 0) {
X				wprintw(jobscr, " %s\n", sys_errlist[errno]);
X				docntf(jobscr);
X			} else {
X				echo();
X				wprintw(jobscr, "elete ? ");
X				noecho();
X				wrefresh(jobscr);
X				if (tolower(wgetch(jobscr)) == 'y') {
X					node = del(node);
X					if (i > total) {
X						i = 1;
X						newline(jobscr);
X					}
X				} else {
X					docntf(jobscr);
X				}
X				newline(jobscr);
X			}
X			break;
X		case 'v':	/* view file */
X			if ((node->st->st_mode & S_IFMT) != S_IFREG ||
X			    access(node->name, R_OK) != 0) {
X				wprintw(jobscr, " not editable\n");
X				docntf(jobscr);
X				break;
X			} else {
X				echo();
X				wprintw(jobscr, "iew ? ");
X				noecho();
X				wrefresh(jobscr);
X				if (tolower(wgetch(jobscr)) == 'y') {
X					clear();
X					refresh();
X					endwin();
X					execute(VIEW, VIEW, node->name, NULL);
X					initcurses();
X					help(hlpscr);
X					break;
X				} else
X					docntf(jobscr);
X			}
X		case 'p':	/* print file */
X			if ((node->st->st_mode & S_IFMT) != S_IFREG ||
X			    access(node->name, R_OK) != 0)
X				wprintw(jobscr, " not printable\n");
X			else {
X				echo();
X				wprintw(jobscr, "rint ? ");
X				noecho();
X				wrefresh(jobscr);
X				if (tolower(wgetch(jobscr)) == 'y')
X					lp(node->name);
X			}
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 't':	/* tag file */
X			wprintw(jobscr, "\b\b\b\b*[%c]ag", c);
X			node->flags |= TAG;
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 'u':	/* untag file */
X			wprintw(jobscr, "\b\b\b\b [%c]ntag", c);
X			node->flags &= ~TAG;
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 'a':	/* tag again */
X			wprintw(jobscr, "gain");
X			retag();
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 'T':	/* tag all files */
X			wprintw(jobscr, "ag all");
X			tagall();
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 'U':	/* untag all files */
X			wprintw(jobscr, "ntag all");
X			untagall();
X			docntf(jobscr);
X			newline(jobscr);
X			break;
X		case 'M':	/* mass operations */
X			/* operation? */
X			wprintw(jobscr, "ass d,p ? ");
X			wrefresh(jobscr);
X			op = tolower(getkey(jobscr, "\ndp"));
X			echokey(jobscr, "dp", op);
X			if (op == '\n') {
X				docntf(jobscr);
X				newline(jobscr);
X				break;
X			}
X			wprintw(jobscr, "\b\b\b\b\b\b");
X			switch (op) {
X			case 'd':
X				wprintw(jobscr, "del");
X				break;
X			case 'p':
X				wprintw(jobscr, "print");
X				break;
X			}
X			/* tagged or untagged? */
X			wprintw(jobscr, " t,u ? ");
X			wrefresh(jobscr);
X			c = tolower(getkey(jobscr, "\ntu"));
X			echokey(jobscr, "tu", c);
X			if (c == '\n') {
X				docntf(jobscr);
X				newline(jobscr);
X				break;
X			}
X			/* operations en masse */
X			switch (op) {
X			case 'd':	/* mass delete */
X				node = massdel(c);
X				i = 1;
X				newline(jobscr);
X				break;
X			case 'p':	/* mass print */
X				node = massprint(c);
X				i = 1;
X				newline(jobscr);
X				break;
X			}
X			break;
X		case 'x':	/* exit program */
X			quit(0);
X		}
X	}
X}
END_OF_FILE
if test 4663 -ne `wc -c <'main.c'`; then
    echo shar: \"'main.c'\" unpacked with wrong size!
fi
# end of 'main.c'
fi
if test -f 'main.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'main.h'\"
else
echo shar: Extracting \"'main.h'\" \(2037 characters\)
sed "s/^X//" >'main.h' <<'END_OF_FILE'
X/*
X**	m a i n . h
X**
X**	global includes, defines and macros
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X/* header files */
X#include <stdio.h>
X#include <string.h>
X#include <ctype.h>
X#include <malloc.h>
X#include <unistd.h>
X#include <errno.h>
X#include <signal.h>
X#include <varargs.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <curses.h>
X#include <dirent.h>
X
X#ifdef HASVOID
X# define VOID void
X#else
X# define VOID int
X#endif
X
X#ifdef SIGVOID
X# define SIGTYPE void
X#else
X# define SIGTYPE int
X#endif
X
X/* filenames for execution, edit to */
X/* match your system requirements */
X#define VIEW		"/usr/bin/view"
X#define RM		"/bin/rm"
X
X/* most SYS5 boxen use LP, however you */
X/* may be different and need LPR instead */
X#ifdef LPR
X# define LP		"/bin/lpr"
X# define LPOPTS		"-b"
X#else
X# define LP		"/usr/bin/lp"
X# define LPOPTS		"-sonobanner"
X#endif
X
X/* directory where RJE print is spooled */
X#define JOBDIR		"/usr/srje1/job"
X
X/* RJE print file prefix and length */
X#define PREFIX		"prnt"
X#define PREFIX_LEN	4
X
X#define MAXARGS		8	/* max args for execute */
X
X#define ECHOKEYS	"bfdvptuaTUMx"
X
X#ifndef ERR
X# define ERR	-1		/* error return value */
X#endif
X
X/* some folks have sys_errlist declared in */
X/* errno.h, others need to declare it here. */
X#ifdef SYSERR
Xextern char *sys_errlist[];
Xextern int sys_nerr;
X#endif
X
X#define newline(scr)	waddch(scr, '\n')
X
X#define UINT	unsigned int
X
Xextern UINT    total, bytes;
X
Xextern VOID    initcurses(), trapsigs(), setuserid(), help(), estat();
Xextern VOID    echdir(), quit(), printline(), freenodes(), lp(), perrorw();
X
X/* some shorthand */
X#define docntf(scr)	node = node->next;\
X			if (++i > total) { i = 1; newline(scr); }
X#define docntb(scr)	node = node->prev;\
X			if (--i < 1) { i = total; newline(scr); }
X
Xextern WINDOW *hlpscr, *jobscr;
X
X/* HELP screen size definitions */
X#define HLP_LINES	8
X#define HLP_COLS	80
X#define HLP_Y		0
X#define HLP_X		0
X
X/* JOB screen size definitions */
X#define JOB_LINES	16
X#define JOB_COLS	80
X#define JOB_Y		8
X#define JOB_X		0
END_OF_FILE
if test 2037 -ne `wc -c <'main.h'`; then
    echo shar: \"'main.h'\" unpacked with wrong size!
fi
# end of 'main.h'
fi
if test -f 'mass.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mass.c'\"
else
echo shar: Extracting \"'mass.c'\" \(1631 characters\)
sed "s/^X//" >'mass.c' <<'END_OF_FILE'
X/*
X**	m a s s . c
X**
X**	functions for performing tagged/untagged
X**	operations en masse
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X/*
X**	m a s s d e l
X**
X**	unlink tagged/untagged files en masse
X**
X*/
XNode   *
Xmassdel(c)
Xint     c;
X{
X	Node   *this, *node, *del();
X	int     hflag;
X
X	node = head;		/* point to head of list */
X	do {
X		hflag = 0;
X		this = node;	/* save pointer to this node */
X		node = node->next;	/* point to next node */
X		if ((c == 't') ? (this->flags & TAG) : !(this->flags & TAG)) {
X			hflag = (this == head);
X			wprintw(jobscr, "\n\tDeleting %s, %8lu bytes freed",
X				this->name, this->st->st_size);
X			(VOID) del(this);	/* delete this node */
X		}
X		if (c == 'u' && (this->flags & TAG)) {	/* is tag on? */
X			this->flags &= ~TAG;	/* turn tag off */
X			this->flags |= WAS;	/* turn was tag on */
X		}
X	} while (node != head || hflag);
X
X	newline(jobscr);
X	return (head);
X}
X
X/*
X**	m a s s p r i n t
X**
X**	spool files to printer en masse
X**
X*/
XNode   *
Xmassprint(c)
Xint     c;
X{
X	Node   *node;
X	VOID    print();
X
X	node = head;		/* point to head of list */
X	do {
X		if ((c == 't') ? (node->flags & TAG) : !(node->flags & TAG)) {
X			wprintw(jobscr, "\n\tSpooled %s to printer", node->name);
X			lp(node->name);	/* print file */
X		}
X		if (node->flags & TAG) {	/* is tag on? */
X			node->flags &= ~TAG;	/* turn tag off */
X			node->flags |= WAS;	/* turn was tag on */
X		} else if (node->flags & WAS)
X			node->flags &= ~WAS;	/* turn was tag off */
X		node = node->next;	/* point to next node */
X	} while (node != head);
X
X	newline(jobscr);
X	return (head);
X}
END_OF_FILE
if test 1631 -ne `wc -c <'mass.c'`; then
    echo shar: \"'mass.c'\" unpacked with wrong size!
fi
# end of 'mass.c'
fi
if test -f 'node.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'node.c'\"
else
echo shar: Extracting \"'node.c'\" \(2370 characters\)
sed "s/^X//" >'node.c' <<'END_OF_FILE'
X/*
X**	n o d e . c
X**
X**	functions for building and maintaining
X**	the two-way circular linked list of nodes
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X/*
X**	m k l i s t
X**
X**	build linked list of structures,
X**	linking nodes backward thru list.
X**	filenames are retrieved via opendir.
X**
X*/
XNode   *
Xmklist(dir)
Xchar   *dir;
X{
X	DIR    *dirp;
X	struct dirent *dp;
X	Node   *mknode(), *node;
X
X	tail = NULL;
X
X	total = bytes = 0;
X
X	dirp = opendir(dir);
X	while ((dp = readdir(dirp)) != NULL)
X		if (strncmp(PREFIX, dp->d_name, PREFIX_LEN) == 0) {
X			node = mknode(dp->d_name);
X			bytes += node->st->st_size;
X			++total;
X		}
X	closedir(dirp);
X	if (total == 0)
X		quit(1);
X	return (node);
X}
X
X/*
X**	t h r e a d
X**
X**	traverse linked list in reverse,
X**	threading nodes forward thru list.
X**
X*/
XNode   *
Xthread(tail)
XNode   *tail;
X{
X	Node   *node, *head = NULL;
X
X	/* traverse linked list backwards */
X	for (node = tail; node != NULL; node = node->prev) {
X		node->next = head;	/* link forward to next node */
X		head = node;	/* save pointer for next link */
X	}
X	head->prev = tail;	/* link head to tail */
X	tail->next = head;	/* and tail to head */
X
X	return (head);
X}
X
X/*
X**	m k n o d e
X**
X**	install node in linked list
X**
X*/
XNode   *
Xmknode(name)
Xchar   *name;
X{
X	Node   *node;
X	char   *emalloc();
X	Job    *jobinfo();
X	VOID    estat();
X
X	/* allocate storage areas */
X	node = (Node *) emalloc(sizeof(Node));
X	node->st = (Stat *) emalloc(sizeof(Stat));
X	node->job = (Job *) emalloc(sizeof(Job));
X
X	strcpy(node->name, name);	/* copy name into node */
X	estat(node->name, node->st);	/* get file statistics */
X	jobinfo(node->name, node->job);	/* get job information */
X	node->flags = 0;	/* set flag states to off */
X	node->prev = tail;	/* link back to previous node */
X	tail = node;		/* and save pointer for next link */
X
X	return (node);
X}
X
X/*
X**	r m n o d e
X**
X**	remove node from linked list
X**
X*/
XNode   *
Xrmnode(node)
XNode   *node;
X{
X	Node   *next;
X
X	node->prev->next = node->next;	/* link previous node forward to next */
X	node->next->prev = node->prev;	/* and next node backward to previous */
X	if (node == head)
X		head = node->next;	/* adjust head pointer */
X	else if (node == tail)
X		tail = node->prev;	/* and tail pointer */
X	next = node->next;
X	free(node->st);
X	free(node->job);
X	free(node);
X
X	return (next);
X}
END_OF_FILE
if test 2370 -ne `wc -c <'node.c'`; then
    echo shar: \"'node.c'\" unpacked with wrong size!
fi
# end of 'node.c'
fi
if test -f 'node.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'node.h'\"
else
echo shar: Extracting \"'node.h'\" \(1042 characters\)
sed "s/^X//" >'node.h' <<'END_OF_FILE'
X/*
X**	n o d e . h
X**
X**	definition of the node used in our linked list
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
Xtypedef struct stat Stat;	/* struct for estat */
X
X/* JES/2 job information */
Xtypedef struct Job {
X	char   name[9];		/* job name */
X	char   day[3];		/* job execution day */
X	char   month[4];	/*   "      "    month */
X	char   year[3];		/*   "      "    year */
X	char   time[9];		/*   "      "    time */
X	char   ampm[3];		/*   "      "    am/pm */
X}	Job;
X
X/* node for linked list */
Xtypedef struct Node {
X	char    name[15];	/* file name */
X	int     flags;		/* file flags */
X#define TAG	0x01		/* is tagged */
X#define WAS	0x02		/* was tagged */
X	Stat   *st;		/* file info */
X	Job    *job;		/* job info */
X	struct Node *prev;	/* link backward */
X	struct Node *next;	/* link forward */
X}       Node;
X
Xextern Node   *head, *tail;
X
Xextern Node   *thread(), *mklist();
Xextern Node   *rmnode(), *gotonode(), *del();
Xextern Node   *retag(), *tagall(), *untagall();
Xextern Node   *massdel(), *massprint();
END_OF_FILE
if test 1042 -ne `wc -c <'node.h'`; then
    echo shar: \"'node.h'\" unpacked with wrong size!
fi
# end of 'node.h'
fi
if test -f 'support.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'support.c'\"
else
echo shar: Extracting \"'support.c'\" \(5675 characters\)
sed "s/^X//" >'support.c' <<'END_OF_FILE'
X/*
X**	s u p p o r t . c
X**
X**	support routines used by all modules
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X/*
X**	h e l p
X**
X**	display program usage text
X**
X*/
XVOID
Xhelp(scr)
XWINDOW *scr;
X{
Xwclear(scr);
Xwprintw(scr, "+-----------------------------------------------------------+\n");
Xwprintw(scr, "|                 RJE PRINT SPOOL MANAGER                   |\n");
Xwprintw(scr, "|    b    previous       T   tag all        v   view file   |\n");
Xwprintw(scr, "|  sp/cr  next           U   untag all      p   print file  |\n");
Xwprintw(scr, "|    t    tag file       a   tag again      d   delete file |\n");
Xwprintw(scr, "|    u    untag file     M   mass ops       x   exit        |\n");
Xwprintw(scr, "+-----------------------------------------------------------+\n");
Xwprintw(scr, "  #  Filename Jobname   Date       Time             Size");
X/*              1  prnt999  PGM77DDA  23 JAN 91  11.32.59 AM  99999999 *[ ] */
Xwrefresh(scr);
X}
X
X/*
X**	s e t u s e r i d
X**
X**	set real uid to effective uid
X**
X*/
XVOID
Xsetuserid()
X{
X	if (getuid() == 0)
X		return;
X	if (setuid(geteuid()) == ERR) {
X		perrorw("setuserid");
X		exit(1);
X	}
X}
X
X/*
X**	q u i t
X**
X**	clear screen, end curses and exit
X**
X*/
XVOID
Xquit(status)
Xint     status;
X{
X	clear();
X	refresh();
X	endwin();
X	exit(status);
X}
X
X/*
X**	i n i t c u r s e s
X**
X**	initialize curses environment
X**
X*/
XVOID
Xinitcurses()
X{
X	initscr();
X
X	if (LINES < 24 || COLS < 80) {
X		printw("Screen must be at least 24 x 80\n");
X		endwin();
X		exit(1);
X	}
X	hlpscr = newwin(HLP_LINES, HLP_COLS, HLP_Y, HLP_X);
X	jobscr = newwin(JOB_LINES, JOB_COLS, JOB_Y, JOB_X);
X
X	if (has_il()) {
X		scrollok(jobscr, TRUE);
X		idlok(jobscr, TRUE);
X	}
X	keypad(jobscr, TRUE);
X	noecho();
X	cbreak();
X}
X
X/*
X**	p r i n t l i n e
X**
X**	print current node info line
X**
X*/
XVOID
Xprintline(scr, node, i)
XWINDOW *scr;
XNode   *node;
Xint     i;
X{
X	wprintw(scr, "%3d  ", i);
X	wprintw(scr, "%-7s  ", node->name);
X	wprintw(scr, "%-8s  ", node->job->name);
X	wprintw(scr, "%2s %3s %2s  ", node->job->day, node->job->month, node->job->year);
X	wprintw(scr, "%8s %2s  ", node->job->time, node->job->ampm);
X	wprintw(scr, "%8lu ", node->st->st_size);
X	wprintw(scr, "%c[ ]", ((node->flags & TAG) ? '*' :
X			       ((node->flags & WAS) ? '~' : ' ')));
X}
X
X/*
X**	g e t k e y
X**
X**	single character input,
X**	only chars in valid string allowed
X**
X*/
Xint
Xgetkey(scr, valid)
XWINDOW *scr;
Xchar   *valid;
X{
X	register int c;
X
X	while (strchr(valid, c = wgetch(scr)) == NULL);
X	return (c);
X}
X
X/*
X**	e c h o k e y
X**
X**	single character echo,
X**	only chars in valid string allowed
X**
X*/
Xint
Xechokey(scr, valid, c)
XWINDOW *scr;
Xchar   *valid;
Xint     c;
X{
X	if (strchr(valid, c) != NULL)
X		wprintw(scr, "%c\b", c);
X	return (c);
X}
X
X/*
X**	f i l e t y p e
X**
X**	test for file type
X**
X*/
Xint
Xfiletype(name, type)
Xchar   *name;
Xint     type;
X{
X	Stat   *st;
X	char   *emalloc();
X
X	st = (Stat *) emalloc(sizeof(Stat));
X
X	if (stat(name, st) == 0)
X		type = ((st->st_mode & S_IFMT) == type);
X	else
X		type = ERR;
X
X	free(st);
X
X	return (type);
X}
X
X/*
X**	e s t a t
X**
X**	stat with error checking
X**
X*/
XVOID
Xestat(path, buf)
Xchar   *path;
XStat   *buf;
X{
X	/* get file statistics */
X	if (stat(path, buf) == ERR) {
X		perrorw(path);
X		exit(1);
X	}
X}
X
X/*
X**	e m a l l o c
X**
X**	malloc with error checking
X**
X*/
Xchar   *
Xemalloc(size)
Xunsigned size;
X{
X	register char *p;
X
X	/* allocate requested storage */
X	if ((p = (char *) malloc(size)) == NULL) {
X		perrorw("malloc");
X		exit(1);
X	}
X	return (p);
X}
X
X/*
X**	e c h d i r
X**
X**	chdir with error checking
X**
X*/
XVOID
Xechdir(path)
Xchar   *path;
X{
X	/* change directory */
X	if (chdir(path) == ERR) {
X		perrorw(path);
X		exit(1);
X	}
X}
X
X/*
X**	a t
X**
X**	return index of char in string
X**
X*/
Xint
Xat(s, c)
Xchar   *s;
Xint     c;
X{
X	int     i;
X
X	for (i = 0; s[i]; i++)
X		if (s[i] == c)
X			return (++i);
X	return (0);
X}
X
X/*
X**	p e r r o r w
X**
X**	print error message on stdscr and die
X**
X*/
XVOID
Xperrorw(s)
Xchar   *s;
X{
X	if (s != NULL)
X		printw("%s: ", s);
X	if (errno <= sys_nerr)
X		printw("%s\n", sys_errlist[errno]);
X	else
X		printw("unknown error occured\n");
X	refresh();
X	endwin();
X}
X
X/*
X**	t r a p s i g s
X**
X**	begin trapping signals
X**
X*/
XVOID
Xtrapsigs()
X{
X	SIGTYPE sigcatch();
X
X	signal(SIGINT, SIG_IGN);
X	signal(SIGQUIT, SIG_IGN);
X	signal(SIGBUS, sigcatch);
X	signal(SIGSEGV, sigcatch);
X	signal(SIGTERM, sigcatch);
X#ifdef SIG_TSTP
X	signal(SIGTSTP, SIG_IGN);
X#endif
X}
X
X/*
X**	s i g c a t c h
X**
X**	catch signals and clean up
X**
X*/
XSIGTYPE
Xsigcatch(sig)
Xint     sig;
X{
X	switch (sig) {
X	case SIGINT:
X	case SIGQUIT:
X		clear();
X		break;
X	case SIGBUS:
X		printw("\n\nbus error ");
X		break;
X	case SIGSEGV:
X		printw("\n\nsegmentation violation ");
X		break;
X	case SIGTERM:
X		printw("\n\nterminated ");
X	default:
X		printw("\n\nunexpected signal ");
X	}
X	refresh();
X	endwin();
X	exit(1);
X}
X
X/*
X**	e x e c u t e
X**
X**	fork and exec child process
X**
X*/
Xint
Xexecute(va_alist)
Xva_dcl
X{
X	va_list ap;
X	char   *file;
X	char   *av[MAXARGS];
X	int     ac = 0;
X	int     pid, w, status;
X	SIGTYPE(*intr) (), (*quit) ();
X
X	va_start(ap);
X	file = va_arg(ap, char *);
X	while ((av[ac++] = va_arg(ap, char *)) != NULL);
X	va_end(ap);
X
X	/* fork child process */
X	if ((pid = fork()) == 0)
X		execv(file, av);
X
X	/* disable interrupts */
X	intr = signal(SIGINT, SIG_IGN);
X	quit = signal(SIGQUIT, SIG_IGN);
X
X	/* wait for child to return */
X	while ((w = wait(&status)) != pid && w != ERR);
X
X	/* enable interrupts */
X	signal(SIGINT, intr);
X	signal(SIGQUIT, quit);
X
X	/* wait was interrupted or */
X	/* child didn't return via exit */
X	if (w == ERR || (status & 0177) != 0)
X		return (ERR);
X
X	/* return arg child returned via exit */
X	return ((status >> 8) & 0377);
X}
END_OF_FILE
if test 5675 -ne `wc -c <'support.c'`; then
    echo shar: \"'support.c'\" unpacked with wrong size!
fi
# end of 'support.c'
fi
if test -f 'tag.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'tag.c'\"
else
echo shar: Extracting \"'tag.c'\" \(1185 characters\)
sed "s/^X//" >'tag.c' <<'END_OF_FILE'
X/*
X**	t a g . c
X**
X**	functions for tagging/untagging files en masse
X**
X**	Arthur W. Neilson III
X**	art at bohtsg.pegasus.com
X**	Feb 7, 1991
X**
X*/
X
X#include "main.h"
X#include "node.h"
X
X/*
X**	r e t a g
X**
X**	retag was tagged files
X**
X*/
XNode   *
Xretag()
X{
X	Node   *node;
X
X	node = head;		/* point to head of list */
X	do {
X		if (node->flags & WAS) {	/* is was tag on? */
X			node->flags &= ~WAS;	/* turn was tag off */
X			node->flags |= TAG;	/* turn tag on */
X		}
X		node = node->next;	/* point to next node */
X	} while (node != head);
X
X	return (head);
X}
X
X/*
X**	t a g a l l
X**
X**	tag all files in list
X**
X*/
XNode   *
Xtagall()
X{
X	Node   *node;
X
X	node = head;		/* point to head of list */
X	do {
X		node->flags &= ~WAS;	/* turn was tag off */
X		node->flags |= TAG;	/* turn tag on */
X		node = node->next;	/* point to next node */
X	} while (node != head);
X
X	return (head);
X}
X
X/*
X**	u n t a g a l l
X**
X**	untag all files in list
X**
X*/
XNode   *
Xuntagall()
X{
X	Node   *node;
X
X	node = head;		/* point to head of list */
X	do {
X		node->flags &= ~WAS;	/* turn was tag off */
X		node->flags &= ~TAG;	/* turn tag off */
X		node = node->next;	/* point to next node */
X	} while (node != head);
X
X	return (head);
X}
END_OF_FILE
if test 1185 -ne `wc -c <'tag.c'`; then
    echo shar: \"'tag.c'\" unpacked with wrong size!
fi
# end of 'tag.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-----8<----- cut here -----8<----- cut here -----8<----- cut here -----8<-----
-- 
Arthur W. Neilson III		| INET: art at pilikia.pegasus.com
Bank of Hawaii Tech Support	| UUCP: uunet!ucsd!nosc!pegasus!pilikia!art



More information about the Alt.sources mailing list