Index: libsm/index.c
===================================================================
--- libsm/index.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/index.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,23 @@
+/*
+   ============================================================================
+	index.c -- BSD style index function
+	Version 1 -- 1987-02-11 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+char *
+index(str, c)
+register char *str;
+register char c;
+{
+	while (*str) {
+
+		if (*str == c)
+			return(str);
+
+		++str;
+	}
+
+	return((char *)0);
+}
+
Index: libsm/memccpy.c
===================================================================
--- libsm/memccpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memccpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,23 @@
+/*
+   =============================================================================
+	memccpy.c -- copy bytes until character seen
+	Version 1 -- 1987-06-12
+
+	Copy s2 to s1, stopping if character c is copied.
+	Copy no more than n bytes.
+	Return a pointer to the byte after character c in the copy,
+	or NULL if c is not found in the first n bytes.
+   =============================================================================
+*/
+
+char *
+memccpy(s1, s2, c, n)
+register char *s1, *s2;
+register char c;
+register int n;
+{
+        while (--n >= 0)
+                if ((*s1++ = *s2++) == c)
+                        return(s1);
+        return((char *)0);
+}
Index: libsm/memchr.c
===================================================================
--- libsm/memchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,20 @@
+/*
+   =============================================================================
+	memchr.c -- search a string for a character
+	Version 1 -- 1987-06-12
+
+	Return the ptr in sp at which the character c appears;
+	NULL if not found in n chars; don't stop at \0.
+   =============================================================================
+*/
+
+char *
+memchr(sp, c, n)
+register char *sp, c;
+register int n;
+{
+        while (--n >= 0)
+                if (*sp++ == c)
+                        return(--sp);
+        return((char *)0);
+}
Index: libsm/memcmp.c
===================================================================
--- libsm/memcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,22 @@
+/*
+   =============================================================================
+	memcmp.c -- compare memory areas
+	Version 2 -- 1987-06-15
+
+	Compare n bytes:  s1>s2: >0  s1==s2: 0  s1<s2: <0
+   =============================================================================
+*/
+
+int
+memcmp(s1, s2, n)
+register char *s1, *s2;
+register int n;
+{
+	register int	diff;
+
+        if (s1 != s2)
+                while (--n >= 0)
+                        if (diff = *s1++ - *s2++)
+                                return(diff);
+        return(0);
+}
Index: libsm/memcmpu.c
===================================================================
--- libsm/memcmpu.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memcmpu.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,38 @@
+/*
+   ============================================================================
+	memcmpu -- compare two memory areas while ignoring case
+	Version 4 -- 1987-06-15 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+#include "ctype.h"
+
+int
+memcmpu(s1, s2, n)
+register char *s1, *s2;
+int n;
+{
+	register char c1, c2;
+
+	while (n) {
+
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (isascii(c1) && islower(c1))
+			c1 = _toupper(c1);
+
+		if (isascii(c2) && islower(c2))
+			c2 = _toupper(c2);
+
+		if (c1 < c2)
+			return(-1);
+
+		if (c1 > c2)
+			return(1);
+
+		n--;
+	}
+
+	return(0);
+}
Index: libsm/memcpy.c
===================================================================
--- libsm/memcpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memcpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,21 @@
+/*
+   =============================================================================
+	memcpy.c -- copy memory
+	Version 1 -- 1987-06-12
+
+	Copy s2 to s1, always copy n bytes.
+	Return s1.
+   =============================================================================
+ */
+
+char *
+memcpy(s1, s2, n)
+register char *s1, *s2;
+register int n;
+{
+        register char *os1 = s1;
+
+        while (--n >= 0)
+                *s1++ = *s2++;
+        return (os1);
+}
Index: libsm/memcpyw.c
===================================================================
--- libsm/memcpyw.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memcpyw.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,21 @@
+/*
+   =============================================================================
+	memcpyw.c -- copy words
+	Version 2 -- 1987-06-15 -- D.N. Lynx Crowe
+
+	Copy s2 to s1, always copy n words.
+	Return pointer to s1.
+   =============================================================================
+*/
+
+short *
+memcpyw(s1, s2, n)
+register short *s1, *s2;
+register int n;
+{
+        register short *os1 = s1;
+
+        while (--n >= 0)
+                *s1++ = *s2++;
+        return (os1);
+}
Index: libsm/memset.c
===================================================================
--- libsm/memset.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memset.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,22 @@
+/*
+   =============================================================================
+	memset.c -- fill memory
+	Version 1 -- 1987-06-12
+
+	Set an array of n chars starting at sp to the character c.
+	Return sp.
+   =============================================================================
+*/
+
+char *
+memset(sp, c, n)
+register char *sp, c;
+register int n;
+{
+        register char *sp0 = sp;
+
+        while (--n >= 0)
+                *sp++ = c;
+		
+        return(sp0);
+}
Index: libsm/memsetw.c
===================================================================
--- libsm/memsetw.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/memsetw.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,21 @@
+/*
+   =============================================================================
+	memset.c -- fill memory with short words
+	Version 1 -- 1987-03-18 -- D.N. Lynx Crowe
+
+	Set an array of n shorts starting at sp to the short w.
+	Return pointer to sp.
+   =============================================================================
+*/
+
+short *
+memsetw(sp, w, n)
+register short *sp, w, n;
+{
+        register short *sp0 = sp;
+
+        while (--n >= 0)
+                *sp++ = w;
+
+        return(sp0);
+}
Index: libsm/rindex.c
===================================================================
--- libsm/rindex.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/rindex.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,23 @@
+/*
+   ============================================================================
+	rindex.c -- BSD style rindex function
+	Version 2 -- 1987-06-12 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+char *
+rindex(str, c)
+register char *str;
+char c;
+{
+	register char *cp;
+
+	for (cp = str ;*cp++ ; )
+		;
+
+	while (cp > str)
+		if (*--cp == c)
+			return(cp);
+
+	return((char *)0);
+}
Index: libsm/str2lc.c
===================================================================
--- libsm/str2lc.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/str2lc.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,19 @@
+/*
+   ============================================================================
+	str2lc(s) -- convert string s to lower case ASCII
+	Version 2 -- 1987-06-12 -- Copyright 1987 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+char *
+str2lc(s)
+register char *s;
+{
+	register char c;
+	register char *r = s;
+
+	while (c = *s)
+		*s++ = tolower(c);
+
+	return(r);
+}
Index: libsm/str2uc.c
===================================================================
--- libsm/str2uc.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/str2uc.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,19 @@
+/*
+   ============================================================================
+	str2uc(s) -- converts string s to upper case ASCII
+	Version 2 -- 1987-06-12 -- (c) Copyright 1987 -- D.N. Lynx Crowe
+   ============================================================================
+*/
+
+char *
+str2uc(s)
+register char *s;
+{
+	register char c;
+	register char *r = s;
+
+	while (c = *s)
+		*s++ = toupper(c);
+
+	return(r);
+}
Index: libsm/strcat.c
===================================================================
--- libsm/strcat.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strcat.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,28 @@
+/*
+   =============================================================================
+	strcat.c -- concatenate strings
+	Version 1 -- 1987-06-12
+
+	Concatenate s2 onto the end of s1.  S1's space must be large enough.
+	Return s1.
+   =============================================================================
+*/
+
+char *
+strcat(s1, s2)
+register char *s1, *s2;
+{
+        register char *os1;
+
+        os1 = s1;
+
+        while(*s1++)
+                ;
+
+        --s1;
+
+        while(*s1++ = *s2++)
+                ;
+
+        return(os1);
+}
Index: libsm/strccpy.c
===================================================================
--- libsm/strccpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strccpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,31 @@
+/*
+   =============================================================================
+	strccpy.c -- copy string up to specified character
+	Version 1 -- 1987-04-03 -- D.N. Lynx Crowe
+   =============================================================================
+*/
+
+/*
+   =============================================================================
+	strccpy(s1, s2, c) -- copy string up to specified character
+
+	Copy string s2 to s1 up to but not including the first occurrence of c.
+	s1 must be large enough to contain the copied bytes.
+	No checking is done. Character c is not copied.  Returns s1.
+   =============================================================================
+ */
+
+char *
+strccpy(s1, s2, c)
+register char *s1, *s2, c;
+{
+        register char *os1;
+	register char x;
+
+        os1 = s1;
+
+        while(c != (x = *s1++))
+		*s2++ = x;
+
+        return(os1);
+}
Index: libsm/strchr.c
===================================================================
--- libsm/strchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,22 @@
+/*
+   =============================================================================
+	strchr.c -- find a character in a string
+
+	Return the ptr in sp at which the character c appears;
+	NULL if not found
+   =============================================================================
+*/
+
+#define NULL    0
+
+char *
+strchr(sp, c)
+register char *sp, c;
+{
+	do {
+		if(*sp == c)
+			return(sp);
+	} while(*sp++);
+
+	return((char *)NULL);
+}
Index: libsm/strcmp.c
===================================================================
--- libsm/strcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,22 @@
+/*
+   =============================================================================
+	strcmp.c -- compare strings
+	Version 2 -- 1987-06-15
+
+	Compare strings:  s1>s2: >0  s1==s2: 0  s1<s2: <0
+   =============================================================================
+*/
+
+int
+strcmp(s1, s2)
+register char *s1, *s2;
+{
+	if(s1 == s2)
+		return(0);
+
+	while(*s1 == *s2++)
+		if(*s1++ == '\0')
+			 return(0);
+
+	return((int)*s1 - (int)*--s2);
+}
Index: libsm/strcpy.c
===================================================================
--- libsm/strcpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strcpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,23 @@
+/*
+   =============================================================================
+	strcpy.c -- copy string
+	Version 1 -- 1987-06-12
+
+	Copy string s2 to s1.  s1 must be large enough.
+	return s1
+   =============================================================================
+*/
+
+char *
+strcpy(s1, s2)
+register char *s1, *s2;
+{
+	register char *os1;
+
+	os1 = s1;
+
+	while(*s1++ = *s2++)
+		;
+
+	return(os1);
+}
Index: libsm/strcspn.c
===================================================================
--- libsm/strcspn.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strcspn.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,29 @@
+/*
+   ============================================================================
+	strcspn.c -- character scan function ala' Unix(tm)
+	Version 1 -- 1987-02-11 -- D.N. Lynx Crowe
+
+	Return the number of characters in the maximum leading segment
+	of string which consists solely of characters NOT from charset.
+   ============================================================================
+*/
+
+int
+strcspn(string, charset)
+char    *string;
+register char   *charset;
+{
+        register char *p, *q;
+	register int n = 0;
+
+        for(q = string; *q != '\0'; ++q , ++n) {
+
+                for(p = charset; *p != '\0' && *p != *q; ++p)
+                        ;
+
+                if(*p != '\0')
+                        break;
+        }
+
+        return(n);
+}
Index: libsm/strfill.c
===================================================================
--- libsm/strfill.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strfill.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,32 @@
+/*
+   =============================================================================
+	strfill() -- fill a string with a constant byte and zero terminate it
+	Version 1 -- 1988-08-19 -- D.N. Lynx Crowe
+
+	Where:
+		s = string pointer
+		c = constant byte
+		n = string length (not including the trailing zero)
+
+	Returns a pointer to the string.
+   =============================================================================
+*/
+
+char *
+strfill(s, c, n)
+register char *s;
+register char c;
+register unsigned n;
+{
+	register unsigned i;
+	char *p;
+
+	p = s;
+
+	for (i = n; i--; )
+		*s++ = c;
+
+	*s = '\0';
+	return(p);
+}
+
Index: libsm/strlcmp.c
===================================================================
--- libsm/strlcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strlcmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,34 @@
+/*
+   ============================================================================
+	strlcmp(s,l) -- compare string s to list l
+	Version 1 -- 1987-03-03 -- D.N. Lynx Crowe
+
+	Compares string s to each entry in the list l of strings
+	until a match is found or until list l is exhausted.
+	List l consists of a zero-entry terminated array of
+	pointers to zero terminated strings.
+	String s must be zero terminated.
+
+	Returns 0 if no match was found, or the 1-origin index
+	of the string in the list l.
+   ============================================================================
+*/
+
+int
+strlcmp(s,l)
+char *s, *l[];
+{
+	int	rc;
+
+	rc = 0;
+
+	while (l[rc]) {
+
+		if (0 == strcmp(s, l[rc]))
+			return(++rc);
+
+		rc++;
+	}
+
+	return(0);
+}
Index: libsm/strlen.c
===================================================================
--- libsm/strlen.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strlen.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,21 @@
+/*
+   =============================================================================
+	strlen.c -- string length function ala' Unix(tm)
+	Version 1 -- 1987-02-11 -- D.N. Lynx Crowe
+
+	Returns the number of non-NULL bytes in string argument.
+   =============================================================================
+*/
+
+
+int
+strlen(s)
+register char *s;
+{
+        register int n = 0;
+
+        while (*s++ != '\0')
+               ++n;
+
+        return (n);
+}
Index: libsm/strltrm.c
===================================================================
--- libsm/strltrm.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strltrm.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,34 @@
+/*
+   =============================================================================
+	strltrm() -- trim leading blanks from a string, in-place
+	Version 1 -- 1988-08-19 -- D.N. Lynx Crowe
+
+	Returns a pointer to the string.
+   =============================================================================
+*/
+
+#include "stddefs.h"
+
+char *
+strltrm(s)
+register char *s;
+{
+	register char c;
+	register char *lp, *rp;
+
+	if (*s NE ' ')
+		return(s);
+
+	lp = s;
+	rp = s;
+
+	while (*rp EQ ' ')
+		++rp;
+
+	while (c = *rp++)
+		*lp++ = c;
+
+	*lp = '\0';
+
+	return(s);
+}
Index: libsm/strncat.c
===================================================================
--- libsm/strncat.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strncat.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,34 @@
+/*
+   =============================================================================
+	strncat.c -- concatenate strings
+	Version 1 -- 1987-06-12
+
+	Concatenate s2 on the end of s1.  S1's space must be large enough.
+	At most n characters are moved.
+	Return s1.
+   =============================================================================
+*/
+
+char *
+strncat(s1, s2, n)
+register char *s1, *s2;
+register int n;
+{
+	register char *os1;
+
+	os1 = s1;
+
+	while(*s1++)
+		;
+
+	--s1;
+
+	while(*s1++ = *s2++)
+		if(--n < 0) {
+
+			*--s1 = '\0';
+			break;
+		}
+
+	return(os1);
+}
Index: libsm/strncmp.c
===================================================================
--- libsm/strncmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strncmp.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,24 @@
+/*
+   =============================================================================
+	strncmp.c -- compare strings
+	Version 2 -- 1987-06-15
+
+	Compare strings (at most n bytes)
+	Returns: s1>s2; >0  s1==s2; 0  s1<s2; <0
+   =============================================================================
+*/
+
+int
+strncmp(s1, s2, n)
+register char *s1, *s2;
+register int n;
+{
+	if (s1 == s2)
+		return(0);
+
+	while ((--n >= 0) && (*s1 == *s2++))
+		if(*s1++ == '\0')
+			return(0);
+
+	return((n < 0) ? 0 : (int)(*s1 - *--s2));
+}
Index: libsm/strncpy.c
===================================================================
--- libsm/strncpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strncpy.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,24 @@
+/*
+   =============================================================================
+	strncpy.c -- copy string of n bytes
+	Version 1 -- 1987-06-12
+
+	Copy s2 to s1, truncating or null-padding to always copy n bytes
+	return s1
+   =============================================================================
+*/
+
+char *
+strncpy(s1, s2, n)
+register char *s1, *s2;
+register int n;
+{
+	register char *os1 = s1;
+
+	while (--n >= 0)
+		if ((*s1++ = *s2++) == '\0')
+			while (--n >= 0)
+				*s1++ = '\0';
+
+	return (os1);
+}
Index: libsm/strpbrk.c
===================================================================
--- libsm/strpbrk.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strpbrk.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,30 @@
+/*
+   =============================================================================
+	strpbrk.c -- find a 'break' character in a string
+	Version 1 -- 1987-06-12
+
+	Return ptr to first occurance of any character from `brkset'
+	in the character string `string'; NULL if none exists.
+   =============================================================================
+*/
+
+char *
+strpbrk(string, brkset)
+register char *string, *brkset;
+{
+	register char *p;
+
+	do {
+
+	for (p = brkset; *p != '\0' && *p != *string; ++p)
+		;
+
+	if (*p != '\0')
+		return(string);
+	}
+
+	while(*string++)
+		;
+
+	return((char *)0);
+}
Index: libsm/strrchr.c
===================================================================
--- libsm/strrchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strrchr.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,29 @@
+/*
+   =============================================================================
+	strrchr.c -- find last occurrence of a character in a string
+	Version 1 -- 1987-06-12
+
+	Return the ptr in sp at which the character c last
+	appears; NULL if not found.
+   =============================================================================
+*/
+
+#define	NULL	(char *)0
+
+char *
+strrchr(sp, c)
+register char *sp, c;
+{
+	register char *r;
+
+	r = NULL;
+
+	do {
+
+	if (*sp == c)
+		r = sp;
+
+	} while(*sp++);
+
+	return(r);
+}
Index: libsm/strrev.c
===================================================================
--- libsm/strrev.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strrev.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,40 @@
+/*
+   =============================================================================
+	strrev.c -- reverse a string
+	Version 1 -- 1988-02-03 -- D.N. Lynx Crowe
+
+	char *
+	strrev(s1, s2)
+	char *s1;
+	char *s2;
+
+		Copies string 's2' into 's1'.  's1' must be large enough
+		to hold 's2'.  Returns 's1'.
+   =============================================================================
+*/
+
+char *
+strrev(s1, s2)
+char *s1;
+register char *s2;
+{
+	register char *s3;
+	register long i;
+
+	i = 0L;				/* initialize string length */
+	s3 = s1;			/* initialize target left end pointer */
+
+	while (*s2) {			/* find right end of source string */
+
+		++s2;
+		++i;
+	}
+
+	--s2;				/* adjust source right end pointer */
+
+	while (i--)			/* copy string in reverse */
+		*s3++ = *s2--;
+
+	*s3 = '\0';			/* terminate the string */
+	return(s1);			/* return address of reversed string */
+}
Index: libsm/strrevi.c
===================================================================
--- libsm/strrevi.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strrevi.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,43 @@
+/*
+   =============================================================================
+	strrevi.c -- reverse a string in place
+	Version 1 -- 1988-02-03 -- D.N. Lynx Crowe
+
+	char *
+	strrevi(s)
+	char *s;
+
+		Reverses string 's1' in place.  Returns 's1'.
+   =============================================================================
+*/
+
+char *
+strrevi(s)
+char *s;
+{
+	register char *p1, *p2;
+	register long i;
+	register char c;
+
+	p1 = s;			/* initialize left end pointer */
+	p2 = s;			/* initialize right end pointer */
+	i = 0L;			/* initialize character count */
+
+	while (*p2) {		/* find the right end of the string */
+
+		++i;
+		++p2;
+	}
+
+	--p2;			/* adjust right end pointer */
+	i >>= 1;		/* calculate swap count */
+
+	while (i--) {		/* for each pair of characters ... */
+
+		c = *p2;	/* ... swap right and left characters */
+		*p2-- = *p1;
+		*p1++ = c;
+	}
+
+	return(s);		/* return pointer to reversed string */
+}
Index: libsm/strrtrm.c
===================================================================
--- libsm/strrtrm.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strrtrm.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,33 @@
+/*
+   =============================================================================
+	strrtrm() -- trim trailing blanks from a string, in-place
+	Version 1 -- 1988-08-19 -- D.N. Lynx Crowe
+
+	Returns a pointer to the string.
+   =============================================================================
+*/
+
+#include "stddefs.h"
+
+char *
+strrtrm(s)
+char *s;
+{
+	register char *lp, *rp;
+
+	lp = s;
+	rp = s;
+
+	while (*rp)
+		++rp;
+
+	while ((long)(--rp) GE (long)lp) {
+
+		if (*rp EQ ' ')
+			*rp = '\0';
+		else
+			break;
+	}
+
+	return(lp);
+}
Index: libsm/strspn.c
===================================================================
--- libsm/strspn.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strspn.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,31 @@
+/*
+   ============================================================================
+	strspn.c -- string scan function ala' Unix(tm)
+	Version 2 -- 1987-06-12 -- D.N. Lynx Crowe
+
+	Return the number of characters in the maximum leading segment
+	of 'string' which consists solely of characters from 'charset'.
+   ============================================================================
+*/
+
+int
+strspn(string, charset)
+char *string;
+register char *charset;
+{
+	register char *p, *q;
+	register int n = 0;
+
+	for (q = string; *q != '\0'; ++q) {
+
+		for (p = charset; *p != '\0' && *p != *q; ++p)
+			;
+
+		if(*p == '\0')
+			break;
+
+		n++;
+	}
+
+	return(n);
+}
Index: libsm/strtok.c
===================================================================
--- libsm/strtok.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strtok.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,45 @@
+/*
+   =============================================================================
+	strtok.c -- tokenize a string
+	Version 1 -- 1987-06-12
+
+	Uses strpbrk and strspn to break 'string' into tokens on
+	sequentially subsequent calls.  Returns NULL when no
+	non-separator characters remain.
+	'subsequent' calls are calls with first argument == NULL.
+   =============================================================================
+*/
+
+#define	NULL	(char *)0
+
+extern int strspn();
+extern char *strpbrk();
+
+char *
+strtok(string, sepset)
+char *string, *sepset;
+{
+	register char *p, *q, *r;
+	static char *savept;
+
+	/* first or subsequent call ? */
+
+        p = (string == NULL) ? savept : string;
+
+	if (p == 0)              /* return if no tokens remain */
+		return(NULL);
+
+	q = p + strspn(p, sepset);      /* skip leading separators */
+
+	if (*q == '\0')          /* return if no tokens remain */
+		return(NULL);
+
+	if ((r = strpbrk(q, sepset)) == NULL)    /* move past token */
+		savept = 0;     /* indicate this is last token */
+	else {
+		*r = '\0';
+		savept = ++r;
+	}
+
+	return(q);
+}
Index: libsm/strtol.c
===================================================================
--- libsm/strtol.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
+++ libsm/strtol.c	(revision 109c83b4de0a1be1740921110e1aab18add40866)
@@ -0,0 +1,72 @@
+/*
+   =============================================================================
+	strtol.c -- convert a string of ASCII digits to a long
+	Version 1 -- 1987-06-12
+   =============================================================================
+*/
+
+#include "ctype.h"
+
+#define DIGIT(x) (isdigit(x) ? (x)-'0' : islower(x) ? (x)+10-'a' : (x)+10-'A')
+
+#define MBASE   ('z' - 'a' + 1 + 10)
+
+long
+strtol(str, ptr, base)
+register char *str;
+char **ptr;
+register int base;
+{
+	register long val;
+	register int c;
+	int xx, neg = 0;
+
+	if (ptr != (char **)0)
+		*ptr = str; /* in case no number is formed */
+
+	if (base < 0 || base > MBASE)
+		return (0); /* base is invalid -- should be a fatal error */
+
+	if (!isalnum(c = *str)) {
+
+		while (isspace(c))
+			c = *++str;
+
+		switch (c) {
+
+		case '-':
+			neg++;
+
+		case '+': /* fall-through */
+			c = *++str;
+		}
+	}
+
+	if (base == 0)
+		if (c != '0')
+			base = 10;
+		else if (str[1] == 'x' || str[1] == 'X')
+			base = 16;
+		else
+			base = 8;
+	/*
+		for any base > 10, the digits incrementally following
+		9 are assumed to be "abc...z" or "ABC...Z"
+	*/
+
+	if (!isalnum(c) || (xx = DIGIT(c)) >= base)
+		return (0); /* no number formed */
+
+	if (base == 16 && c == '0' && isxdigit(str[2]) &&
+	   (str[1] == 'x' || str[1] == 'X'))
+		c = *(str += 2); /* skip over leading "0x" or "0X" */
+
+	for (val = -DIGIT(c); isalnum(c = *++str) && (xx = DIGIT(c)) < base; )
+		 /* accumulate neg avoids surprises near MAXLONG */
+		val = base * val - xx;
+
+	if (ptr != (char **)0)
+		*ptr = str;
+
+	return (neg ? val : -val);
+}
