4.4BSD/usr/src/contrib/rc-1.4/EXAMPLES

There is no repository for useful rc code snippets as yet, so I'm including
a (short) file in the distribution with some helpful/intriguing pieces of
rc code.

A sample .rcrc
--------------
Here is the .rcrc I use on archone:

umask 022 
path=(/bin /usr/bin /usr/ucb)
ht=`/usr/arch/bin/hosttype
h=$home
history=$h/.history
bin=$h/bin/$ht
lib=$h/lib/$ht
sh=$h/bin/sh
include=$h/lib/include

switch ($ht) {
case sun*
	OBERON='. '$h/other/oberon
	p=/usr/ucb
	compiler='gcc -Wall -O -g'
	MANPATH=$h/man:/usr/arch/man:/usr/man
	if (! ~ $TERM ()) {
		stty dec
		/usr/arch/bin/msgs -q
	}
case next
	p=(/usr/ucb /usr/bin /NextApps)
	compiler='cc -Wall -O -g -DNODIRENT'
	MANPATH=$h/man:/usr/arch/man:/usr/man
	if (! ~ $TERM ())
		stty dec
case sgi
	p=(/usr/ucb /usr/sbin /usr/bin)
	compiler='gcc -Wall -O -g -DNOSIGCLD'
	MANPATH=$h/man:/usr/arch/man:/usr/catman
	if (!{~ $TERM () || ~ $TERM *iris*})
		stty line 1 intr '' erase '' kill ''
case *
	echo .rcrc not configured for this machine
}

path=(. $sh $bin /usr/arch/bin $p /bin /usr/bin/X11 /etc /usr/etc)
cdpath=(. .. $h $h/src $h/misc $h/other $h/adm)
RNINIT=-d$h' -t -M -2400-h -2400+hfrom'; DOTDIR=$h/misc/news
PRINTER=lw

fn s {
	echo $status
}
fn cd {
	builtin cd $1 && \
	switch ($1) {
	case ()
		dir=$home
	case *
		dir=()
	}
}
fn pwd {
	if (~ $dir ())
		dir=`/bin/pwd
	echo $dir
}
fn x {
	if (~ `tty /dev/console)
		clear_colormap
	clear
	exit
}
fn p {
	if (~ $history ()) {
		echo '$history not set' >[1=2]
		return 1
	}

	if (! ~ $#* 0 1 2) {
		echo usage: $0 '[egrep pattern] [sed command]' >[1=2]
		return 1
	}

	command=`{
		egrep -v '^[ 	]*p([	 ]+|$)' $history | switch ($#*) {
		case 0
			cat
		case 1
			egrep $1
		case 2
			egrep $1 | sed $2
		} | tail -1
	}

	echo $command
	eval $command
}

if (~ $TERM dialup network) {
	TERM=vt100
	biff y
}

A front-end to NeXT's "openfile"
--------------------------------

Named after the sam "B" command for opening a file, this script was written
by Paul Haahr. (Assumes the "pick" command from Kernighan and Pike is also
in your path.)

#!/bin/rc
if (~ $#* 0)
        exec openfile
create = ()
files = ()
for (i in $*)
        if (test -f $i) {
                files = ($files $i)
        } else {
                create = ($create $i)
	}
create = `{ pick $create }
files = ($files $create)
for (i in $create)
        > $i
if (! ~ $#files 0)
	openfile $files

A read function
---------------

Unlike sh, rc doesn't have a read. This clever alternative returns an
exit status as well as fetch a variable. Use as

	read foo

to set $foo to a single line from the terminal.

(due to John Mackin <john@syd.dit.csiro.au>)

fn read {
        x=() {
                x = `` ($nl) { awk '{print; print 0; exit}' ^ $nl ^ \
                                   'END {print 1; print 1}' }
                $1 = $x(1)
                return $x(2)
        }
}

From cs.wisc.edu!dws Fri Aug  2 18:16:14 1991

#-------
# ls front end
#-------
fn ls	\
{
	test -t 1 && * = (-FCb $*)
	builtin ls $*
}
#-------
# nl - holds a newline, useful in certain command substitutions
#-------
nl='
'
#-------
# show - tell me about a name
#
# Runs possibly dangerous things through cat -v in order to protect
# me from the effects of control characters I might have in the
# environment.
#-------
fn show	\
{
	* = `` $nl {whatis -- $*}
	for(itis)
	{
		switch($^itis)
		{
		case 'fn '*	; echo $itis | cat -v -t
		case builtin*	; echo $itis
		case /*		; file $itis; ls -ld $itis
		case *'='*	; echo $itis | cat -v -t
		case *		; echo $itis: UNKNOWN: update show
		}
	}
	itis = ()
}
#-------
# Tell me automatically when a command has a nonzero status.
#-------
fn prompt	\
{
	Status = $status
	~ $Status 0 || echo '[status '$Status']'
}

#-------
# chop - echo the given list, less its final member
#
# e.g. chop (a b c) -> (a b)
#-------
fn chop {
	~ $#* 0 1 && return 0
	ans = '' {	# local variable
		ans = ()
		while(! ~ $#* 1)
		{
			ans = ($ans $1)
			shift
		}
		echo $ans
	}
}

From arnold@audiofax.com Thu May 30 08:49:51 1991

# cd.rc --- souped up version of cd

# this is designed to emulate the fancy version of cd in ksh,
# so if you're a purist, feel free to gag

_cwd=$home
_oldcwd=$home

fn cd {
	if (~ $#* 0) {
		if (~ $_cwd $home) {	# do nothing
		} else {
			builtin cd && { _oldcwd=$_cwd ; _cwd=$home }
		}
	} else if (~ $#* 1) {
		if (~ $1 -) {
			_t=$_cwd
			builtin cd $_oldcwd && {
				_cwd=$_oldcwd
				_oldcwd=$_t
				echo $_cwd
			}
			_t=()
		} else {
			# if a cd happens through the cdpath, rc echos
			# the directory on its own.  all we have to do
			# is track where we end up
			_dopwd = 1
			{ ~ $1 /* } && _dopwd = 0	# absolute path
			builtin cd $1 && {
				_oldcwd=$_cwd
				_cwd=$1
				{ ~ $_dopwd 1 } && _cwd=`/bin/pwd
			}
			_dopwd=()
		}
	} else if (~ $#* 2) {
		_t=`{ echo $_cwd | sed 's<'$1'<'$2'<' }
		builtin cd $_t && {
			_oldcwd=$_cwd
			_cwd=$_t
			echo $_cwd
		}
		_t=()
	} else {
		echo cd: takes 0, 1, or 2 arguments >[1=2]
		builtin cd $1 && { _oldcwd=$_cwd ; _cwd=`/bin/pwd ; echo $_cwd }
	}
}

fn pwd { echo $_cwd }

From vlsi.cs.caltech.edu!drazen Tue Jan 21 16:03:14 1992

# A kill builtin.

#ifdef B_KILL
#include <ctype.h>
static void b_kill(char **av)
{
    int signal = SIGTERM;
    int n = 1;
    pid_t pid;
    boolean res;

    if (!av[1]) {
        set(TRUE);
        return;
    }
#undef  STRCMP
#define STRCMP strcmp
    if ( '-' == av[1][0]) {
        char *p = 1+av[1];
        if (0 == strcmp(av[1], "-l")){
            int r; const int nsig = NUMOFSIGNALS;
            const int C = 4, R = 1 + (int)((nsig-2)/C);
            for (r=1; r<=R; r++){
              int j;
              for (j=r; j<nsig; j+=R){
                fprint(1, "%s%d. %s\t", j<10?" ":"", j, signals[j][0]);
              }
              fprint(1,"\n");
            }
            set(TRUE);
            return;
        }
        n++;
        if ( (signal=a2u(p)) < 0){
            int i;
            for (i = 1; i < NUMOFSIGNALS; i++){
                char UPPER[31], *u=UPPER, *q;
                for (q=signals[i][0]; *q; q++, u++) *u = toupper(*q);
                *u = '\0';

                if (*signals[i][0] &&
                  (!STRCMP(signals[i][0], p) || !STRCMP(3+signals[i][0],p)
                   || !STRCMP(UPPER, p) || !STRCMP(3+UPPER, p) )  )
                {
                    signal = i;
                    break;
                }
            }
            if (signal < 0){
                fprint(2,"kill: bad signal %s\n", av[1]);
                set(FALSE);
                return;
            }
        }
    }
#undef STRCMP

    for (res=TRUE; av[n]; n++){
        if( (pid = (pid_t) a2u(av[n])) < 0){
            fprint(2, "kill: bad process number %s\n", av[n]);
            res = FALSE;
            continue;
        }
        if (kill(pid,signal)){
            uerror("kill");
            res = FALSE;
            continue;
        }
    }
    set(res);
}
#endif
From acc.stolaf.edu!quanstro Thu Apr  2 02:51:10 1992
Received: from thor.acc.stolaf.edu ([130.71.192.1]) by archone.tamu.edu with SMTP id <45339>; Thu, 2 Apr 1992 02:50:56 -0600
Received: by thor.acc.stolaf.edu; Thu, 2 Apr 92 02:49:31 -0600
Date: Thu, 2 Apr 1992 02:49:31 -0600
From: quanstro@acc.stolaf.edu
Message-Id: <9204020849.AA26566@thor.acc.stolaf.edu>
To: byron@archone.tamu.edu
Subject: EXAMPLES in 1.4beta
Status: RO


I have a little bit of code which might be a little more general than
the souped-up version that is already there. Here it is, if you are
interested. 

# directory functions ###################################################
fn pwd { echo $PWD; }

fn pushd {
  dirs = ($PWD $dirs);		
  builtin cd $*;
  PWD = `{builtin pwd};
}

fn popd {
  switch ($#*)
    {
    case 0
      ;
    case 1
      echo 'popd: argument '^$1^' ignored.' >[1=2];
    case *
      echo 'popd: usage: popd [n].';
    }

  if (! ~ $dirs ()) 
    {
      builtin cd $dirs(1);
      PWD = $dirs(1);
      echo $PWD;
      * = $dirs;
      shift
      dirs = $*;
    }
}

fn cd {
  ~ $* () && * = $home;
  !~ $#* 1 && echo 'cd: too many arguments' >[1=2] && return 1;

  if (test -r $* ) {
    pushd $*;
  } else {
    echo cd: $* does not exist. >[1=2]
    return 1;
  } 
}

fn back { popd $*; }

fn Back { 
  cd $home;
  PWD = $home;
  dirs = ();
}

fn dirs {
  echo $dirs;
}

PWD = `{builtin pwd} ; dirs = $PWD		# kickstart





From acc.stolaf.edu!quanstro Thu Apr  2 02:53:40 1992
Received: from thor.acc.stolaf.edu ([130.71.192.1]) by archone.tamu.edu with SMTP id <45339>; Thu, 2 Apr 1992 02:53:38 -0600
Received: by thor.acc.stolaf.edu; Thu, 2 Apr 92 02:51:46 -0600
Date: Thu, 2 Apr 1992 02:51:46 -0600
From: quanstro@acc.stolaf.edu
Message-Id: <9204020851.AA26573@thor.acc.stolaf.edu>
To: byron@archone.tamu.edu
Subject: EXAMPLES
Status: RO


Little yp hack which act's like ~ w/o syntatic sugar (for those who do
not have the luxury of seting up symbolic links to all user's homes

# user function #########################################################
fn u user {  
  info = ()
  info = `` (':') {ypmatch $1 passwd >[2] /dev/null }

  if (~ $info ()) {
    echo user $1 unknown >[1=2];
    return 1;
  } else {
    echo $info(6)
    if (~ $0 user) 
      cd $info(6)
  }
}


From stolaf.edu!quanstro Sun Apr  5 04:53:34 1992
Date: Sun, 5 Apr 1992 04:53:08 -0500
From: quanstro@stolaf.edu (Erik Quanstrom)
To: byron@archone.tamu.edu
Subject: man written in rc 
Status: RO

I whipped this up because the NeXTs here insist on using MANPAGER
instead of PAGER and otherwise being obnoxious . . . 

Anyway ... I hope you approve

#!/bin/rc
#########################################################################
# file:		man							#
#									#
# object:	display man pages					#
#									#
# bugs:		* slow							#
#		* does not know about fmt files				#
#									#
# Erik Quanstrom							#
# 11. Februar 1992							#
#########################################################################
PATH=/bin:/usr/bin:/usr/ucb:/usr/local/bin:$PATH ; 
TROFF = (nroff -hq -Tcrt);
macros=an;
sections=(cat1 cat2 cat3 cat4 cat5 cat6 cat7 cat8 catl man1 man2 man3 man4 \
	  man5 man6 man7 man8 manl)
$nl='
'
fn sigint sighup sigquit sigalrm sigterm { rm -f $Bat; exit 2;}
  
fn usage {
  echo usage: $0 [-] [-t] [-M path] [-T macros] [[section] title] ...>[1=2];
  exit 1;
}

n=();
fn shiftn {
  n=($n 1)
}

~ $PAGER () && test -t 1 && PAGER=more; #default pager
     
while (~ $1 -*)
  { 
    switch ($1)
      {
      case -
	if (~ $PAGER troff)
	  echo bad combination of flags >[1=2] && usage;
	PAGER=cat;
      case -t
	~ TROFF () && TROFF = (troff -t);
	~ TCAT  () && PAGER=(lpr -t);
      case -M
	shift;
	~ $1 () && usage;
	
	MANPATH=$1;
      case -T
	shift;
	~ $1 () && usage;
	macros=$1;
      case -k
	fflag=(); kflag=1;
        shift;
        break;
      case -f
	# locate related too filenames
	kflag=(); fflag=1;
        shift;
        break;
      case -*
	echo bad flag '`'^$1^'''' >[1=2];
	usage;
      }
    shift;
  }

if (!~ $#* 1) {
  ~ $1 [l1-8] && { sname=$1 ; sections=(cat man)^$1 ; shift }
  #hack for sun-style man pages
  ~ $1 [l1-8]? && { sname=$1 ; sections=(cat man)^`{echo $1| cut -c1} ; shift }
}

if (~ 1 $fflag $kflag) {
  dirlist=();
  for (d in ``(:$nl) {echo $MANPATH})
    test -s $d^/whatis && dirlist=($dirlist $d^/whatis);
  
  ~ $1 () && usage;
  
  if (~ $fflag 1) { 
    while (!~ $1 ()) {
      cmd=`{echo $1 | sed 's/^.*\///g'}
      egrep -h '^'^$cmd' ' $dirlist;
      shift;
    }
  } else {
    while (!~ $1 ()) {
      grep -h $1 $dirlist;
      shift;
    }
  }
 exit 0;
}

s=0;	 
while (!~ $1 ()) {
  for (dir in ``(:$nl) {echo $MANPATH}) {
    filelist=($filelist `{echo $dir/^$sections^/$1^.* |\
			    tr ' ' '\12' | grep -v '*'})

    # coment this out if you don't care about speed, but 
    # would rather find all the pages.
    ~ $filelist () || break;
  }

  if (~ $filelist ()) {
    if (~ $#sections 2) {
      echo no entry for $1 in section '`'$sname'''' of the manual >[1=2];
    } else {
      echo no entry for '`'$1'''' found. >[1=2];
    }
    s=1;
  } else {

    echo $filelist '(' $#filelist ')' >[1=2];

    for (file in $filelist) {
      if (~ $file */cat[1-8l]/*) {
	Cat = ($Cat $file);
      } else {
	# search for dups
	dont=()
	for (x in $Cat) {
	  if (~ `{echo $x |  sed 's/\/[mc]a[nt][1-8l]//'} \
	        `{echo $file |  sed 's/\/[mc]a[nt][1-8l]//'}) {
	    dont=1;
	    break;
	  }
	}

	if (~ $dont ()) {
	  cd `{echo $file | sed 's/man[1-8].*//'}
	  echo -n Formatting ...
	  $TROFF -m^$macros $file > /tmp/man^$pid^$#n && \
		Bat = ($Bat /tmp/man^$pid^$#n)

	  shiftn;
	  echo ' 'done.
	}
      }
    }
  } 
  shift;
}

{ !~ () $Cat || !~ () $Bat } && $PAGER $Cat $Bat;

rm -f $Bat;
~ $s () || exit $s;
     
exit 0;



From osf.org!rsalz Thu Apr 23 16:22:32 1992
Date: Thu, 23 Apr 1992 16:22:07 -0500
From: rsalz@osf.org
To: byron@archone.tamu.edu
Subject: One for your EXAMPLES file
Status: RO

Use
	trimhist [-#lines]
trims your history file back; useful for folks with dis quota's :-)
fn trimhist { p1=-100 {
    cp $history $history^'~'
    ~ $#* 1 && p1=$1
    tail $p1 <$history^'~' >$history
    rm $history^'~'
} }

From Pa.dec.com!uucp Mon Apr 27 12:25:02 1992
Date: Mon, 27 Apr 1992 12:15:18 -0500
From: haahr@adobe.com
To: Byron Rakitzis <byron@archone.tamu.edu>
Subject: a neat little rc script

what you have to know to understand this:
	$md for me is usually obj.$machine
	my mkfiles build *.o, *.a, and the a.outs in $md
	this is my acc script, which i use for compiling adobe routines
---
#! /user/haahr/bin/next/rc

cc = cc
proto = '-DPROTOTYPES=1'

switch ($md) {
case noproto.$machine;	proto = '-DPROTOTYPES=0'
case gprof.$machine;	cc = ($cc -pg)
case prof.$machine;	cc = ($cc -p)
case lcomp.$machine;	cc = lcomp
}
exec $cc $proto '-DPACKAGE_SPECS="package.h"' '-DISP=isp_mc68020' '-DOS=os_mach' $*

From rc-owner Tue May 12 14:54:10 1992
Received: from postman.osf.org ([130.105.1.152]) by archone.tamu.edu with SMTP id <45337>; Tue, 12 May 1992 14:38:16 -0500
Received: from earth.osf.org by postman.osf.org (5.64+/OSF 1.0)
	id AA14480; Tue, 12 May 92 13:25:03 -0400
Received: by earth.osf.org (5.64/4.7) id AA03499; Tue, 12 May 92 13:25:02 -0400
Date: Tue, 12 May 1992 12:25:02 -0500
From: rsalz@osf.org
Message-Id: <9205121725.AA03499@earth.osf.org>
To: rc@archone.tamu.edu
Subject: Useful function
Status: R

It looks like line noise, but it turns things like
	/home/rsalz/foo/bar
into
	~/foo/bar

Useful for when you put your current directory up in your icon title.
By duplicating the $home section you can make things like
	/project/dce/build/dce1.0.1/src/rpc
become
	$MYBT/src/rpc

##  If a pathname starts with $home, turn $home into ~.  Uses all built-ins.
fn tildepath { p1=() i=() {
    p1=$1
    switch ($p1) {
    case $home $home/*
	# Split arg into components
	*=`` (/) { echo -n $p1 }
	# Shift down by number of components in $home
	for (i in `` (/) { echo -n $home } ) shift
	# Glue back together
	p1='~'
	for (i) p1=$p1 ^ '/' ^ $i
	echo $p1
    case *
	echo $p1
    }
    return 0
} }

From osf.org!rsalz Tue May 12 15:47:12 1992
Received: from postman.osf.org ([130.105.1.152]) by archone.tamu.edu with SMTP id <45316>; Tue, 12 May 1992 15:47:06 -0500
Received: from earth.osf.org by postman.osf.org (5.64+/OSF 1.0)
	id AA21070; Tue, 12 May 92 16:46:58 -0400
Received: by earth.osf.org (5.64/4.7) id AA09396; Tue, 12 May 92 16:46:56 -0400
Date: Tue, 12 May 1992 15:46:56 -0500
From: rsalz@osf.org
Message-Id: <9205122046.AA09396@earth.osf.org>
To: byron@archone.tamu.edu
Subject: Re: Useful function
Status: R

>wow. thanks, i'll add it to EXAMPLES.
Glad you like.  Getting something added to EXAMPLES has been a goal of mine...

I've been thinking, a bit, about a more general way of doing it.  I want
a "prefix-sub" function, like this
	prefix $some_path var1 var2 var3 var4 var5
That would take some_path and replace any leading $var1 (etc) values
with the variable name.  Return on the first match.

Hmm -- come to think of it, that's very easy to do:

# Use pathprefix filename var1 var2 var3
# returns filename, with leading prefixes (in $var1...) turned into the
# string $var1...
fn pathprefix { p1=() i=() j=() {
    p1=$1 ; shift
    for (i) {
	~ $p1 $$i $$i^/* && {
	    *=`` (/) { echo -n $p1 }
	    for (j in `` (/) { echo -n $$i } ) shift
	    p1='$'^$i
	    for (j) p1=$p1 ^ '/' ^ $j
	    echo $p1
	    return 0
	}
    }
    echo $p1
    return 0
} }

home=/user/users/rsalz
z=/usr/users
pathprefix /usr/users/rsalz home usr	# --> $home
pathprefix /usr/users/rsalz z		# --> $z/rsalz
pathprefix /usr/users/rsalz/foo z home	# --> $z/rsalz/foo
pathprefix /usr/users/rsalz/foo home	# --> $home/foo