Wizard-level questions

Larry McVoy lm at slovax.Eng.Sun.COM
Mon Jan 28 18:55:35 AEST 1991


In article <16048 at sdcc6.ucsd.edu> cs163wcr at sdcc10.ucsd.edu (I support the U.N.) writes:
>[1] Can you access a file by its i-node number?  Something like
>	(for C code) FILE *iopen (int inode, char *mode) ?

Program included below.  This program does an internal file tree walk
to find the inode.  Slow, but quite portable, contrary to a supposed
wizard's opinion.

>[2] With Internet sockets, how does a machine accept()ing a
>	socket connection know what machine is calling it?  Does
>	it rely on the calling program to tell it?

Go look at ethernet packets.  They have both a sender and a destination.
The sender field, after going through a few protocol layers, gets jammed
into one of the accept(2) args.

>[3] I have a server program that reads my mail and does various
>	functions.  One thing I would like it to do is send a "write"
>	message to other users when it gets a letter with subject
>	"WRITE user", sending the letter body as the message, but I
>	can't get write to work unless the output is a tty.  How do
>	I fool write into thinking my pipe is a tty?

Oh, I suspect a little perl script will do it.  That's included below as well.
Yes, I was bored this evening.  :-)

>[4] How did you become a Unix Wizard?  I'm learning various
>	features as I go, as I think of a use for them and/or
>	learn about them.  Is there a more organized/better way?

Use the force, read the source.

# 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:
# iopen.c wruser

echo x - iopen.c
cat > "iopen.c" << '//E*O*F iopen.c//'
#include	<ftw.h>
#include	<sys/stat.h>

static	int	_inum;		/* XXX - won't work when multi threaded */
				/* could be a function */
#ifdef	MAIN
static	char	*_path;		/* just so we can print it out */
#endif

iopen(mnt, inum)
	char	*mnt;
{
	char	*mine();
	char	*path;
	int	fd;

	_inum = inum;
	path = (char*)ftw(mnt, mine, 32);	/* XXX - 32 */
	if (path == (char*)0)
		return (-1);
	if ((fd = open(path, 2)) == -1)
		fd = open(path, 0);
#ifdef	MAIN
	_path = path;
#endif
	return (fd);
}

static	char*
mine(p, sp, flags)
	char	*p;
	struct	stat *sp;
{
	if (sp->st_ino == _inum) {
		return (p);
	}
	return (0);
}

#ifdef	MAIN
main(ac, av)
	char	**av;
{
	int	fd;

	if (ac != 3) {
		printf("usage: %s mntpoint inum\n", av[0]);
		exit(1);
	}
	fd = iopen(av[1], atoi(av[2]));
	if (fd == -1) {
		printf("%s: can't find ino %d\n", atoi(av[2]));
		exit(2);
	}
	printf("open of %s, ino %d, returns %d\n", _path, atoi(av[2]), fd);
}
#endif
//E*O*F iopen.c//

echo x - wruser
cat > "wruser" << '//E*O*F wruser//'
#!/bin/perl

# stolen from vacation.pl

@lines = <>;	# schlep 'em in

foreach $_ (@lines) {
	last if /^\n/;
	next unless /^Subject: WRITE /;
	$buf = $_;
	$buf =~ s/Subject: WRITE //;
	split(/[ \t\n]+/, $buf);
	foreach $u (@_) {
		$user{$u} = 1;
	}
	$found++;
	last;
}
if (!defined $found) {
	#
	# Do whatever you would normally do in the case that
	# this is normal mail.
	# I just copy it to stdout.
	foreach $_ (@lines) {
		print;
	}
	exit 0;
}

#
# OK, let's find the user[s] we want.
#
open(WHO, "/usr/bin/who|") || die "No who?";
while (<WHO>) {
	split;
	if ($user{$_[0]} == 1) {
		open(W, "|/bin/write $_[0] $_[1]") || die "write $_[0] $_[1]";
		foreach $_ (@lines) {
			print W;
		}
		close(W);
	}
}
close(WHO);
exit 0;
//E*O*F wruser//

echo Possible errors detected by \'wc\' [hopefully none]:
temp=/tmp/shar$$
trap "rm -f $temp; exit" 0 1 2 3 15
cat > $temp <<\!!!
      57     159     925 iopen.c
      45     130     727 wruser
     102     289    1652 total
!!!
wc  iopen.c wruser | sed 's=[^ ]*/==' | diff -b $temp -
exit 0
---
Larry McVoy, Sun Microsystems     (415) 336-7627       ...!sun!lm or lm at sun.com



More information about the Comp.unix.wizards mailing list