Listing 1. The termprint utility provides a simple
interface for printing one or more specified files on the local
printer attached to the user's terminal.
A. Listing of the termprint
Bourne shell program:
1 #!/bin/sh 2 # @(#) termprint Print data on local-terminal printer 3 # Author: Greg Hinkel, July 1991 4 # Modified by Becca Thomas , November 1993 5 $DBG_SH # Dormant debugging directive (Apr. 92) 6 7 # Remind the user to put their printer online. 8 echo "Make sure your printer is online." >/dev/tty; sleep 3 9 10 # Constants: 11 CTRL_L=`echo X | tr X '\014'` # Store formfeed (Control-L) character 12 PrintOn="" # Hard code if don't have tput 13 PrintOff="" # Hard code if necessary 14 Tmpfile=/tmp/`basename $0`$$ # File containing text to print 15 16 # Set trap to erase temp file and announce signal receipt: 17 trap 'rm -f $Tmpfile 2>/dev/null; exit' 0 18 trap 'echo "Interrupted by signal" >&2; exit' 1 2 3 15 19 20 # Figure out how to do echo without newline: 21 if [ -z "`echo 'hello\c' | sed 's/[^c]//g'`" ]; then 22 N=''; C='\c' 23 else 24 N='-n'; C='' 25 fi 26 27 # Process command-line argument(s): 28 case $# in 29 0) # Naive users might invoke without arguments and no pipe: 30 [ -t 0 ] && echo "Usage: termprint file ...">&2 && exit 1 31 # It might be appropriate to replace Control-L with a 32 # Control-M to avoid ejecting blank pages: 33 (echo $N "$CTRL_L$C" ; cat -) > $Tmpfile ;; # Store stdin 34 *) for File in $* ; do 35 if [ ! -r $File ]; then 36 echo "Cannot read \"$File\"" >&2 37 else 38 (echo $N "$CTRL_L$C" ; cat $File) >> $Tmpfile 39 fi 40 done ; shift ;; 41 esac 42 43 # Exit if there are no files to print: 44 if [ ! -s "$Tmpfile" ]; then 45 echo "Exiting, no readable files were located" >&2 ; exit 2 46 fi 47 48 # Get local-terminal printer-control codes if not already defined: 49 : ${PrintOn:="`tput mc5`"} # Get printer-on and 50 : ${PrintOff:="`tput mc4`"} # printer-off capability 51 52 # Make sure the printer-on and printer-off capabilities exist: 53 if [ ! "$PrintOn" -o ! "$PrintOff" ]; then 54 echo "Your terminal \"$TERM\" can't control your local printer" >&2 55 exit 3 56 fi 57 58 # Output printer-on code, files, formfeed, printer-off code: 59 echo $N "$PrintOn$C"; cat $Tmpfile; 60 echo $N "$CTRL_L$C"; echo $N "$PrintOff$C"
B. Sample usage:
$ termprint file $ pr file | termprint
Listing 2. Source for Jerry Peek's
tcap Program.
static char *rcsid = "$Header$";
/*
** tcap - termcaps for shell scripts.
** Usage: tcap [-a] cap
*/
#include <stdio.h>
#include <ctype.h>
extern char *tgetdefstr(), *tgetstr(), *tgoto();
extern int tgetdefnum(), tgetnum();
typedef struct tbl
{ char *str;
short val;
} lookuptbl;
#define STRING 1
#define STR1ARG 2
#define STR2ARG 3
#define NUMBER 4
#define FLAG 5
lookuptbl tcaps[] = {
"AL", STR1ARG,
"Bj", STRING,
"Bl", STRING,
"Br", STRING,
"CC", STRING,
"Cj", STRING,
"CM", STR2ARG,
"DC", STR1ARG,
"DL", STR1ARG,
"DO", STR1ARG,
"EP", FLAG,
"Ge", STRING,
"Gs", STRING,
"HD", FLAG,
"Hl", STRING,
"IC", STR1ARG,
"K1", STRING,
"K2", STRING,
"K3", STRING,
"K4", STRING,
"K5", STRING,
"LC", FLAG,
"LE", STR1ARG,
"Lj", STRING,
"NL", FLAG,
"OP", FLAG,
"RI", STR1ARG,
"Rj", STRING,
"SF", STR1ARG,
"SR", STR1ARG,
"Tj", STRING,
"Tl", STRING,
"Tr", STRING,
"UC", FLAG,
"UP", STR1ARG,
"Vl", STRING,
"Xc", STRING,
"ae", STRING,
"al", STRING,
"am", FLAG,
"as", STRING,
"bc", STRING,
"bl", STRING,
"bs", FLAG,
"bt", STRING,
"bw", FLAG,
"cd", STRING,
"ce", STRING,
"ch", STR1ARG,
"cl", STRING,
"cm", STR2ARG,
"co", NUMBER,
"cr", STRING,
"cs", STR2ARG,
"ct", STRING,
"cv", STR1ARG,
"dB", NUMBER,
"dC", NUMBER,
"dF", NUMBER,
"dN", NUMBER,
"dT", NUMBER,
"dV", NUMBER,
"da", FLAG,
"db", FLAG,
"dc", STRING,
"dl", STRING,
"dm", STRING,
"do", STRING,
"ds", STRING,
"ec", STR1ARG,
"ed", STRING,
"ei", STRING,
"eo", FLAG,
"es", FLAG,
"ff", STRING,
"fs", STRING,
"gn", FLAG,
"hc", FLAG,
"hd", STRING,
"ho", STRING,
"hs", FLAG,
"hu", STRING,
"hz", FLAG,
"ic", STRING,
"if", STRING,
"im", STRING,
"in", FLAG,
"ip", STRING,
"is", STRING,
"it", NUMBER,
"k0", STRING,
"k1", STRING,
"k2", STRING,
"k3", STRING,
"k4", STRING,
"k5", STRING,
"k6", STRING,
"k7", STRING,
"k8", STRING,
"k9", STRING,
"kA", STRING,
"kC", STRING,
"kD", STRING,
"kE", STRING,
"kF", STRING,
"kH", STRING,
"kI", STRING,
"kL", STRING,
"kM", STRING,
"kN", STRING,
"kP", STRING,
"kR", STRING,
"kS", STRING,
"kT", STRING,
"ka", STRING,
"kb", STRING,
"kd", STRING,
"ke", STRING,
"kh", STRING,
"kl", STRING,
"km", FLAG,
"kn", NUMBER,
"ko", STRING,
"kr", STRING,
"ks", STRING,
"kt", STRING,
"ku", STRING,
"l0", STRING,
"l1", STRING,
"l2", STRING,
"l3", STRING,
"l4", STRING,
"l5", STRING,
"l6", STRING,
"l7", STRING,
"l8", STRING,
"l9", STRING,
"le", STRING,
"li", NUMBER,
"ll", STRING,
"lm", NUMBER,
"ma", STRING,
"mb", STRING,
"md", STRING,
"me", STRING,
"mh", STRING,
"mi", FLAG,
"mk", STRING,
"ml", STRING,
"mm", STRING,
"mo", STRING,
"mp", STRING,
"mr", STRING,
"ms", FLAG,
"mu", STRING,
"nc", FLAG,
"nd", STRING,
"nl", STRING,
"ns", FLAG,
"nw", STRING,
"os", FLAG,
"pO", STR1ARG,
"pb", NUMBER,
"pc", STRING,
"pf", STRING,
"po", STRING,
"ps", STRING,
"pt", FLAG,
"rP", STRING,
"rc", STRING,
"rf", STRING,
"rp", STR2ARG,
"rs", STRING,
"sa", STR2ARG,
"sc", STRING,
"se", STRING,
"sf", STRING,
"sg", NUMBER,
"so", STRING,
"sr", STRING,
"st", STRING,
"ta", STRING,
"tc", STRING,
"te", STRING,
"ti", STRING,
"ts", STR1ARG,
"uc", STRING,
"ue", STRING,
"ug", NUMBER,
"ul", FLAG,
"up", STRING,
"us", STRING,
"vb", STRING,
"ve", STRING,
"vi", STRING,
"vs", STRING,
"vt", NUMBER,
"wi", STRING,
"ws", NUMBER,
"xb", FLAG,
"xn", FLAG,
"xo", FLAG,
"xr", FLAG,
"xs", FLAG,
"xt", FLAG,
"xv", FLAG,
"xx", FLAG,
};
putx(c) { putchar (c); }
main (argc, argv)
int argc;
char **argv;
{
char tcbuf[1024];
char *cp, *arg;
int i, tgetnum(), tgetflag();
static int aflag = 0;
if (tgetent(tcbuf, getenv ("TERM")) <= 0) {
(void) fprintf (stderr, "tcap: cannot find termcap for %s.\n",
getenv ("TERM"));
exit (1);
}
cp = (char *) malloc (256);
argv++;
while (*argv) {
arg = *argv++;
if (strcmp (arg, "-a") == 0) {
aflag = 1;
continue;
}
i = lookup (arg, tcaps);
if (i < 0) {
(void) fprintf (stderr, "tcap: no such termcap: %s\n", arg);
exit (2);
}
switch (tcaps[i].val & 017) {
case STRING:
if (aflag)
show (tgetdefstr (arg, &cp));
else
tputs (tgetdefstr (arg, &cp), 1, putx);
break;
case STR1ARG:
if (aflag)
show (tgetstr (arg, &cp));
else
if (argv != NULL && isdigit (**argv))
tputs (tgoto (tgetstr (arg, &cp),
atoi (*argv++), 0), 1, putx);
else {
(void) fprintf (stderr, "tcap: error in arguments to %s\n",
arg);
exit(3);
}
break;
case STR2ARG:
if (aflag)
show (tgetstr (arg, &cp));
else
if (argv != NULL && argv[1] != NULL &&
isdigit (**argv) && isdigit (*(argv[1])))
tputs (tgoto (tgetstr (arg, &cp),
atoi (*argv++), atoi (*argv++)), 1, putx);
else {
(void) fprintf (stderr, "tcap: error in arguments to %s\n",
arg);
exit(3);
}
break;
case NUMBER:
if (aflag)
(void) printf ("%d\n", tgetdefnum (arg));
break;
case FLAG:
if (aflag)
(void) printf (tgetflag (arg) ? "true\n" : "false\n");
break;
}
}
exit (0);
}
#define MAXLUPN 3 /* longer than longest possible name */
/* Lookup name in table. Will take nonambiguous abbreviations. If
you want to insist that a certain table entry must be spelled
out, enter it twice in the table. Table entries must be sorted
by name, and a name which is a substring of a longer name comes
earlier in the table. Accepts upper or lower case if table entry
is lower case.
Returns:
> 0 table entry index
-1 not found
-2 ambiguous
*/
int lookup (name, table)
char *name;
lookuptbl *table;
{
register char *namptr,
*tblptr;
int ind;
int value = 0;
short length;
short longest = 0;
int ambig = 0;
char lname[MAXLUPN];
if (name == NULL)
return -1;
namptr = name;
tblptr = lname;
for (;;) {
if ((*tblptr++ = isupper (*namptr)? tolower (*namptr++): *namptr++)
== '\0')
break;
if (tblptr >= &lname[MAXLUPN])
return -1;
}
for (ind = 0; (tblptr = table->str) != 0; table++, ind++) {
namptr = lname;
for (; *tblptr == *namptr; tblptr++, namptr++) {
if (*tblptr == '\0')
break;
}
if (*namptr == '\0') { /* end of name or exact match */
length = namptr - lname;
if (longest < length) {
longest = length;
ambig = 0;
value = ind;
if (*tblptr == '\0')
break; /* exact match */
}
else /* longest == length */
ambig = 1;
}
else if ( *namptr < *tblptr )
break;
}
if (ambig)
return -2;
if (longest)
return value;
return -1;
}
show (str)
char *str;
{
char c;
if (str == (char *)0) {
(void) printf ("NULL\n");
return;
}
while (c = *str++ & 127)
if (c < ' ') {
if (c == 27)
(void) printf ("\n");
(void) printf ("^%c", c + '@');
} else if (c == 127)
(void) printf ("^?");
else
(void) printf ("%c", c);
(void) printf ("\n");
return;
}
char *
tgetdefstr (cap, ptr)
char *cap, *ptr;
{
char *x;
static char *bs = "\b",
*ht = "\t",
*nl = "\n",
*cr = "\r",
*ff = "\f",
*nu = "\0",
*bl = "\007",
*nlcr = "\n\r";
if ((x = tgetstr (cap, ptr)) != (char *) 0)
return (x);
if (strcmp (cap, "pc") == 0)
return (nu);
if (strcmp (cap, "bc") == 0)
return (bs);
if (strcmp (cap, "ta") == 0)
return (ht);
if (strcmp (cap, "nl") == 0)
return (nl);
if (strcmp (cap, "cr") == 0)
return (cr);
if (strcmp (cap, "ff") == 0)
return (ff);
if (strcmp (cap, "nw") == 0)
return (nlcr);
if (strcmp (cap, "bl") == 0)
return (bl);
if (strcmp (cap, "ho") == 0)
return (tgoto (tgetstr ("cm", ptr), 0, 0));
if (strcmp (cap, "ll") == 0)
return (tgoto (tgetstr ("cm", ptr), tgetnum ("li") - 1, 0));
if (strcmp (cap, "rs") == 0)
return (tgetstr ("is", ptr));
if (strcmp (cap, "is") == 0)
return (tgetstr ("rs", ptr));
if (strcmp (cap, "rf") == 0)
return (tgetstr ("if", ptr));
if (strcmp (cap, "if") == 0)
return (tgetstr ("rf", ptr));
return ((char *) 0);
}
tgetdefnum (cap)
char *cap;
{
int x;
if ((x = tgetnum (cap)) != -1)
return (x);
if (strcmp (cap, "ws") == 0)
return (tgetnum ("co"));
return (0);
}
Listing 3: A script can be used to manage .rhosts files by
renaming them.
1 #! /bin/sh 2 # rhyes/rhno Enable/disable use of remote .rhosts file 3 # Author: Jerry Peek, May 1992 4 # set -x # uncomment for debugging 5 6 # Get name of invoked script: 7 Thisprog="`basename $0`" 8 9 # Get account name of invoking user: 10 if [ "$USER" ]; then 11 Username=$USER 12 elif [ "$LOGNAME" ]; then 13 Username=$LOGNAME 14 else 15 echo "Can't determine your account name." >&2; exit 2 16 fi 17 18 # Determine home directory for user: 19 if [ "$HOME" ]; then 20 Homedir=$HOME 21 elif [ "$LOGDIR" ]; then 22 Homedir=$LOGDIR 23 else 24 echo "Can't determine your home directory name." >&2; exit 3 25 fi 26 27 # Handle invocation without a remote host name: 28 case $# in 29 0) # No argument specified, so rename local file: 30 case "$Thisprog" in 31 rhyes) if [ ! -f $Homedir/.rhosts.moved ]; then 32 echo "Exiting, no $Homedir/.rhosts.moved" >&2 33 exit 2 34 fi 35 mv $Homedir/.rhosts.moved $Homedir/.rhosts ;; 36 rhno) if [ ! -f $Homedir/.rhosts ]; then 37 echo "Exiting, no $Homedir/.rhosts" >&2 38 exit 2 39 fi 40 mv $Homedir/.rhosts $Homedir/.rhosts.moved ;; 41 *) echo "$Thisprog: Invalid program name" >&2 42 exit 1 ;; 43 esac 44 exit 0 ;; 45 esac 46 47 # Create proper file-name order for rename operation: 48 case "$Thisprog" in 49 rhyes) Cmdargs=".rhosts.moved .rhosts" ;; 50 rhno) Cmdargs=".rhosts .rhosts.moved" ;; 51 *) echo "$0: Help! Shouldn't get here!" 1>&2 52 exit 1 ;; 53 esac 54 55 # Perform operation for all remote hosts: 56 for host 57 do 58 echo "Connecting to $host ..." 59 cat << ENDCMDS | ftp -n $host # Don't use .netrc 60 user $Username 61 rename $Cmdargs 62 quit 63 ENDCMD 64 done
B. Sample usage session:
% rhyes snake
Password: ...type snake password
% rsh snake some-command
...
% rhno snake
Password: ...type snake password
% rsh snake some-command
Permission denied.
% []