Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Posting-Version: version B 2.10.2 9/18/84; site gitpyr.UUCP
Path: utzoo!watmath!clyde!bonnie!akgua!gatech!gitpyr!robert
From: rob...@gitpyr.UUCP (Robert Viduya)
Newsgroups: net.sources
Subject: termcap to terminfo translator
Message-ID: <83@gitpyr.UUCP>
Date: Wed, 30-Jan-85 15:42:01 EST
Article-I.D.: gitpyr.83
Posted: Wed Jan 30 15:42:01 1985
Date-Received: Fri, 1-Feb-85 23:35:32 EST
Distribution: net
Organization: Georgia Tech, Atlanta
Lines: 790

The following is a program that converts termcap database files to terminfo
source files.  It reads the termcap file from standard input and writes the
terminfo source to standard output.  I tried to be as complete as possible,
but I wasn't able to implement some things due to ambiguous documentation.
The unimplemented parts are in the %-escapes.  I wasn't sure about some
of the more exotic termcap %-escapes like '%B'.  However, things like '%c',
'%d', '%2d' and '%+' are implemented.

		as usual, send bug reports...

			robert

------
#!/bin/sh
# Posted from gitpyr!robert
#	Run the following text with /bin/sh to create:
#	Makefile
#	captoinfo.c
#	getcap.c
#	putinfo.c
#	tget.c
sed 's/^X//' << '--burp--' > Makefile
XCFLAGS	=	-O
XOBJS	=	captoinfo.o getcap.o putinfo.o tget.o
X
Xcaptoinfo:	$(OBJS)
X		cc $(CFLAGS) $(OBJS) -o captoinfo
X
Xcaptoinfo.o:	captoinfo.c
X
Xgetcap.o:	getcap.c
X
Xputinfo.o:	putinfo.c
X
Xtget.o:		tget.c
--burp--
sed 's/^X//' << '--burp--' > captoinfo.c
X/*
X * captoinfo:
X *	Translate termcap terminal database to terminfo source
X *	format.
X *
X *	Captoinfo reads standard input, which is assumed to be
X *	a termcap file and writes the equivalent to standard
X *	output in terminfo source format.
X *
X * Robert Viduya - Georgia Institute of Technology.
X *
X *	gitpyr!robert
X */
X#include <stdio.h>
X
X#define	bool	char
X#define	TRUE	1
X#define	FALSE	0
X
Xchar    buffer[2048];
X
X
Xmain ()
X{
X    int		c;
X
X    while ((c = getchar ()) != EOF) {
X	if (c == '#') {
X	    (void) putchar (c);
X	    do {
X		c = getchar ();
X		(void) putchar (c);
X	    } while (c != '\n');
X	}
X	else {
X	    if (ungetc (c, stdin) == EOF) {
X		fprintf (stderr, "ungetc failed.\n");
X		exit (1);
X	    }
X	    get_termcap ();
X	    print_name ();
X	    print_bools ();
X	    print_nums ();
X	    print_strs ();
X	}
X    }
X    exit (0);
X}
--burp--
sed 's/^X//' << '--burp--' > getcap.c
X#include <stdio.h>
X#include <ctype.h>
X
X#define	bool	char
X#define	TRUE	1
X#define	FALSE	0
X
Xextern char    buffer[];
X
X
X/*
X * get_termcap:
X *	read next termcap entry into buffer from standard input.
X */
Xget_termcap ()
X{
X    int		c;
X    char	*bptr;
X
X    bptr = buffer;
X    while ((c = getchar ()) != '\n') {
X	if (c == '\\') {
X	    if ((c = getchar ()) != '\n') {
X		if (ungetc (c, stdin) == EOF) {
X		    fprintf (stderr, "ungetc failed.\n");
X		    exit (1);
X		}
X		*(bptr++) = '\\';
X	    }
X	}
X	else {
X	    *(bptr++) = c;
X	}
X    }
X    *bptr = '\0';
X}
--burp--
sed 's/^X//' << '--burp--' > putinfo.c
X#include <stdio.h>
X#include <strings.h>
X#include <ctype.h>
X
X#define	bool	char
X#define	TRUE	1
X#define	FALSE	0
X
X#define	MAXINDEX(array)	(sizeof(array)/sizeof(array[0]))
X
X/*
X * bools & boolcaps:
X *	lookup translate table for boolean fields.
X */
Xstruct	bools {
X    char	*capname;	/* termcap name */
X    char	*infoname;	/* terminfo name */
X};
Xstruct	bools	boolcaps[] = {
X    { "bw", "bw" },	{ "am", "am" },		{ "xb", "xsb" },
X    { "xs", "xhp" },	{ "xn", "xenl" },	{ "eo", "eo" },
X    { "gn", "gn" },	{ "hc", "hc" },		{ "km", "km" },
X    { "hs", "hs" },	{ "in", "in" },		{ "da", "da" },
X    { "db", "db" },	{ "mi", "mir" },	{ "ms", "msgr" },
X    { "os", "os" },	{ "es", "eslok" },	{ "xt", "xt" },
X    { "hz", "hz" },	{ "ul", "ul" },		{ "xo", "xon" }
X};
X#define MAXBOOLS	MAXINDEX(boolcaps)
X
X/*
X * nums & numcaps:
X *	lookup translate table for numeric capabilities.
X */
Xstruct	nums {
X    char	*capname;	/* termcap name */
X    char	*infoname;	/* terminfo name */
X};
Xstruct	nums	numcaps[] = {
X    { "co", "cols" },	{ "it", "it" },		{ "li", "lines" },
X    { "lm", "lm" },	{ "sg", "xmc" },	{ "pb", "pb" },
X    { "vt", "vt" },	{ "ws", "wsl" }
X};
X#define	MAXNUMS		MAXINDEX(numcaps)
X
X/*
X * strs & strcaps:
X *	lookup translate table for string capabilities.
X */
Xstruct	strs	{
X    char	*capname;	/* termcap name */
X    char	*infoname;	/* terminfo name */
X    char	*dflt;		/* default value */
X};
Xstruct	strs	strcaps[] = {
X    { "bt",	"cbt",		((char *)0) },
X    { "bl",	"bel",		"\007" },
X    { "cr",	"cr",		"\r" },
X    { "cs",	"csr",		((char *)0) },
X    { "ct",	"tbc",		((char *)0) },
X    { "cl",	"clear",	((char *)0) },
X    { "ce",	"el",		((char *)0) },
X    { "cd",	"ed",		((char *)0) },
X    { "ch",	"hpa",		((char *)0) },
X    { "CC",	"cmdch",	((char *)0) },
X    { "cm",	"cup",		((char *)0) },
X    { "do",	"cud1",		"\n" },
X    { "ho",	"home",		((char *)0) },
X    { "vi",	"civis",	((char *)0) },
X    { "le",	"cub1",		"\b" },		/* special case - check bc */
X    { "CM",	"mrcup",	((char *)0) },
X    { "ve",	"cnorm",	((char *)0) },
X    { "nd",	"cuf1",		((char *)0) },
X    { "ll",	"ll",		((char *)0) },
X    { "up",	"cuu1",		((char *)0) },
X    { "vs",	"cvvis",	((char *)0) },
X    { "dc",	"dch1",		((char *)0) },
X    { "dl",	"dl1",		((char *)0) },
X    { "ds",	"dsl",		((char *)0) },
X    { "hd",	"hd",		((char *)0) },
X    { "as",	"smacs",	((char *)0) },
X    { "mb",	"blink",	((char *)0) },
X    { "md",	"bold",		((char *)0) },
X    { "ti",	"smcup",	((char *)0) },
X    { "dm",	"smdc",		((char *)0) },
X    { "mh",	"dim",		((char *)0) },
X    { "im",	"smir",		((char *)0) },
X    { "mp",	"prot",		((char *)0) },
X    { "mr",	"rev",		((char *)0) },
X    { "mk",	"invis",	((char *)0) },
X    { "so",	"smso",		((char *)0) },
X    { "us",	"smul",		((char *)0) },
X    { "ec",	"ech",		((char *)0) },
X    { "ae",	"rmacs",	((char *)0) },
X    { "me",	"sgr0",		((char *)0) },
X    { "te",	"rmcup",	((char *)0) },
X    { "ed",	"rmdc",		((char *)0) },
X    { "ei",	"rmir",		((char *)0) },
X    { "se",	"rmso",		((char *)0) },
X    { "ue",	"rmul",		((char *)0) },
X    { "vb",	"flash",	((char *)0) },
X    { "ff",	"ff",		((char *)0) },
X    { "fs",	"fsl",		((char *)0) },
X    { "is",	"is1",		((char *)0) },
X    { "i1",	"is2",		((char *)0) },
X    { "i2",	"is3",		((char *)0) },
X    { "if",	"if",		((char *)0) },
X    { "ic",	"ich1",		((char *)0) },
X    { "al",	"il1",		((char *)0) },
X    { "ip",	"ip",		((char *)0) },
X    { "kb",	"kbs",		"\b" },
X    { "ka",	"ktbc",		((char *)0) },
X    { "kC",	"kclr",		((char *)0) },
X    { "kt",	"kctab",	((char *)0) },
X    { "kD",	"kdch1",	((char *)0) },
X    { "kL",	"kdl1",		((char *)0) },
X    { "kd",	"kcud1",	"\n" },
X    { "kM",	"krmir",	((char *)0) },
X    { "kE",	"kel",		((char *)0) },
X    { "kS",	"ked",		((char *)0) },
X    { "k0",	"kf0",		((char *)0) },
X    { "k1",	"kf1",		((char *)0) },
X    { "k2",	"kf2",		((char *)0) },
X    { "k3",	"kf3",		((char *)0) },
X    { "k4",	"kf4",		((char *)0) },
X    { "k5",	"kf5",		((char *)0) },
X    { "k6",	"kf6",		((char *)0) },
X    { "k7",	"kf7",		((char *)0) },
X    { "k8",	"kf8",		((char *)0) },
X    { "k9",	"kf9",		((char *)0) },
X    { "kh",	"khome",	((char *)0) },
X    { "kI",	"kich1",	((char *)0) },
X    { "kA",	"kil1",		((char *)0) },
X    { "kl",	"kcub1",	"\b" },
X    { "kH",	"kll",		((char *)0) },
X    { "kN",	"knp",		((char *)0) },
X    { "kP",	"kpp",		((char *)0) },
X    { "kr",	"kcuf1",	((char *)0) },
X    { "kF",	"kind",		((char *)0) },
X    { "kR",	"kri",		((char *)0) },
X    { "kT",	"khts",		((char *)0) },
X    { "ku",	"kcuu1",	((char *)0) },
X    { "ke",	"rmkx",		((char *)0) },
X    { "ks",	"smkx",		((char *)0) },
X    { "l0",	"lf0",		((char *)0) },
X    { "l1",	"lf1",		((char *)0) },
X    { "l2",	"lf2",		((char *)0) },
X    { "l3",	"lf3",		((char *)0) },
X    { "l4",	"lf4",		((char *)0) },
X    { "l5",	"lf5",		((char *)0) },
X    { "l6",	"lf6",		((char *)0) },
X    { "l7",	"lf7",		((char *)0) },
X    { "l8",	"lf8",		((char *)0) },
X    { "l9",	"lf9",		((char *)0) },
X    { "mm",	"smm",		((char *)0) },
X    { "mo",	"rmm",		((char *)0) },
X    { "nw",	"nel",		"\r\n" },
X    { "pc",	"pad",		((char *)0) },
X    { "DC",	"dch",		((char *)0) },
X    { "DL",	"dl",		((char *)0) },
X    { "DO",	"cud",		((char *)0) },
X    { "IC",	"ich",		((char *)0) },
X    { "SF",	"indn",		((char *)0) },
X    { "AL",	"il",		((char *)0) },
X    { "LE",	"cub",		((char *)0) },
X    { "RI",	"cuf",		((char *)0) },
X    { "SR",	"rin",		((char *)0) },
X    { "UP",	"cuu",		((char *)0) },
X    { "pk",	"pfkey",	((char *)0) },
X    { "pl",	"pfloc",	((char *)0) },
X    { "px",	"pfx",		((char *)0) },
X    { "ps",	"mc0",		((char *)0) },
X    { "pf",	"mc4",		((char *)0) },
X    { "po",	"mc5",		((char *)0) },
X    { "rp",	"rep",		((char *)0) },
X    { "rs",	"rs1",		((char *)0) },
X    { "r1",	"rs2",		((char *)0) },
X    { "r2",	"rs3",		((char *)0) },
X    { "rf",	"rf",		((char *)0) },
X    { "rc",	"rc",		((char *)0) },
X    { "cv",	"vpa",		((char *)0) },
X    { "sc",	"sc",		((char *)0) },
X    { "sf",	"ind",		"\n" },
X    { "sr",	"ri",		((char *)0) },
X    { "sa",	"sgr",		((char *)0) },
X    { "st",	"hts",		((char *)0) },
X    { "wi",	"wind",		((char *)0) },
X    { "ta",	"ht",		((char *)0) },	/* conditional - check pt */
X    { "ts",	"tsl",		((char *)0) },
X    { "uc",	"uc",		((char *)0) },
X    { "hu",	"hu",		((char *)0) },
X    { "iP",	"iprog",	((char *)0) },
X    { "K1",	"ka1",		((char *)0) },
X    { "K2",	"kb2",		((char *)0) },
X    { "K3",	"ka3",		((char *)0) },
X    { "K4",	"kc1",		((char *)0) },
X    { "K5",	"kc3",		((char *)0) },
X    { "pO",	"mc5p",		((char *)0) },
X    { "tc",	"use",		((char *)0) }
X};
X#define	MAXSTRS		MAXINDEX(strcaps)
X
Xint	tgetname ();	/* get termcap name */
Xint	tgetflag ();	/* get termcap boolean value */
Xint	tgetnum ();	/* get termcap numeric value */
Xint	tgetstr ();	/* get termcap string value */
X
X
X/*
X * print_name:
X *	print name and aliases of current termcap entry.
X */
Xprint_name ()
X{
X    char	name[100];
X
X    tgetname (name);
X    printf ("%s,\n", name);
X}
X
X/*
X * print_bools:
X *	print all boolean fields of current termcap entry.
X */
Xprint_bools ()
X{
X    int		i, val;
X    bool	stuffprinted = FALSE;
X
X    for (i = 0; i < MAXBOOLS; i++)
X	if (val = tgetflag (boolcaps[i].capname)) {
X	    if (val == 1)
X		printf ("\t%s,", boolcaps[i].infoname);
X	    else
X		printf ("\t%s@,", boolcaps[i].infoname);
X	    stuffprinted = TRUE;
X	}
X    if (stuffprinted)
X	(void) putchar ('\n');
X}
X
X/*
X * print_nums:
X *	print all numeric fields of current termcap entry.
X */
Xprint_nums ()
X{
X    int		i, capval;
X    bool	stuffprinted = FALSE;
X
X    for (i = 0; i < MAXNUMS; i++)
X	if ((capval = tgetnum (numcaps[i].capname)) >= 0) {
X	    printf ("\t%s#%d,", numcaps[i].infoname, capval);
X	    stuffprinted = TRUE;
X	}
X	else if (capval == -2) {
X	    printf ("\t%s@,", numcaps[i].infoname);
X	    stuffprinted = TRUE;
X	}
X    if (stuffprinted)
X	(void) putchar ('\n');
X}
X
X/*
X * print_strs:
X *	print all string fields of current termcap entry.
X */
Xprint_strs ()
X{
X    int		i, count = 0;
X    char	capval[100];
X
X    for (i = 0; i < MAXSTRS; i++) {
X	tgetstr (strcaps[i].capname, capval);
X	if (!capval[0]) {
X	    if (strcmp (strcaps[i].capname, "le") == 0) {
X		tgetstr ("bc", capval);
X	    }
X	    else if (strcmp (strcaps[i].capname, "ta") == 0) { 
X		if (tgetflag ("pt")) {
X		    capval[0] = '\t';
X		    capval[1] = '\0';
X		}
X	    }
X	}
X	if ((!capval[0]) && (strcaps[i].dflt))
X	    (void) strcpy (capval, strcaps[i].dflt);
X	if (capval[0]) {
X	    if (strcmp (capval, "@") != 0) {
X		printf ("\t%s=", strcaps[i].infoname);
X		if (strcmp(strcaps[i].infoname,"use") != 0) {
X		    put_str (capval);
X		    printf (",");
X		}
X		else
X		    printf ("%s,", capval);
X	    }
X	    else
X		printf ("%s@,", strcaps[i].infoname);
X	    count++;
X	    if (!(count %= 3))
X		putchar ('\n');
X	}
X    }
X    if (count)
X	(void) putchar ('\n');
X}
X
X/*
X * put_str:
X *	translate strings to printable format and print them.
X */
Xput_str (s)
Xchar	*s;
X{
X    bool	rflag = FALSE;	/* % codes */
X    char	*c;
X    int		parm;
X
X    if ((isdigit (*s)) || (*s == '.')) {	/* handle padding */
X	printf ("$<");
X	while ((isdigit (*s)) || (*s == '.')) {
X	    (void) putchar (*s);
X	    s++;
X	}
X	if (*s == '*') {
X	    (void) putchar (*s);
X	    s++;
X	}
X	(void) putchar ('>');
X    }
X    for (c = s; *c; c++) {	/* scan for % codes (needs work) */
X	if (*c == '%') {
X	    c++;
X	    switch (*c) {
X		case 'r':
X		    rflag = TRUE;
X		    break;
X		default:
X		    break;	/* ignore */
X	    }
X	}
X    }
X    parm = 0;
X    while (*s) {		/* print the string */
X	switch (*s) {
X	    case '%':
X		s++;
X		switch (*s) {
X		    case '%':
X			printf ("%%%%");
X			break;
X		    case 'i':
X			printf ("%%i");
X			break;
X		    case 'd':
X			parm++;
X			if ((rflag) && (parm <= 2)) {
X			    if (parm == 1)
X				printf ("%%p2%%d");
X			    else
X				printf ("%%p1%%d");
X			}
X			else
X			    printf ("%%p%d%%d", parm);
X			break;
X		    case '2':
X			parm++;
X			if ((rflag) && (parm <= 2)) {
X			    if (parm == 1)
X				printf ("%%p2%%02d");
X			    else
X				printf ("%%p1%%02d");
X			}
X			else
X			    printf ("%%p%d%%02d", parm);
X			break;
X		    case '3':
X			parm++;
X			if ((rflag) && (parm <= 2)) {
X			    if (parm == 1)
X				printf ("%%p2%%03d");
X			    else
X				printf ("%%p1%%03d");
X			}
X			else
X			    printf ("%%p%d%%03d", parm);
X			break;
X		    case '.':
X			parm++;
X			if ((rflag) && (parm <= 2)) {
X			    if (parm == 1)
X				printf ("%%p2%%c");
X			    else
X				printf ("%%p1%%c");
X			}
X			else
X			    printf ("%%p%d%%c", parm);
X			break;
X		    case '+':
X			s++;
X			parm++;
X			if ((rflag) && (parm <= 2)) {
X			    if (parm == 1)
X				printf ("%%p2%%'%c'%%+%%c", *s);
X			    else
X				printf ("%%p1%%'%c'%%+%%c", *s);
X			}
X			else
X			    printf ("%%p%d%%'%c'%%+%%c", parm, *s);
X			break;
X		    default:
X			break;	/* ignore */
X		}
X		break;
X	    case '\200':
X		printf ("\\0");
X		break;
X	    case '\177':
X		printf ("^?");
X		break;
X	    case ',':
X		printf ("\\,");
X		break;
X	    case '\\':
X		printf ("\\\\");
X		break;
X	    case '^':
X		printf ("\\^");
X		break;
X	    case ':':
X		printf ("\\:");
X		break;
X	    case '\033':
X		printf ("\\E");
X		break;
X	    case '\n':
X		printf ("\\n");
X		break;
X	    case '\r':
X		printf ("\\r");
X		break;
X	    case '\t':
X		printf ("\\t");
X		break;
X	    case '\b':
X		printf ("\\b");
X		break;
X	    case '\f':
X		printf ("\\f");
X		break;
X	    case ' ':
X		printf ("\\s");
X		break;
X	    default:
X		if (*s < ' ')
X		    printf ("^%c", *s + 'A' - 1);
X		else
X		    (void) putchar (*s);
X		break;
X	}
X	s++;
X    }
X}
--burp--
sed 's/^X//' << '--burp--' > tget.c
X#include <stdio.h>
X#include <ctype.h>
X#include <strings.h>
X
X#define	bool	char
X#define	TRUE	1
X#define	FALSE	0
X
Xextern char    buffer[];
X
X
X/*
X * scan:
X *	scan for character in string, return position of character.
X *	similar to index/strchr, except that if char not found, returns
X *	pointer to null at end of string, instead of a null pointer.
X */
Xchar *
Xscan (s, c)
Xregister char	*s;
Xregister char	c;
X{
X    while ((*s) && (*s != c))
X	s++;
X    return (s);
X}
X
X/* findcap:
X * 	returns pointer to just after capname (trailing ':' for flags,
X *	'#' for nums, '=' for strs, '@' for disabled stuff) or to null
X *	 after termcap if not found.
X */
Xchar *
Xfindcap (capname)
Xchar	*capname;
X{
X    register char	*bptr = buffer;
X    register bool	found = FALSE;
X    char		cap[3];
X
X    cap[2] = '\0';
X    while ((!found) && (*bptr)) {
X	bptr = scan (bptr, ':');
X	if (*bptr) {
X	    cap[0] = *(bptr + 1);
X	    cap[1] = *(bptr + 2);
X	    if (strcmp (cap,capname) == 0) {
X		found = TRUE;
X		bptr += 3;	/* skip colon and capname */
X	    }
X	    else
X		bptr++;		/* skip colon */
X	}
X    }
X    return (bptr);
X}
X
X/*
X * tgetname:
X *	store name of termcap entry in name
X */
Xtgetname (name)
Xchar	*name;
X{
X    char	*bptr;
X
X    bptr = buffer;
X
X    while ((*bptr) && (*bptr != ':'))
X	*(name++) = *(bptr++);
X    *(name) = '\0';
X}
X
X/*
X * tgetflag:
X *	return 1 if capname present, 0 otherwise, -1 if '@'ed.
X */
Xint
Xtgetflag (capname)
Xchar	*capname;
X{
X    char	*c;
X
X    c = findcap (capname);
X    if (*c == '\0')
X	return (0);
X    else if (*c == '@')
X	return (-1);
X    else
X	return (1);
X}
X
X/*
X * tgetnum:
X *	return value of capname, -1 if not present, -2 if '@'ed.
X */
Xint
Xtgetnum (capname)
Xchar	*capname;
X{
X    char	*c;
X    int		val;
X
X    c = findcap (capname);
X    if (*c == '@')
X	return (-2);
X    else if (*c != '\0') {
X	c++;	/* skip '#' */
X	val = 0;
X	while (isdigit (*c)) {
X	    val = (val * 10) + (*c - '0');
X	    c++;
X	}
X	return (val);
X    }
X    else
X	return (-1);
X}
X
X/*
X * tgetstr:
X *	store binary value of capname into value, store null if
X *	not present, store "@" if '@'ed.
X */
Xtgetstr (capname, value)
Xchar		*capname;
Xregister char	*value;
X{
X    register char	*c;
X
X    c = findcap (capname);
X    if (*c == '@')
X	strcpy (value, "@");
X    else if (*c != '\0') {
X	c++;	/* skip '=' */
X	while ((*c) && (*c != ':')) {
X	    if (*c == '^') {
X		c++;
X		if (islower (*c)) 
X		    *(value++) = toupper(*(c++)) - '@';	/* ascii dependent */
X		else
X		    *(value++) = *(c++) - '@';	/* ascii dependent */
X	    }
X	    else if (*c == '\\') {
X		c++;
X		switch (*c) {
X		    case 'E':
X			*(value++) = '\033';
X			c++;
X			break;
X		    case 'n':
X			*(value++) = '\n';
X			c++;
X			break;
X		    case 'r':
X			*(value++) = '\r';
X			c++;
X			break;
X		    case 't':
X			*(value++) = '\t';
X			c++;
X			break;
X		    case 'b':
X			*(value++) = '\b';
X			c++;
X			break;
X		    case 'f':
X			*(value++) = '\f';
X			c++;
X			break;
X		    default:
X			if (isdigit (*c)) {	/* octal value */
X			    *value = '\0';
X			    while (isdigit (*c)) {
X				*value = ((*value) * 8) + ((*c) - '0');
X				c++;
X			    }
X			    value++;
X			}
X			else
X			    *(value++) = *(c++);
X			break;
X		}
X	    }
X	    else
X		*(value++) = *(c++);
X	}
X	*value = '\0';
X    }
X    else
X	*value = '\0';
X}
--burp--
exit
-- 
Robert Viduya
Georgia Institute of Technology

...!{akgua,allegra,amd,hplabs,ihnp4,masscomp,ut-ngp}!gatech!gitpyr!robert
...!{rlgvax,sb1,uf-cgrl,unmvax,ut-sally}!gatech!gitpyr!robert

			  SCO's Case Against IBM

November 12, 2003 - Jed Boal from Eyewitness News KSL 5 TV provides an
overview on SCO's case against IBM. Darl McBride, SCO's president and CEO,
talks about the lawsuit's impact and attacks. Jason Holt, student and 
Linux user, talks about the benefits of code availability and the merits 
of the SCO vs IBM lawsuit. See SCO vs IBM.

Note: The materials and information included in these Web pages are not to
be used for any other purpose other than private study, research, review
or criticism.