Mail Delivery Problem

SMTP MAILER postmaster at ecf.ncsl.nist.gov
Sat Aug 11 21:21:49 AEST 1990


 ----Reason for mail failure follows----
Sending mail to host ecf.ncsl.nist.gov :
  Fatal reply code to command 'RCPT TO:<ise.ncsl.nist.gov at ecf.ncsl.nist.gov>':
  550 User "ise.ncsl.nist.gov" Unknown.


 ----Transcript of message follows----
Date: 11 Aug 90 06:45:00 EST
From: unix-wizards at BRL.MIL
Subject: UNIX-WIZARDS Digest  V10#113
To: "ise.ncsl.nist.gov" <ise.ncsl.nist.gov at ecf.ncsl.nist.gov>

Return-Path: <unixwiz-request at ecf.ncsl.nist.gov>
Received: from SEM.BRL.MIL by ecf.ncsl.nist.gov with SMTP ; 
          Sat, 11 Aug 90 06:44:47 EST
Received: from SEM.BRL.MIL by SEM.BRL.MIL id aa03279; 11 Aug 90 5:57 EDT
Received: from sem.brl.mil by SEM.BRL.MIL id aa03234; 11 Aug 90 5:45 EDT
Date:       Sat, 11 Aug 90 05:45:11 EST
From:       The Moderator (Mike Muuss) <Unix-Wizards-Request at BRL.MIL>
To:         UNIX-WIZARDS at BRL.MIL
Reply-To:   UNIX-WIZARDS at BRL.MIL
Subject:    UNIX-WIZARDS Digest  V10#113
Message-ID:  <9008110545.aa03234 at SEM.BRL.MIL>

UNIX-WIZARDS Digest          Sat, 11 Aug 1990              V10#113

Today's Topics:
                 Re: Cron - First Saturday of the month
                     Re: Streams message allocation
                              nested loops
                            Re: nested loops
                             waitpid() ???
                      unix sys v - uptime question
        Interesting keyboard read problem (ioctl, function keys)
                       sockets and signals (in C)
                     Re: sockets and signals (in C)
                       Re: Re.: UNdeleting files
             seeking information about file system details.
                  evaluating ${10} and above in sh/ksh
            Re: How variables can be specified as arguments
                               Re: ln -f

-----------------------------------------------------------------

From: Bob Strait <rls at svcs1.uucp>
Subject: Re: Cron - First Saturday of the month
Date: 9 Aug 90 17:13:32 GMT
To:       unix-wizards at sem.brl.mil

In article <19744 at orstcs.CS.ORST.EDU> curt at oce.orst.edu (Curt Vandetta) writes:
>  I'm wondering if anyone has a way of making cron run a job on the
>  first Saturday of every month?  
>

How about running your job each of the first seven days of every
month, and have the job first test whether it's Saturday and
exit if it's not.  There are several easy ways to do the test:
'date | grep Sat' comes to mind.
-- 
BUBBA	(aka Bob Strait)		...!mips!svcs1!rls
Silicon Valley Computer Society
Sunnyvale, CA
--

-----------------------------

From: Bob McGowen x4312 dept208 <bob at wyse.wyse.com>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 02:40:29 GMT
Sender: news at wyse.wyse.com
To:       unix-wizards at sem.brl.mil

In article <1990Aug8.185745.16606 at iwarp.intel.com> merlyn at iwarp.intel.com (Randal Schwartz) writes:
>In article <19744 at orstcs.CS.ORST.EDU>, curt at oce (Curt Vandetta) writes:
>|   I'm wondering if anyone has a way of making cron run a job on the
>|   first Saturday of every month?  
>
>3 4 1-7 * 6 command
>
>to make 'command' run at 4:03am... adjust the first two fields as
>necessary.  Remember, the parameters are "and"-ed together.
 ...flame deleted

My documentation states that a line like the one you have provided
would cause the command to run on EVERY Saturday as well as on each
of the first seven days in the month.

My flame--

I would be very interested if you could provide a cron only method
of getting my cron to execute on the first Saturday (or any other
day) such that it executes on that single day only.  My attempts at
solving this have been to combine cron to run the command on Saturday
and have command be a script that checks the date to be sure it is
less than or equal to 7.  But this only works for the first 13 days
so I have to figure out the next exclusion, probably to limit between
a start and stop.  In any case, getting cron to do what Curt wants is
a little more difficult.  Possibly (probably, I think) even wizard
caliber.

Bob McGowan  (standard disclaimer, these are my own ...)
Product Support, Wyse Technology, San Jose, CA
 ..!uunet!wyse!bob
bob at wyse.com

-----------------------------

From: Michael van Elst <p554mve at mpirbn.mpifr-bonn.mpg.de>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 14:28:35 GMT
Posted: Fri Aug 10 15:28:35 1990
To:       unix-wizards at sem.brl.mil

In article <1990Aug8.185745.16606 at iwarp.intel.com> merlyn at iwarp.intel.com (Randal Schwartz) writes:
>In article <19744 at orstcs.CS.ORST.EDU>, curt at oce (Curt Vandetta) writes:
>|   I'm wondering if anyone has a way of making cron run a job on the
>|   first Saturday of every month?  
>3 4 1-7 * 6 command
>to make 'command' run at 4:03am... adjust the first two fields as
>necessary.  Remember, the parameters are "and"-ed together.

>From the SunOS4.03 Manual:

Note: the specification of days may be made by two fields
(day of the month and day of the week). If both are specified
as a list of elements, both are adhered to. For example:

   0 0 1,15 * 1 command

would run a command on the first and the fifteenth of each month,
as well as on every Monday.
 .
 .

Seems that, at least here, your suggestion doesn't work.

-- 
Michael van Elst
UUCP:     universe!local-cluster!milky-way!sol!earth!uunet!unido!mpirbn!p554mve
Internet: p554mve at mpirbn.mpifr-bonn.mpg.de
                                "A potential Snark may lurk in every tree."

-----------------------------

From: Ed Anselmo <anselmo-ed at cs.yale.edu>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 16:42:38 GMT
Sender: news at cs.yale.edu
Nntp-Posting-Host: bigbird.cf.cs.yale.edu
To:       unix-wizards at sem.brl.mil

I peeked at the sources -- the BSD cron "ands" all the fields
together.

I don't have Sun 4.x sources, but under SunOS 4.0.3, I saw
the same behavior as David Canzi saw.

So, with a crontab like:

28 12 1-5 * 5 anselmo date > /homes/facility/anselmo/temp/www
28 12 7-11 * 1 anselmo date > /homes/facility/anselmo/temp/xxx
28 12 1-5 * 1 anselmo date > /homes/facility/anselmo/temp/yyy
28 12 7-11 * 5 anselmo date > /homes/facility/anselmo/temp/zzz

running on Fri Aug 10, under the BSD cron, only zzz got created.
Running under Sun 4.x cron (with the crontab entries suitably
modified), www, xxx, and zzz got created.
-- 
Ed Anselmo   anselmo-ed at cs.yale.edu   {harvard,cmcl2}!yale!anselmo-ed

-----------------------------

From: Maarten Litmaath <maart at cs.vu.nl>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 17:26:39 GMT
Sender: news at cs.vu.nl
To:       unix-wizards at sem.brl.mil

The manual (man 5 crontab on SunOS 4.0.3c):

     [...]
     Note: the specification of days may be made  by  two  fields
     (day  of the month and day of the week).  If both are speci-
     fied as a list of elements, both are adhered to.  For  exam-
     ple,

          0 0 1,15 * 1

     would run a command on  the  first  and  fifteenth  of  each
     month,  as well as on every Monday.  To specify days by only
     one field, the other field should be set to *.  For example,

          0 0 * * 1

     would run a command only on Mondays.
     [...]

The code:

	int
	match(cp, loct)
		register char **cp;
		register struct	tm *loct;
	{
		int	cancel_ex = 0;

		*cp = cmp(*cp, loct->tm_min, &cancel_ex);
		*cp = cmp(*cp, loct->tm_hour, &cancel_ex);
		*cp = cmp(*cp, loct->tm_mday, &cancel_ex);
		*cp = cmp(*cp, loct->tm_mon, &cancel_ex);
		*cp = cmp(*cp, loct->tm_wday, &cancel_ex);
		return(!cancel_ex);
	}

	char *
	cmp(p, v, cancel_ex)
	char *p;
	int *cancel_ex;
	{
		register char *cp;

		cp = p;
		switch(*cp++) {

		case EXACT:
			if (*cp++ != v)
				(*cancel_ex)++;
			return(cp);

		case ANY:
			return(cp);

		case LIST:
			while(*cp != LIST)
				if(*cp++ == v) {
					while(*cp++ != LIST)
						;
					return(cp);
				}
			(*cancel_ex)++;
			return(cp+1);

		case RANGE:
			if(cp[0] < cp[1]) {
				if(!(cp[0]<=v && cp[1]>=v))
					(*cancel_ex)++;
			} else if(!(v>=cp[0] || v<=cp[1]))
				(*cancel_ex)++;
			return(cp+2);
		}
		if(cp[-1] != v)
			(*cancel_ex)++;
		return(cp);
	}

The conclusion: the manual and the code contradict each other!
The example

          0 0 1,15 * 1

 ...will run the job on each monday whose date is either the 1st or the 15th!
It might be too late to fix the manual...  (Grrrr!)
--
   "UNIX was never designed to keep people from doing stupid things, because
    that policy would also keep them from doing clever things."  (Doug Gwyn)

-----------------------------

From: Chip Salzenberg <chip at tct.uucp>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 17:46:26 GMT
To:       unix-wizards at sem.brl.mil

According to dmcanzi at watserv1.waterloo.edu (David Canzi):
>if [ `date | sed 's/^... ...  *\([^ ]*\) .*/\1/'` -le 7 ]

At least on SysV, this is working too hard!  Use this instead:

	if [ "`date +%d`" -le 7 ]

Manual pages are wonderful things...
-- 
Chip Salzenberg at ComDev/TCT     <chip at tct.uucp>, <uunet!ateng!tct!chip>

-----------------------------

From: Maarten Litmaath <maart at cs.vu.nl>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 18:13:28 GMT

6 at star.cs.vu
Sender: news at cs.vu.nl
To:       unix-wizards at sem.brl.mil

In article <7286 at star.cs.vu.nl>, I wrote:
)The manual (man 5 crontab on SunOS 4.0.3c):
)...
)The code:
)...

I forgot to mention the code is _not_ SunOS 4.0.3c (still no up to date
sources...)
Anyway, my point still stands: _anding_ the fields is preferred (as Randal
already explained), but it might be too late to fix the specifications...
--
   "UNIX was never designed to keep people from doing stupid things, because
    that policy would also keep them from doing clever things."  (Doug Gwyn)

-----------------------------

From: Ronald S H Khoo <ronald at robobar.co.uk>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 19:05:17 GMT
To:       unix-wizards at sem.brl.mil

In article <1990Aug10.063819.5253 at iwarp.intel.com> merlyn at iwarp.intel.com (Randal Schwartz) writes:

> Sigh.  Sorry.  I'll crawl under my rock now.  Cron's only for the
> heavyweights, anyway.

System V cron isn't just for heavyweights, though, it's got per-user
crontabs, remember, so joe-random-non-wizard who has his own crontab
has to understand the manpage.  Sigh.

Someone once mentioned wanting to write a System V-like cron in perl
so he could have per-user crontabs on his machine.  I wonder who
it was, and how he parsed the manpage ?
-- 
Eunet: Ronald.Khoo at robobar.Co.Uk  Phone: +44 81 991 1142  Fax: +44 81 998 8343
Paper: Robobar Ltd. 22 Wadsworth Road, Perivale, Middx., UB6 7JD ENGLAND.

-----------------------------

From: Randal Schwartz <merlyn at iwarp.intel.com>
Subject: Re: Cron - First Saturday of the month
Date: 10 Aug 90 22:43:31 GMT

6 at star.cs.vu
Sender: news at iwarp.intel.com
To:       unix-wizards at sem.brl.mil

In article <7286 at star.cs.vu.nl>, maart at cs (Maarten Litmaath) writes:
| The code:
[deleted to protect my eyes, but it *is* the code I remember ...]
| The conclusion: the manual and the code contradict each other!
| The example
| 
|           0 0 1,15 * 1
| 
| ...will run the job on each monday whose date is either the 1st or the 15th!
| It might be too late to fix the manual...  (Grrrr!)

Yes, this is my point.  Actually, what I think happened is that you
posted the V7-derived cron, and Sunos4.1 went to the user-crontab
System (blech) V cron, and I suspect that they put some widgets in
there to do this stupid "OR" logic that I complained about in my last
two postings.

Anyone with access to system V source care to comment?  Are there some
yucky kludges in there?

Just another System V disliker,
-- 
/=Randal L. Schwartz, Stonehenge Consulting Services (503)777-0095 ==========\
| on contract to Intel's iWarp project, Beaverton, Oregon, USA, Sol III      |
| merlyn at iwarp.intel.com ...!any-MX-mailer-like-uunet!iwarp.intel.com!merlyn |
\=Cute Quote: "Welcome to Portland, Oregon, home of the California Raisins!"=/

-----------------------------

From: David Canzi <dmcanzi at watserv1.waterloo.edu>
Subject: Re: Cron - First Saturday of the month
Date: 11 Aug 90 03:08:18 GMT
To:       unix-wizards at sem.brl.mil

In article <1990Aug8.214539.1264 at watserv1.waterloo.edu> I wrote:
>In a sh script, it can be done by:
>
>if [ `date | sed 's/^... ...  *\([^ ]*\) .*/\1/'` -le 7 ]; then
>	...
>fi

This is better done using awk:

if [ `date | awk '{print $3}'` -le 7 ]; then
	...
fi

-- 
David Canzi

-----------------------------

From: Larry McVoy <lm at snafu.sun.com>
Subject: Re: Streams message allocation
Keywords: streams deadlock
Date: 9 Aug 90 17:21:06 GMT
Sender: news at sun.eng.sun.com
To:       unix-wizards at sem.brl.mil

In article <1990Aug2.043059.578 at cbnewsl.att.com> sar0 at cbnewsl.att.com (stephen.a.rago) writes:
>The number of messages needed per buffer class (size) is something that
>can only be determined statistically or empirically.  In the absence of
>information like inter-arrival rate of allocation requests and message
>hold times, the best way to proceed is to start with an educated guess
>of how many messages you may need.  

Here's a package I wrote a few years ago when tuning STREAMS for SCO XENIX
(I was porting the LAI TCP/IP to XENIX and tuning was really critical).

Use this while your system is under a "normal" load and it will give you a
pretty good idea of where to set things.  No promises that it works -
it worked on SCO XENIX a while ago, beyond that you're on your own.  If
you have SCO XENIX & TCP/IP you should have this program already.



# This is a shell archive.  Remove anything before this line, then
# unpack it by saving it in a file and typing "sh file".  (Files
# unpacked will be owned by you and have default permissions.)
#
# This archive contains:
# Makefile mode.c sw.1 sw.c term.h termcap.c

echo x - Makefile
cat > "Makefile" << '//E*O*F Makefile//'
O = sw.o termcap.o mode.o
S = Makefile sw.1 sw.c termcap.c mode.c term.h
#CFLAGS=-DUNIX=\"/xenix\" -DKMEM=\"/dev/mem\" -DSAVECNT=0
BIN=/usr/local/bin

all sw: $O
	cc $O -ltermlib -o sw 
install: sw
	cp sw $(BIN)
	chown root $(BIN)/sw
	chmod 4755 $(BIN)/sw
clean:
	rm -f $O a.out core shar
clobber: clean
	rm -f sw
shar:
	shar $S > shar
//E*O*F Makefile//

echo x - mode.c
cat > "mode.c" << '//E*O*F mode.c//'
/*
 * copyright (C) 1986 by Larry McVoy
 * MUST be distributed in source form only.
 */
# include	<stdio.h>
# include	<sgtty.h>
# include	<fcntl.h>

static struct sgttyb buf;
static done = 0;

delay(on)
{
    if (on) {
	int flags;
	fcntl(0, F_GETFL, &flags);
	flags &= ~O_NDELAY;
	return fcntl(0, F_SETFL, flags);
    }
    else {
	return fcntl(0, F_SETFL, O_NDELAY);
    }
}

cbreak(on)
{
    if (!done) {
	ioctl(fileno(stdin), TIOCGETP, &buf);
	done++;
    }

    if (on) {
	buf.sg_flags |= CBREAK;
	ioctl(fileno(stdin), TIOCSETP, &buf);
    }
    else {
	buf.sg_flags &= ~CBREAK;
	ioctl(fileno(stdin), TIOCSETP, &buf);
    }
}

echo(on)
{
    if (!done) {
	ioctl(fileno(stdin), TIOCGETP, &buf);
	done++;
    }

    if (on) {
	buf.sg_flags |= ECHO;
	ioctl(fileno(stdin), TIOCSETP, &buf);
    }
    else {
	buf.sg_flags &= ~ECHO;
	ioctl(fileno(stdin), TIOCSETP, &buf);
    }
}
//E*O*F mode.c//

echo x - sw.1
cat > "sw.1" << '//E*O*F sw.1//'
 .TH SW 1
 .UC 4
 .SH NAME
sw - (stream watch) watch streams resources on System V
 .SH SYNOPSIS
 .B sw
 .SH DESCRIPTION
 .I Sw
digs into kmem to find out how many streams, queues, message blocks, and data
blocks are in use.  It find this in the \fIstruct strstat strst\fR variable.
For each category mentioned above the following fields are printed:
 .IP Use 
(strst.use)
How many of the resource in question are in use.
 .IP "Ave10, Ave30, Ave60, Ave120"
As above, only the value is averaged over the last N iterations 
(an iteration is
about one second).
 .IP Total 
(strst.total)
The total number of the resource used since boot time or the last time it
was cleared.
 .IP Max 
(strst.max)
The maximum number of the resource allocated at the same time.
 .IP Fail 
(strst.fail)
The number of times a request was made, for the resource, that could not
be granted.
 .PP
The data block section is further broken down into sub classes.  This section 
has a slightly different format; in the title section the field is 
\fISiz<#> Count <#>\fR, where the first number is the data block size and
the second number is the number of data blocks statically allocated.
 .PP
The screen is managed by curses.  It will respond to:
 .IP c
clear the total max & fail fields (you have to have write permission on
/dev/mem).
 .IP ^L
redraw the screen.
 .IP N
Where N is 0-9.  Set the number of seconds between interations.
 .IP q
(quit) Quit the program.
 .IP ^L
(Control-L) Refresh the screen.
 .SH FILES
 .DT
/dev/kmem	kernel memory
 .br
/unix		for getting variable addresses
 .SH BUGS
The definitions of the various fields is my best guess, they do not reflect
any AT&T documentation that I've read.
 .SH COPYRIGHT
\fBSw\fR is copyright 1988 by Larry McVoy.  Permission is hereby granted to
publish strings in source or object form as long as all copyright notices
are retained.  Object-only distributions are permitted only if the source
is also freely available from the distributer.  Any fee charged for such
publication may consist only of a reasonable charge for any media used.
 .SH AUTHOR
Larry McVoy (lm at eng.sun.com)
//E*O*F sw.1//

echo x - sw.c
cat > "sw.c" << '//E*O*F sw.c//'
/*
 * copyright 1988 by Larry McVoy.  All rights reserved.
 * If you redistribute this you must distribute in source form.
 */
#include "term.h"
#include <signal.h>
#ifdef M_XENIX
#include <a.out.h>
#else
#include <nlist.h>
#endif
#include <ctype.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/strstat.h>
#include <sys/var.h>
#if defined(M_XENIX)  ||  defined(sys5)
#include <sys/utsname.h>
#endif
#ifndef UNIX
#define	UNIX		"/vmunix"
#endif
#ifndef KMEM
#define	KMEM		"/dev/kmem"
#endif
#ifdef M_XENIX
#define	v_nblk4096	v_nblk8192
#endif
#ifdef sun
#define NCLASS 9
#endif
#ifndef SAVECNT
#define SAVECNT		121
#endif
#define kbytes(x)	( ((x)+1023) >> 10)

#ifdef M_XENIX
#define nlist xlist
#define n_value xl_value
#define n_name xl_name
struct nlist nl[] = {
#define	NL_STRST	0
	{0,0,0,"_strst"},
#define	NL_RBSIZE	1
	{0,0,0,"_rbsize"},
#define	NL_V		2
	{0,0,0,"_v"},
#define	NL_DBALLOC	3
	{0,0,0,"_dballoc"},
#define	NL_NMBLOCK	4
	{0,0,0,"_nmblock"},
	{0,0,0,(char *) 0},
};
#else
#ifdef sys5
struct nlist nl[] = {
#define	NL_STRST	0
	{"_strst"},
#define	NL_RBSIZE	1
	{"_rbsize"},
#define	NL_V		2
	{"_v"},
#define	NL_DBALLOC	3
	{"_dballoc"},
#define	NL_NMBLOCK	4
	{"_nmblock"},
	{ 0 },
};
#else
#ifdef sun
char* nl_names[] = {
#define	NL_STRST	0
	"_strst",
#define	NL_RBSIZE	1
	"_rbsize",
#define	NL_NDBLKS	2
	"_ndblks",
#define	NL_DBALLOC	3
	"_dballoc",
#define	NL_NMBLOCK	4
	"_nmblock",
	"",
};

struct nlist nl[sizeof(nl_names)/sizeof(char*)];
#endif	/* sun */
#endif	/* sys5 */
#endif	/* M_XENIX */

ushort rbsize[NCLASS];
short cnt[NCLASS];
struct dbalcst dballoc[NCLASS];
int total, ndblock, nmblock, fd, sleeptime = 1;
#ifndef sun
struct var v;
#endif
typedef struct {
    alcdat stream;
    alcdat queue;
    alcdat mblock;
    alcdat dblock;
    alcdat dblk[NCLASS];
} Strstat;
Strstat strst;

/*
 * It's the main thing...
 */
main(ac, av)
    char** av;
{
    int* p;
    int i;
    int done();

    for (i=1; i<ac; ++i) {
	 if (av[i][0] == '-')
	    if (isdigit(av[i][1]))
		sleeptime = atoi(&av[i][1]);
    }
/*
 * get stuff from kmem
 */
# ifdef sun
    for (i=0; i<sizeof(nl_names)/sizeof(char*); ++i)
	nl[i].n_name = nl_names[i];
# endif
    if (nlist(UNIX, nl))
	error("nlist");
    if (((fd = open(KMEM, 2)) == -1)  && ((fd = open(KMEM, 0)) == -1))
	error(KMEM);
    readstuff();
# ifdef sun
    for (i=0; i<NCLASS; ndblock += cnt[i++])
	;
# else
    for (i=0, p= &v.v_nblk4096; i<NCLASS; ndblock += (cnt[NCLASS - ++i] = *p++))
	;
# endif
/*
 * screen/mode stuff
 */
    termcap();;
    echo(0);
    cbreak(1);
    delay(0);
    signal(SIGHUP, done);
    signal(SIGINT, done);
    signal(SIGQUIT, done);
    signal(SIGTERM, done);
    screen();
/*
 * display until quit
 */
    for ( ;; ) {
	if (lseek(fd, nl[NL_STRST].n_value, 0) == -1)
	    error("lseek");
	if (read(fd, &strst, sizeof(strst)) != sizeof(strst))
	    error("read");
	dump(&strst);
	for (i=0; i<sleeptime; ++i) {
	    if (input())
		break;
	    sleep(1);
	}
	input();
    }
}

/*
 * look for commands; expect to be in cbreak mode
 */
input()
{
    char c;

    if (read(0, &c, 1) != 1)
	return 0;
    switch (c) {
    case 'c':
	clearstuff();
	return 1;
    case '':
	screen();
	return 1;
    case 'q':
	done();
    case '0': case '1': case '2': case '3': case '4':
    case '5': case '6': case '7': case '8': case '9':
	sleeptime = c - '0';
	Pause();
	return 1;
    case '?':
    case 'h':
	clear();
	tprint("", 0, 0);
	printf("\nOptions are\n");
	printf("\tc\tclear total, max, and fail fields\n");
	printf("\t^L\trefresh the screen\n");
	printf("\tq\tquit\n");
	printf("\tN\twhere N is a number 0..9 for the delay between refresh\n");
	printf("Hit any key to continue....\n");
	while (read(0, &c, 1) != 1)
	    sleep(1);
	screen();
	return 1;
    default:
	return 0;
    }
}

/*
 * clear the total, max, and fail fields
 *
 * N.B. assumes acldat is use, total, max, fail
 * and there are NCLASS+4 acldat's in a strstat
 */
clearstuff()
{
    static int clr[3];
    register i;

    clear();
    lseek(fd, nl[NL_STRST].n_value+sizeof(int), 0);
    for (i=0; i<NCLASS+4; ++i) {
	if (write(fd, clr, sizeof(clr)) != sizeof(clr))
	    perror("write");
	lseek(fd, sizeof(int), 1);
    }
    screen();
}

/*
 * display the "once only" stuff
 */
screen()
{
    char buf[200];
    register i;
#if defined(M_XENIX)  ||  defined(sys5)
    struct utsname u;
#else
    char host[100];
#endif

    clear();
#if defined(M_XENIX)  ||  defined(sys5)
    uname(&u);
    sprintf(buf, "Host=%s", u.nodename);
#else
    gethostname(host, sizeof(host));
    sprintf(buf, "Host=%s", host);
#endif
    tprint(buf, 50, 0);
# if SAVECNT > 0
    sprintf(buf, "%11s%5s%6s%6s%6s%6s%7s%8s%8s%8s", 
	"Resource", "Cnt", "Use", "Ave10", "Ave30", "Ave60", "Ave120", "Total", 
	"Max", "Fail");
# else
    sprintf(buf, "%11s%5s%10s%8s%8s%8s", 
	"Resource", "Cnt", "Use", "Total", "Max", "Fail");
# endif
    tprint(buf, 0, 2);
# ifdef sun
    sprintf(buf, "%11s:%4s",  "stream", "?");
    tprint(buf, 0, 3);
    sprintf(buf, "%11s:%4s",  "queue", "?");
    tprint(buf, 0, 4);
# else
    sprintf(buf, "%11s:%4d",  "stream", v.v_nstream);
    tprint(buf, 0, 3);
    sprintf(buf, "%11s:%4d",  "queue", v.v_nqueue); 
    tprint(buf, 0, 4);
# endif
    sprintf(buf, "%11s:%4d",  "mblock", nmblock); 
    tprint(buf, 0, 5);
    sprintf(buf, "%11s:%4d",  "dblk totals", ndblock); 
    tprint(buf, 0, 6);
# if SAVECNT > 0
    sprintf(buf, "%4s%4s%4s%4s%6s%6s%6s%6s%7s%8s%8s%8s", 
	"Size", "Cnt", "Med", "Low", "Use", "Ave10", "Ave30", "Ave60", "Ave120", "Total", "Max", "Fail");
# else
    sprintf(buf, "%-4s%4s%4s%4s%4s%6s%8s%8s%8s", 
	"Mem", "Size", "Cnt", "Med", "Low", "Use", "Total", "Max", "Fail");
# endif
    tprint(buf, 0, 8);
    for (total=i=0; i<NCLASS; ++i) {
	register lo = dballoc[i].dba_lo;
	register med = dballoc[i].dba_med;

	total += rbsize[i] * cnt[i];
# if SAVECNT > 0
	sprintf(buf, "%4d %3d %3d %3d", rbsize[i], cnt[i], med, lo);
# else
	sprintf(buf, "%3d %4d %3d %3d %3d", kbytes(rbsize[i] * cnt[i]), 
	    rbsize[i], cnt[i], med, lo);
# endif
	tprint(buf, 0, 9 + i);
    }
    sprintf(buf, "Buffers (used/total) = ");
    tprint(buf, 0, 23);
    Pause();
}

Pause()
{
    char buf[40];

    sprintf(buf, "Pause=%d", sleeptime);
    tprint(buf, 0, 0);
}

# if SAVECNT == 0
/*
 * display the information, called once per second (about)
 *
 * No averaging version
 */
dump(s)
    register struct strstat* s;
{
    char buf[80];
    register i, mem = 0;
    static calls = 0;

    sprintf(buf, "%6d%8d%8d%8d",
	s->stream.use, s->stream.total, s->stream.max, s->stream.fail);
    tprint(buf, 20, 3);
    sprintf(buf, "%6d%8d%8d%8d",
	s->queue.use, s->queue.total, s->queue.max, s->queue.fail);
    tprint(buf, 20, 4);
    sprintf(buf, "%6d%8d%8d%8d",
	s->mblock.use, 
	s->mblock.total, s->mblock.max, s->mblock.fail);
    tprint(buf, 20, 5);
    sprintf(buf, "%6d%8d%8d%8d",
	s->dblock.use, s->dblock.total, s->dblock.max, s->dblock.fail);
    tprint(buf, 20, 6);
    for (i=0; i<NCLASS; ++i) {
	mem += s->dblk[i].use * rbsize[i];
	sprintf(buf, "%6d%8d%8d%8d",
	    s->dblk[i].use, s->dblk[i].total, s->dblk[i].max, s->dblk[i].fail);
	tprint(buf, 20, 9 + i);
    }
    sprintf(buf, "%d/%d Kbytes", kbytes(mem), kbytes(total));
    tprint(buf, 23, 23);
    calls++;
    sprintf(buf, "Calls=%d", calls);
    tprint(buf, 10, 0);
}
# else
/*
 * display the information, called once per second (about)
 *
 * Averaging version
 */
dump(s)
    register struct strstat* s;
{
    char buf[80];
    register i, j, b10, b30, b60, b120, mem = 0;
    static struct strstat pst[SAVECNT];
    static struct strstat sum10, sum30, sum60, sum120;
    static calls = 0;

    j = calls % SAVECNT;
    b10 = (j + SAVECNT - 10) % SAVECNT;
    b30 = (j + SAVECNT - 30) % SAVECNT;
    b60 = (j + SAVECNT - 60) % SAVECNT;
    b120 = (j + SAVECNT - 120) % SAVECNT;
    memcpy(&pst[j], s, sizeof(struct strstat));
    addstrst(s, &sum10);
    addstrst(s, &sum30);
    addstrst(s, &sum60);
    addstrst(s, &sum120);
    if (!calls) {
	mulstrst(&sum10, 10);
	mulstrst(&sum30, 30);
	mulstrst(&sum60, 60);
	mulstrst(&sum120, 120);
	for (i=1; i<SAVECNT; ++i)
	    memcpy(&pst[i], s, sizeof(struct strstat));
    }
    else {
	substrst(&pst[b10], &sum10);
	substrst(&pst[b30], &sum30);
	substrst(&pst[b60], &sum60);
	substrst(&pst[b120], &sum120);
    }
    sprintf(buf, "%6d%6d%6d%6d%7d%8d%8d%8d",
	s->stream.use, 
	sum10.stream.use / 10, sum30.stream.use / 30, sum60.stream.use / 60,
	sum120.stream.use / 120,
	s->stream.total, s->stream.max, s->stream.fail);
    tprint(buf, 16, 3);
    sprintf(buf, "%6d%6d%6d%6d%7d%8d%8d%8d",
	s->queue.use, 
	sum10.queue.use / 10, sum30.queue.use / 30, sum60.queue.use / 60,
	sum120.queue.use / 120,
	s->queue.total, s->queue.max, s->queue.fail);
    tprint(buf, 16, 4);
    sprintf(buf, "%6d%6d%6d%6d%7d%8d%8d%8d",
	s->mblock.use, 
	sum10.mblock.use / 10, sum30.mblock.use / 30, sum60.mblock.use / 60,
	sum120.mblock.use / 120,
	s->mblock.total, s->mblock.max, s->mblock.fail);
    tprint(buf, 16, 5);
    sprintf(buf, "%6d%6d%6d%6d%7d%8d%8d%8d",
	s->dblock.use, 
	sum10.dblock.use / 10, sum30.dblock.use / 30, sum60.dblock.use / 60,
	sum120.dblock.use / 120,
	s->dblock.total, s->dblock.max, s->dblock.fail);
    tprint(buf, 16, 6);
    for (i=0; i<NCLASS; ++i) {
	mem += s->dblk[i].use * rbsize[i];
	sprintf(buf, "%6d%6d%6d%6d%7d%8d%8d%8d",
	    s->dblk[i].use, 
	    sum10.dblk[i].use / 10, sum30.dblk[i].use / 30, 
	    sum60.dblk[i].use / 60, sum120.dblk[i].use / 120,
	    s->dblk[i].total, s->dblk[i].max, s->dblk[i].fail);
	tprint(buf, 16, 9 + i);
    }
    sprintf(buf, "%d/%d Kbytes", kbytes(mem), kbytes(total));
    tprint(buf, 23, 23);
    calls++;
    sprintf(buf, "Calls=%d", calls);
    tprint(buf, 10, 0);
}

/*
 * add a to be, leave result in b
 *
 * N.B. Assumes that elements are ints
 */
addstrst(a, b)
    register alcdat* a;
    register alcdat* b;
{
    register i;

    for (i=sizeof(struct strstat)/sizeof(*a); i--; (b++)->use += (a++)->use)
	;
}

/*
 * subtract a from be, result in b
 */
substrst(a, b)
    register alcdat* a;
    register alcdat* b;
{
    register i;

    for (i=sizeof(struct strstat)/sizeof(*a); i--; (b++)->use -= (a++)->use)
	;
}

/*
 * multiply a by b, result in a
 */
mulstrst(a, b)
    register alcdat* a;
    register int b;
{
    register i;

    for (i=sizeof(struct strstat)/sizeof(*a); i--; (a++)->use *= b)
	;
}
# endif	/* SAVECNT */

/*
 * nasty cleanup
 */
error(s)
    char* s;
{
    perror(s);
    done();
}

/*
 * nice cleanup
 */
done()
{
    echo(1);
    cbreak(0);
    delay(1);
    tprint("", cols -1, lines - 1);
    printf("\n");
    exit(0);
}

/*
 * read all once only stuff from kmem
 */
readstuff()
{
    register i;
    if (!nl[NL_RBSIZE].n_value) {
	printf("%s: no value\n", nl[NL_RBSIZE].n_name);
	exit(1);
    }
    if (!nl[NL_STRST].n_value) {
	printf("%s: no value\n", nl[NL_STRST].n_name);
	exit(1);
    }
# ifdef sun
    if (!nl[NL_NDBLKS].n_value) {
	printf("%s: no value\n", nl[NL_NDBLKS].n_name);
# else
    if (!nl[NL_V].n_value) {
	printf("%s: no value\n", nl[NL_V].n_name);
# endif
	exit(1);
    }
    if (!nl[NL_DBALLOC].n_value) {
	printf("%s: no value\n", nl[NL_DBALLOC].n_name);
	exit(1);
    }
    if (!nl[NL_NMBLOCK].n_value) {
	printf("%s: no value\n", nl[NL_NMBLOCK].n_name);
	exit(1);
    }
    if (lseek(fd, nl[NL_RBSIZE].n_value, 0) == -1)
	error("lseek");
    if (read(fd, rbsize, sizeof(rbsize)) != sizeof(rbsize))
	error("read");
# ifdef sun
    if (lseek(fd, nl[NL_NDBLKS].n_value, 0) == -1)
	error("lseek");
    if (read(fd, cnt, sizeof(cnt)) != sizeof(cnt))
	error("read");
# else
    if (lseek(fd, nl[NL_V].n_value, 0) == -1)
	error("lseek");
    if (read(fd, &v, sizeof(v)) != sizeof(v))
	error("read");
# endif
# ifdef sun
    if (lseek(fd, nl[NL_DBALLOC].n_value, 0) == -1)
	error("lseek");
    if (read(fd, &nl[NL_DBALLOC].n_value, sizeof(int)) != sizeof(int))
	error("read");
# endif
    if (lseek(fd, nl[NL_DBALLOC].n_value, 0) == -1)
	error("lseek");
    if (read(fd, dballoc, sizeof(dballoc)) != sizeof(dballoc))
	error("read");
    if (lseek(fd, nl[NL_NMBLOCK].n_value, 0) == -1)
	error("lseek");
    if (read(fd, &nmblock, sizeof(nmblock)) != sizeof(nmblock))
	error("read");
# ifdef sun
    if (lseek(fd, nl[NL_STRST].n_value, 0) == -1)
	error("lseek");
    if (read(fd, &nl[NL_STRST].n_value, sizeof(int)) != sizeof(int))
	error("read");
# endif
}
//E*O*F sw.c//

echo x - term.h
cat > "term.h" << '//E*O*F term.h//'
# ifndef	_TERM_H_
#include <stdio.h>
#include <sgtty.h>

char	*getenv();
char	*tgetstr();
char	PC;
short	ospeed;
short	lines;
short	cols;
char 	ceolbuf[20];
char 	clbuf[20];
char 	pcbuf[20];
char 	cmbuf[20];
#undef	putchar
int	putchar();
char 	term_buf[1024];

# endif	_TERM_H_
//E*O*F term.h//

echo x - termcap.c
cat > "termcap.c" << '//E*O*F termcap.c//'
/*
 * copyright (C) 1986 by Larry McVoy
 * MUST be distributed in source form only.
 */
# include	"term.h"

char* tgoto();

/*------------------------------------------------------------------15/Dec/86-*
 * init_term - read in the termcap stuff
 *----------------------------------------------------------------larry mcvoy-*/
termcap()
{
    char *cp = getenv("TERM");
    char *foo;
    char garbage[10];
    struct sgttyb tty;

    gtty(1, &tty);
    ospeed = tty.sg_ospeed;
    if (cp == (char *) 0)
	    return -1;
    if (tgetent(term_buf, cp) != 1)
	    exit(1);
    foo = garbage;
    foo = tgetstr("pc", &foo);
    if (foo)
	    PC = *foo;
    foo = clbuf;
    tgetstr("cl", &foo);
    foo = ceolbuf;
    tgetstr("ce", &foo);
    foo = cmbuf;
    tgetstr("cm", &foo);
    lines = tgetnum("li");
    cols = tgetnum("co");
    return 0;
}

/* clear to end of line */
ceol(col, row)
{
    char *foo = tgoto(cmbuf, col, row);

    write(1, foo, strlen(foo));
    tputs(ceolbuf, 1, putchar);
}

/* clear screen */
clear()
{
    tputs(clbuf, lines, putchar);
}

/*------------------------------------------------------------------15/Dec/86-*
* tputchar(c, col, row) - put a single char on the screen
*
* Inputs ----> (char), (int), (int)
*
* Bugs ------> Assumes that the coords make sense
*
* Revisions:   
*----------------------------------------------------------------larry mcvoy-*/
tputchar(c, col, row)
    char c;
{
    register char* foo;

    foo = tgoto(cmbuf, col, row);
    tputs(foo, lines, putchar);
    write(1, &c, 1);
}

/*------------------------------------------------------------------15/Dec/86-*
* tprint(s, col, row) - put a string on the screen
*
* Inputs ----> (char), (int), (int)
*
* Results ---> Puts the string out iff it will fit.
*
* Revisions:   
*----------------------------------------------------------------larry mcvoy-*/
tprint(s, col, row)
    register char* s;
{
    register char* foo;

    if (row > lines  ||  col > cols)
	return -1;

    if (strlen(s) > cols - col)
	return -2;

    foo = tgoto(cmbuf, col, row);
    tputs(foo, lines, putchar);
    return write(1, s, strlen(s));
}

/* fake putchar for tputs */
putchar(c)
char c;
{
    write(1, &c, 1);
}
//E*O*F termcap.c//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      17      53     336 Makefile
      57     120     878 mode.c
      63     359    2087 sw.1
     563    1521   12403 sw.c
      19      36     278 term.h
     104     281    2203 termcap.c
     823    2370   18185 total
!!!
wc  Makefile mode.c sw.1 sw.c term.h termcap.c | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
---
Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm at sun.com

-----------------------------

From:  iccad <adley at herbie.misemi>
Subject: nested loops
Date: 9 Aug 90 19:17:28 GMT
To:       unix-wizards at sem.brl.mil

Hi,
We are trying to write a Bourne shell script that includes two 
nested loops as follows

!# /bin/sh
this="one two three"
that="four five six seven"
them="eight nine ten"
all="this that them"
#
for i in $all
do
for j in $`echo $i`
do
echo $i $j
done
done


we want (and expected!) the output:
this one
this two
this three
that four
that five
that six
that seven
them eight
them nine
them ten

The problem lies in the  $`echo $i` statment
the `echo $i` preforms as expected and the result is one of this,
that, or them
the $ infront of this statment however is taken as a literal $
and does not return the value of the variable this or that or them
instead it returns $this or $that or $them.

Does anybody know why this happens or how we can get the results 
that would be expected here (with the exception of doing it in a 
C shell or in a C program).

Thanks.

-----------------------------

From: Gilles Courcoux <gilles at pase60.convergent.com>
Subject: Re: nested loops
Date: 10 Aug 90 16:15:51 GMT
Sender: root at risky.convergent.com
To:       unix-wizards at sem.brl.mil

In article <4103 at herbie.misemi> you wrote:
>The problem lies in the  $`echo $i` statment

Right, double variable expansion like that is resolved through the use
of the eval(1) command as in :
	eval echo '$'$i

When the shell read the command, it expands it into 
	eval echo $them			# the first time !

and then eval(1) do his job : evaluating its arguments, including
variables expansion and then execute the command which is by now :
	echo one two three

The echo(1) command is needed because eval(1) then exec(2)utes its
first argument.

Your script become :

this="one two three"
that="four five six seven"
them="eight nine ten"
all="this that them"
#
for i in $all
do
	for j in `eval echo '$'$i`
	do
	echo $i $j
	done
done

Have a nice day,

Gilles Courcoux                        E-mail: sun!pyramid!ctnews!pase60!gilles
Unisys Network Computing Group         Phone:  (408) 435-7692

-----------------------------

From: Chet Ramey <chet at cwns1.INS.CWRU.Edu>
Subject: Re: nested loops
Date: 10 Aug 90 19:28:41 GMT
Sender: news at usenet.ins.cwru.edu
To:       unix-wizards at sem.brl.mil

In article <4103 at herbie.misemi> adley at herbie.misemi ( iccad) writes:

$ !# /bin/sh
$ this="one two three"
$ that="four five six seven"
$ them="eight nine ten"
$ all="this that them"
$ #
$ for i in $all
$ do
$ for j in $`echo $i`
$ do
$ echo $i $j
$ done
$ done

$ The problem lies in the  $`echo $i` statment
$ the `echo $i` preforms as expected and the result is one of this,
$ that, or them
$ the $ infront of this statment however is taken as a literal $
$ and does not return the value of the variable this or that or them
$ instead it returns $this or $that or $them.

Use `eval'.

Chet
-- 
Chet Ramey				``Levi Stubbs' tears run down
Network Services Group			  his face...''
Case Western Reserve University	
chet at ins.CWRU.Edu		

-----------------------------

From: Mitch Wright <mitch at hq.af.mil>
Subject: waitpid() ???
Date: 10 Aug 90 04:20:07 GMT
Sender: mitch at hq.af.mil
To:       unix-wizards at sem.brl.mil

Greetings!

	I was recently flipping through the source of ksh(1), humbly
admiring the work of David Korn, when I came across a function called
waitpid().  I quickly grep'ed through the code to see if I could find
where this function was defined, since I was not aware of a system call 
by this name.  Well, I found no definition for this call in the code or
in the few SYSV programming manuals that I have.  Does anyone have an
idea exactly what this call does?  Since it is in the middle of the job
control routines, I'd assume it was similar to wait3() in the Bezerkely
world, but the parameters seem to be out of whack, and all three of them
are integers instead of 1 int, 1 union wait *, and a struct rusage *.

	A man-page would be fine, but I'd prefer not only a man page, but
a *real* description of what this puppy does.

	Thanks!

--
   ..mitch

   mitch at hq.af.mil (Mitch Wright) | The Pentagon, 1B1046 | (202) 695-0262

   The two most common things in the universe are hydrogen and stupidity,
   but not necessarily in that order. 

-----------------------------

From: Boy named Superuser <root at storm.uucp>
Subject: unix sys v - uptime question
Date: 10 Aug 90 06:00:43 GMT
To:       unix-wizards at sem.brl.mil

Does anyone out there know how to get Unix sys V/386 (sco) to display
load averages. The man pages say that uptime "displays the load averages 
over 1 5 and 15 minutes" on "systems that maintain the necessary data."
However, I cannot seem to find out how to get the system to keep the 
necessary data. Can anyone out there help?

Thanks!

root at storm.uucp@skinner.cs.uoregon.edu

-----------------------------

From: Devon Tuck <tuck at iris.ucdavis.edu>
Subject: Interesting keyboard read problem (ioctl, function keys)
Date: 10 Aug 90 08:10:33 GMT
Sender: usenet at ucdavis.ucdavis.edu
To:       unix-wizards at sem.brl.mil

Hey wizards,

I have been working with an intersting problem...  How to write a keyboard 
input routine that does not mess up its' transmission of repeated function
keys.  You might have noticed that even in vi, and in the C-shell, if you
sit on an arrow key or some other function key that maps to a character
sequence, you get intermittent beeps, or stray characters, respectively.

I am porting an editor for a bunch of users who are in deep wedlock with
their function keys, and they MUST be able to sit on their little arrow
keys and not lose any characters, BUT character throughput must be VERY
FAST.

The problem is that this editor is very bulky, and spends too much time
away from the keyboard input routine, so that if I do the logical thing
and set VMIN=1 and VTIME=0, portions of the home key sequence (<ESC>[H),
for example, get split across network packets and arrive with too much gap
for the keyboard driver to consider it a valid screen movement sequence.

Has anyone solved this problem?  I think I might have it with a routine that
forks on its' first call, after setting up a pipe and ioctl calls, (VMIN=0,
VTIME=0) and thus leaves a small subprocess running alongside the editor
acting as a slave to the keyboard and sending all characters into a pipe
to be read at the leasure of the main character input routine.

How do other editors do it?  How do Crisp, emacs, etc. handle this? (as I
mentioned, vi doesn't..)

Thanks,
	Devon Tuck
	tuck at iris.ucdavis.edu

PS - Incidentally, when I use a straight character read with VMIN>=1,
VTIME=1 the input is still too slow.

-----------------------------

From: Steve Perryman  <skp at stl.stc.co.uk>
Subject: sockets and signals (in C)
Date: 10 Aug 90 08:45:16 GMT
Sender: news at stl.stc.co.uk
To:       unix-wizards at sem.brl.mil


Does anyone know of a way to set up a signal handler such that if a flood
of data comes in to a socket, the SIGIO/SIGPOLL (maybe even SIGURG) signal
can invoke a handler fast enough such that a variable can be incremented to
represent the correct number of data items at the socket.

The signal handler will be :

void catch()
{
   signal(SIGIO,catch) ;
   count++ ;
   ...
   /* Process the signal */
   ...
}

I've used fcntl to allow the socket to interrupt :

fcntl(sock,F_SETOWN,getpid()) ;
fcntl(sock,F_SETFL,F_ASYNC) ;
 ...
 ...

This works but it can't log the correct number of items received if they come
in as bursts of data (5+ items per burst). Can this timing problem be resolved
using SIGIO , or is another way required ???




skp

-----------------------------

From: Larry McVoy <lm at snafu.sun.com>
Subject: Re: sockets and signals (in C)
Date: 10 Aug 90 18:49:12 GMT
Sender: news at sun.eng.sun.com
To:       unix-wizards at sem.brl.mil

In article <3304 at stl.stc.co.uk> "Steve Perryman " <skp at stl.stc.co.uk> writes:
>
>Does anyone know of a way to set up a signal handler such that if a flood
>of data comes in to a socket, the SIGIO/SIGPOLL (maybe even SIGURG) signal
>can invoke a handler fast enough such that a variable can be incremented to
>represent the correct number of data items at the socket.
>
>This works but it can't log the correct number of items received if they come
>in as bursts of data (5+ items per burst). Can this timing problem be resolved
>using SIGIO , or is another way required ???

This can't be done with Unix signals.  Unix signals don't stack, i.e., if
you hit yout interrupt character several times before the kernel delivers 
the signal, the application will only see one signal.

About the best you can do for you application is to use sigio as a hint that
there is data waiting and schedule a timeout every second or so to collect
what you might have missed.  It's also a good idea to code your processing
like so:


	for ( ;; ) {
		sigpause(0);
		while (more_data()) {
			process_data();
		}
	}

rather than

	for ( ;; ) {
		sigpause(0);
		if (more_data()) {
			process_data();
		}
	}
---
Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm at sun.com

-----------------------------

From: Kishore Seshadri <kseshadr at quasar.intel.com>
Subject: Re: Re.: UNdeleting files
Date: 10 Aug 90 14:51:06 GMT
Sender: news at inews.intel.com
To:       unix-wizards at sem.brl.mil

In article <7410002 at hpfcmgw.HP.COM>, munir at hpfcmgw (Munir Mallal) writes:
>>>A similar thing has just happened here, and we don't have fsdb either.
>>>The machine has been untouched since the directory was deleted.
>>>Any suggestions ?
>>
>    >Whether done with fsdb or not, the task is to read the disk
>    >partition block by block, check each block to determine whether
>    >it's part of the data to be recovered, and reassemble the recovered
>    >blocks.
>
>You can use adb if you have it, but will have to do a lot of math to determine
>offsets etc.
>
I have a binary file modifier called fm that I pulled off comp.sources.misc
that can be used to edit devices and binary files. Once again if you do the
math beforehand this program may be of help in this situation. The devices
can be edited in either hex or ascii modes and simple string searches can be
handled. You should probably have a good understanding of the way the file
system has been implemented before fooling with this.

Kishore Seshadri

 ----------------------------------------------------------------------------
Kishore Seshadri <kseshadr at mipos3.intel.com> or <..!intelca!mipos3!kseshadr>
"The nice thing about standards is that you have so many to choose from."

-----------------------------

From: Scott McGregor <mcgregor at hemlock.atherton.com>
Subject: seeking information about file system details.
Date: 10 Aug 90 17:12:33 GMT
Sender: news at athertn.atherton.com
To:       unix-wizards at sem.brl.mil


I am curious as to how accesses to multiple concurrent types of file
systems are implemented under SysV and BSD.  I've read the Bach
book and the BSD book, as well as books on device drivers.  But what
I am more interested in is at the switchable file system layer.  Explanations
of what goes on in the following example are welcome, recommendations
of books that cover this stuff is even more heartily desired.

I know that mount takes a file type. I know how the file system
tree is traced using inodes, and I have heard of vnodes (which is
what I think I want  to know more about) but I haven't found anything
written on vnodes.  I am aware that several vendors support multiple
varieties of file systems (Bell, BSD, NFS, MS-DOS) all accessable on
the same system, and the files on them can be accessed using standard
o/s calls and stdio library routines.

I guess what I am interested in is if I have a non-unix file system
and I want to allow the this file system to be mounted as a unix
file system, and accessed using open, creat, read, write, close, et al,
what interface translators would I have to create between my own
file system and the unix system calls, and how and where would I
add typically add these translators.  I presume that a new type
would have to be tested for in mount, and that the open, etc. commands
would have to know what type of file system they were operating on
and that a case statement switch would have to be supported by them for each
new type of file system to be supported.  

Is this correct, or is there some other way that the switching  between
file systems is handled.   

Mail can be directed to: 

mcgregor at atherton.com or ...!sun!atherton!mcgregor

Scott McGregor
Atherton Technology

-----------------------------

From: Chris Bertin <chrisb at risky.convergent.com>
Subject: evaluating ${10} and above in sh/ksh
Keywords: sh, ksh, eval
Date: 10 Aug 90 17:58:37 GMT
To:       unix-wizards at sem.brl.mil

There doesn't seem to be a way, in sh or ksh, to evaluate $10 and higher.
$10 and higher are evaluated as ${1}0, ${1}1, etc...
		     instead of ${10}, ${11}, etc...
I have tried many different ways and they all fail. Do you know one
that will work?

#! /bin/sh

set a b c d e f g h i j k l

arg=0

while [ $arg -le $# ]; do
	echo "evaluating \$$arg"
	eval echo $"$arg"
	eval echo $"${arg}"
	eval echo "$`eval echo $arg`"
	# Now, some of the crazy things I tried.
	# ( The parens are there when eval causes an error )
	echo "\${$arg} results in \c"
	( eval echo "\${$arg}" )
	echo "$`echo '{'``eval echo $arg``echo '}'` results in \c"
	( eval echo "$`echo '{'``eval echo $arg``echo '}'`" )
	arg=`expr $arg + 1`
done
-- 
Chris Bertin		|   chrisb at risky.Convergent.COM
Unisys			|		or
(408) 435-3762		| ...!uunet!pyramid!ctnews!risky!chrisb

-----------------------------

From: Chet Ramey <chet at cwns1.cwru.edu>
Subject: Re: How variables can be specified as arguments
Date: 10 Aug 90 19:24:41 GMT
Sender: news at usenet.ins.cwru.edu
To:       unix-wizards at sem.brl.mil

In article <7298 at helios.TAMU.EDU> skdutta at cs.tamu.edu (Saumen K Dutta) writes:

$ read_KEY1 "key" 
$ 
$ should define a new variable called key and
$ assigns it's value according to what user types.
$ 
$ I am not able to solve this ! Please help me

Use `eval'.

Chet

-- 
Chet Ramey				``Levi Stubbs' tears run down
Network Services Group			  his face...''
Case Western Reserve University	
chet at ins.CWRU.Edu		

-----------------------------

From: Guy Harris <guy at auspex.auspex.com>
Subject: Re: ln -f
Date: 10 Aug 90 20:19:01 GMT
To:       unix-wizards at sem.brl.mil

>Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
>use the rename system call?

Because they're named "ln", not "mv".

"rename()" is *NOT* an atomic operation that removes the target and
makes an *additional* link from the source with the name of the target. 
It's an atomic operation that *renames* the source to the target, and if
it succeeds does *not* leave the source behind.

-----------------------------

From: "David J. MacKenzie" <djm at eng.umd.edu>
Subject: Re: ln -f
Date: 10 Aug 90 22:54:43 GMT
Sender: The News System <news at eng.umd.edu>
To:       unix-wizards at sem.brl.mil

> Why don't the versions of ln that you know of on 4.3 BSD and SunOS 4
> use the rename system call?

Because rename doesn't do the same thing as ln.

If before you run ln, the file has n links, after you run ln
successfully the file will have n + 1 links.
If you just rename the file, it will still have n links, but one of
them will be different from before.
--
David J. MacKenzie <djm at eng.umd.edu> <djm at ai.mit.edu>

-----------------------------


End of UNIX-WIZARDS Digest
**************************



More information about the Comp.unix.wizards mailing list