adding zephyr-im master branch

This commit is contained in:
2022-07-25 09:01:27 -06:00
parent 61f5ed8f01
commit ee1236fa5c
311 changed files with 62265 additions and 0 deletions

View File

@ -0,0 +1,56 @@
SHELL=@SHELL@
prefix=@prefix@
exec_prefix=@exec_prefix@
datadir=@datadir@
sysconfdir=@sysconfdir@
sbindir=@sbindir@
lsbindir=@lsbindir@
datarootdir=@datarootdir@
includedir=@includedir@
mandir=@mandir@
libdir=@libdir@
bindir=@bindir@
top_builddir=../..
srcdir=@srcdir@
top_srcdir=@top_srcdir@
BUILDTOP=../..
VPATH=@srcdir@
LIBTOOL=@LIBTOOL@
CC=@CC@
INSTALL=@INSTALL@
LIBZEPHYR=${BUILDTOP}/lib/libzephyr.la
CPPFLAGS=@CPPFLAGS@
CFLAGS=@CFLAGS@
ALL_CFLAGS=${CFLAGS} -I${top_srcdir}/h -I${BUILDTOP}/h ${CPPFLAGS}
LDFLAGS=@LDFLAGS@
LIBS=${LIBZEPHYR} @LIBS@ -lcom_err
OBJS= zwrite.o
all: zwrite
zwrite: ${OBJS} ${LIBZEPHYR}
${LIBTOOL} --mode=link ${CC} ${LDFLAGS} -o $@ ${OBJS} ${LIBS}
.c.o:
${CC} -c ${ALL_CFLAGS} $<
check:
install: zwrite
${LIBTOOL} --mode=install ${INSTALL} -m 755 zwrite ${DESTDIR}${bindir}
${INSTALL} -m 644 ${srcdir}/zwrite.1 ${DESTDIR}${mandir}/man1
clean:
${LIBTOOL} --mode=clean rm -f zwrite
rm -f ${OBJS}
${OBJS}: ${top_srcdir}/h/sysdep.h ${BUILDTOP}/h/config.h
${OBJS}: ${BUILDTOP}/h/zephyr/zephyr.h ${BUILDTOP}/h/zephyr/zephyr_err.h
.PHONY: all check install clean

290
clients/zwrite/zwrite.1 Normal file
View File

@ -0,0 +1,290 @@
.\" $Id$
.\"
.\" Copyright 1987,1988 by the Massachusetts Institute of Technology
.\" All rights reserved. The file /usr/include/zephyr/mit-copyright.h
.\" specifies the terms and conditions for redistribution.
.\"
.\"
.TH ZWRITE 1 "October 26, 1989" "MIT Project Athena"
.ds ]W MIT Project Athena
.SH NAME
zwrite \- write to another user via Zephyr
.SH SYNOPSIS
.B zwrite
[
.BI \-a
] [
.BI \-d
] [
.BI \-v
] [
.BI \-q
] [
.BI \-t
] [
.BI \-u
] [
.BI \-o
] [
.BI \-n
] [
.BI \-l
] [
.BI \-C
] [
.BI \-U
] [
.BI \-O
opcode ] [
.BI \-s
signature ] [
.BI \-c
class ] [
.BI \-i
instance ] [
.BI \-r
realm ] [
.BI \-f
arg ] [
.BI \-S
sender ] [
.BI user \ ...
] [
.BI \-m
.BI message
]
.SH DESCRIPTION
.I Zwrite
sends a message from you to another user through the
.I zephyr(1)
notification service. The user must have subscribed to messages of
the appropriate class and instance using the
.I zctl(1)
program.
.PP
.I Zwrite
understands the following options.
.TP 12
.B \-a
Causes
.I zwrite
to send the message authenticated, using
.I Kerberos
to perform the authentication. This is the default.
.TP
.B \-d
Causes
.I zwrite
to send the message unauthenticated.
.TP
.B \-v
Causes
.I zwrite
to print what type of message it is sending, and whether or not it was
successful.
.TP
.B \-q
Forces
.I zwrite
to suppress information about whether or not the message was sent.
.TP
.B \-t
Prevents
.I zwrite
from expanding tabs in the message into appropriate spaces. Normally
.I zwrite
will expand any tabs it finds into the appropriate number of spaces to
maintain separation based on 8-character tab stops.
.TP
.B \-l
Causes
.I zwrite
to ignore `.' on a line by itself in the input and only end a typed
message when the user types the end-of-file character (usually
control-D). When the input is not a terminal, this is the default action.
.TP
.B \-u
Sends an urgent message. This changes the
.I zephyr
instance of the message to ``URGENT''.
.TP
.B \-o
Causes
.I zwrite
to ignore the Zephyr variables
.IR zwrite-class ,
.IR zwrite-inst ,
and
.I zwrite-opcode
when picking a default class, instance, and opcode.
.TP
.B \-n
prevents
.I zwrite
from sending a PING message to verify the recipient is subscribing to
messages. By default,
.I zwrite
will send a notice to the destination class, instance, and recipient,
with opcode ``PING'' before sending the message. If the PING is sent,
and the server response indicates there are no recipients subscribed to
your message,
.I zwrite
exits without sending a message.
When the
.B \-n
option is used, no PING is sent.
.TP
.B \-C
prepends a "CC:" line to the body of the message indicating the
recipients of the message. This is strictly a convenience: the
presence of a "CC:" line at the top of a zephyr body does not
necessarily indicate that this option was used, or that the message
really was sent to the listed users, and its lack doesn't indicate
that the message was not sent to multiple users.
.TP
.B \-U
Send an unacked message.
.I zwrite
will not wait for acknowledgement that the message was sent, nor will
it issue a PING before sending.
.TP
.B \-s \fIsignature\fR
sets the signature to be included in the message. This overrides both
the user's name (as found in the password file) and any
setting of the Zephyr variable
.IR zwrite-signature .
.I signature
must
be a single argument, hence when using a shell it should be quoted with
double quotes. A
.I signature
argument of "" leaves the signature in
the message empty.
.TP
.B \-c \fIclass\fR
Allows a user to specify a different class for the message. This allows
a message to be sent to a large group of people with some degree of
security. See
.I zephyr(1)
and
.I zephyrd(8)
for a description of how to restrict access to classes. When this option
is specified, the message is sent to recipient "*" unless an additional
list of recipients is specified.
.br
This argument may not be used in conjunction with the \-f option.
.TP
.B \-i \fIinstance\fR
Allows a user to specify a different instance than the default.
When this option is used, the message is sent to recipient "*" unless an
additional list of recipients is specified. This allows a message to be
sent to a large group of people (e.g. a development group) just by having
the members subscribe to messages of class "MESSAGE", the specified instance,
and recipient "*".
.br
This argument may not be used in conjunction with the \-f option.
.TP
.B \-r \fIrealm\fR
Allows a user to specify a different realm for the message, if the
server supports interrealm Zephyr.
.TP
.B \-S \fIsender\fR
Specify a sender. The message will be sent unauthenticated.
.TP
.B \-F \fIformat\fR
Allows a user to specify a different default format for the message.
.TP
.B \-O \fIopcode\fR
Allows a user to specify a different opcode for the message.
Some Zephyr notice display programs may use the opcode to decide how
to display a notice.
.TP
.B \-f \fIarg\fR
Allows a user to specify an argument to be interpreted as a filesystem
specification. The class is set to
.BR FILSRV .
he instance is set
to
.I arg
as modified:
If
.I arg
contains no colons (`:'), it is assumed to
be a host name, and it is converted into an official host name via
.I gethostbyname(3).
If
.I arg
contains a colon, the portion preceding the colon is
treated as a host name, and the colon and any trailing characters are
appended to the offical host name returned by
.I gethostbyname.
If the name fails to resolve into an official host name, the instance is
set to
.I arg
unmodified.
.br
This option may not be used in conjunction with the \-c or \-i option.
.TP
.B \-m
.I Zwrite
sends the remaining arguments on the command line as the message.
.PP
If the
.I \-m
option is not specified, the user is prompted for the message to be
sent. The message may be terminated by typing ^D or ``.'' on a line
by itself.
.PP
The default class for messages is ``MESSAGE'', the default instance
is ``PERSONAL'', andthe default opcode is ``'' (an empty string).
These defaults can be overridden by setting the Zephyr
variables
.IR zwrite-class ,
.IR zwrite-inst ,
and
.IR zwrite-opcode ,
respectively.
Command-line options can override the defaults.
.PP
If the class is ``MESSAGE'' and the instance is either ``PERSONAL'' or
``URGENT'', a recipient must be specified. These comparisons are
case-sensitive.
.PP
Unless the
.B \-s
option is used, the contents of the Zephyr variable
.I zwrite-signature
are used to augment the user's username in the
message. If
.I zwrite-signature
is not set and the
.B \-s
option is not specified, the user's full name (as specified in the
password file) is used instead.
.SH BUGS
Tab expansion should really be done by the receiver of the message.
.br
The \-u option is provided for compatibility with old versions of
.I zwrite
and is not necessarily useful for sending messages to users who do not
have old subscription files.
.SH SEE ALSO
kerberosintro(1), zctl(1), zephyr(1), zwgc(1), zhm(8), zephyrd(8),
gethostbyname(3)
.br
Project Athena Technical Plan Section E.4.1, `Zephyr Notification
Service'
.SH FILES
/etc/passwd
.br
$ZEPHYR_VARS or $HOME/.zephyr.vars
.SH AUTHOR
.PP
.br
Robert S. French (MIT-Project Athena)
.SH RESTRICTIONS
Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
All Rights Reserved.
.br
.I zephyr(1)
specifies the terms and conditions for redistribution.

568
clients/zwrite/zwrite.c Normal file
View File

@ -0,0 +1,568 @@
/* This file is part of the Project Athena Zephyr Notification System.
* It contains code for the "zwrite" command.
*
* Created by: Robert French
*
* $Id$
*
* Copyright (c) 1987,1988 by the Massachusetts Institute of Technology.
* For copying and distribution information, see the file
* "mit-copyright.h".
*/
#include <sysdep.h>
#include <zephyr/mit-copyright.h>
#include <zephyr/zephyr.h>
#include <netdb.h>
#include <pwd.h>
#ifndef lint
static const char rcsid_zwrite_c[] = "$Id$";
#endif /* lint */
#define DEFAULT_CLASS "MESSAGE"
#define DEFAULT_INSTANCE "PERSONAL"
#define URGENT_INSTANCE "URGENT"
#define DEFAULT_OPCODE ""
#define FILSRV_CLASS "FILSRV"
#define MAXRECIPS 100
int nrecips, msgarg, verbose, quiet, nodot, cc;
char *whoami, *inst, *class, *opcode, *realm, *recips[MAXRECIPS], *sender = 0;
Z_AuthProc auth;
ZNotice_Kind_t kind = ACKED;
void un_tabify(char **, int *);
char *fix_filsrv_inst(char *);
void usage(char *);
void send_off(ZNotice_t *, int);
int
main(int argc, char *argv[])
{
int retval, arg, nocheck, nchars, msgsize, filsys, tabexpand;
char *message, *signature = NULL, *format = NULL;
static char bfr[BUFSIZ], classbfr[BUFSIZ], instbfr[BUFSIZ], sigbfr[BUFSIZ];
static char opbfr[BUFSIZ];
static ZNotice_t notice;
char *charset = NULL;
whoami = argv[0];
if ((retval = ZInitialize()) != ZERR_NONE) {
com_err(whoami, retval, "while initializing");
exit(1);
}
if (argc < 2)
usage(whoami);
auth = ZAUTH;
verbose = quiet = msgarg = nrecips = nocheck = filsys = nodot = 0;
tabexpand = 1;
class = ZGetVariable("zwrite-class");
if (class) {
(void) strcpy(classbfr, class);
class = classbfr;
}
else
class = DEFAULT_CLASS;
inst = ZGetVariable("zwrite-inst");
if (inst) {
(void) strcpy(instbfr, inst);
inst = instbfr;
}
else
inst = DEFAULT_INSTANCE;
opcode = ZGetVariable("zwrite-opcode");
if (opcode)
opcode = strcpy(opbfr, opcode);
else
opcode = DEFAULT_OPCODE;
signature = ZGetVariable("zwrite-signature");
if (signature) {
(void) strcpy(sigbfr, signature);
signature = sigbfr;
}
arg = 1;
for (;arg<argc && !msgarg; arg++) {
if (*argv[arg] != '-') {
recips[nrecips++] = argv[arg];
continue;
}
if (strlen(argv[arg]) > 2)
usage(whoami);
switch (argv[arg][1]) {
case 'a': /* Backwards compatibility */
auth = ZAUTH;
break;
case 'o':
class = DEFAULT_CLASS;
inst = DEFAULT_INSTANCE;
opcode = DEFAULT_OPCODE;
break;
case 'd':
auth = ZNOAUTH;
break;
case 'v':
verbose = 1;
break;
case 'q':
quiet = 1;
break;
case 'n':
nocheck = 1;
break;
case 't':
tabexpand = 0;
break;
case 'u':
inst = URGENT_INSTANCE;
break;
case 'O':
if (arg == argc-1)
usage(whoami);
arg++;
opcode = argv[arg];
break;
case 'i':
if (arg == argc-1 || filsys == 1)
usage(whoami);
arg++;
inst = argv[arg];
filsys = -1;
break;
case 'c':
if (arg == argc-1 || filsys == 1)
usage(whoami);
arg++;
class = argv[arg];
filsys = -1;
break;
case 'f':
if (arg == argc-1 || filsys == -1)
usage(whoami);
arg++;
class = FILSRV_CLASS;
inst = fix_filsrv_inst(argv[arg]);
filsys = 1;
nocheck = 1; /* implied -n (no ping) */
break;
case 's':
if (arg == argc-1)
usage(whoami);
arg++;
signature = argv[arg];
break;
case 'm':
if (arg == argc-1)
usage(whoami);
nocheck = 1; /* implied -n (no ping) */
msgarg = arg+1;
break;
case 'l': /* literal */
nodot = 1;
break;
case 'F':
if (arg == argc-1)
usage(whoami);
arg++;
format = argv[arg];
break;
case 'r':
if (arg == argc-1)
usage(whoami);
arg++;
realm = argv[arg];
break;
case 'C':
cc = 1;
break;
case 'x':
if (arg == argc-1)
usage(whoami);
arg++;
charset = argv[arg];
break;
case 'S':
if (arg == argc-1)
usage(whoami);
arg++;
sender = argv[arg];
auth = ZNOAUTH;
break;
case 'U':
kind = UNACKED;
nocheck = 1; /* implied -n (no ping) */
break;
default:
usage(whoami);
}
}
if (!nrecips && !(strcmp(class, DEFAULT_CLASS) ||
(strcmp(inst, DEFAULT_INSTANCE) &&
strcmp(inst, URGENT_INSTANCE)))) {
/* must specify recipient if using default class and
(default instance or urgent instance) */
fprintf(stderr, "No recipients specified.\n");
usage(whoami);
}
if (!signature) {
/* try to find name in the password file */
register struct passwd *pwd;
register char *cp = sigbfr;
register char *cp2, *pp;
pwd = getpwuid(getuid());
if (pwd) {
cp2 = pwd->pw_gecos;
for (; *cp2 && *cp2 != ',' ; cp2++) {
if (*cp2 == '&') {
pp = pwd->pw_name;
*cp++ = islower(*pp) ? toupper(*pp) : *pp;
pp++;
while (*pp)
*cp++ = *pp++;
} else
*cp++ = *cp2;
}
signature = sigbfr;
}
}
memset(&notice, 0, sizeof(ZNotice_t));
notice.z_kind = kind;
notice.z_port = 0;
notice.z_class = class;
notice.z_class_inst = inst;
notice.z_opcode = "PING";
notice.z_sender = sender;
notice.z_message_len = 0;
notice.z_recipient = "";
notice.z_charset = ZGetCharset(charset);
if (format)
notice.z_default_format = format;
else
notice.z_default_format = "http://zephyr.1ts.org/wiki/df";
if (!nocheck && nrecips)
send_off(&notice, 0);
if (!msgarg && isatty(0)) {
if (nodot)
printf("Type your message now. End with the end-of-file character.\n");
else
printf("Type your message now. End with control-D or a dot on a line by itself.\n");
}
message = NULL;
msgsize = 0;
if (signature) {
message = malloc((unsigned)(strlen(signature)+2));
(void) strcpy(message, signature);
msgsize = strlen(message);
message[msgsize++] = '\0';
} else {
message = malloc(1);
message[msgsize++] = '\0';
}
if (cc && nrecips > 1) {
int size = msgsize;
for (arg=0;arg<nrecips;arg++)
size += (strlen(recips[arg]) + 2);
size += 6; /* for the newlines and "cc: " */
message = realloc(message, (unsigned) size);
(void) strcpy(message+msgsize, "CC: ");
msgsize += 4;
for (arg=0;arg<nrecips;arg++) {
(void) strcpy(message+msgsize, recips[arg]);
msgsize += strlen(recips[arg]);
if (arg != nrecips-1) {
message[msgsize] = ' ';
msgsize++;
}
}
message[msgsize] = '\n';
msgsize += 1;
}
if (msgarg) {
int size = msgsize;
for (arg=msgarg;arg<argc;arg++)
size += (strlen(argv[arg]) + 1);
size++; /* for the newline */
message = realloc(message, (unsigned) size);
for (arg=msgarg;arg<argc;arg++) {
(void) strcpy(message+msgsize, argv[arg]);
msgsize += strlen(argv[arg]);
if (arg != argc-1) {
message[msgsize] = ' ';
msgsize++;
}
}
message[msgsize] = '\n';
msgsize += 1;
} else {
if (isatty(0)) {
for (;;) {
unsigned int l;
if (!fgets(bfr, sizeof bfr, stdin))
break;
if (!nodot && bfr[0] == '.' &&
(bfr[1] == '\n' || bfr[1] == '\0'))
break;
l = strlen(bfr);
message = realloc(message, msgsize+l+1);
(void) strcpy(message+msgsize, bfr);
msgsize += l;
}
if (ferror(stdin)) /* drop the message */
exit(1);
message = realloc(message, (unsigned)(msgsize+1));
}
else { /* Use read so you can send binary messages... */
while ((nchars = read(fileno(stdin), bfr, sizeof bfr))) {
if (nchars == -1) {
fprintf(stderr, "Read error from stdin! Can't continue!\n");
exit(1);
}
message = realloc(message, (unsigned)(msgsize+nchars));
(void) memcpy(message+msgsize, bfr, nchars);
msgsize += nchars;
}
/* end of msg */
message = realloc(message, (unsigned)(msgsize+1));
}
}
notice.z_opcode = opcode;
if (tabexpand)
un_tabify(&message, &msgsize);
notice.z_message = message;
notice.z_message_len = msgsize;
send_off(&notice, 1);
exit(0);
}
void
send_off(ZNotice_t *notice, int real)
{
int i, success, retval;
char realm_recip[BUFSIZ], dest[3 * BUFSIZ];
ZNotice_t retnotice;
success = 0;
for (i=0;i<nrecips || i==0;i++) {
if (realm) {
sprintf(realm_recip, "%s@%s", (nrecips) ? recips[i] : "", realm);
notice->z_recipient = realm_recip;
} else {
notice->z_recipient = (nrecips) ? recips[i] : "";
}
if (nrecips)
strcpy(dest, recips[i]);
else if (!strcmp(class, DEFAULT_CLASS))
sprintf(dest, "instance \"%s\"", inst);
else if (!strcmp(inst, DEFAULT_INSTANCE))
sprintf(dest, "class \"%s\"", class);
else
sprintf(dest, "class \"%s\", instance \"%s\"", class, inst);
if (verbose && real)
printf("Sending %smessage, class %s, instance %s, to %s\n",
auth?"authenticated ":"",
class, inst,
nrecips?notice->z_recipient:"everyone");
if ((retval = ZSendNotice(notice, auth)) != ZERR_NONE) {
com_err(whoami, retval, "while sending notice to %s", dest);
break;
}
if (kind == UNACKED)
continue;
if (real && !quiet) {
if (verbose)
printf("Queued... ");
else
printf("Message queued for %s... ", dest);
fflush(stdout);
}
if ((retval = ZIfNotice(&retnotice, (struct sockaddr_in *) 0,
ZCompareUIDPred,
(char *)&notice->z_uid)) != ZERR_NONE) {
com_err(whoami, retval, "while waiting for acknowledgement for %s",
dest);
continue;
}
if (retnotice.z_kind == SERVNAK) {
if (!quiet) {
printf("Received authorization failure while sending to %s\n",
dest);
}
ZFreeNotice(&retnotice);
break; /* if auth fails, punt */
}
if (retnotice.z_kind != SERVACK || !retnotice.z_message_len) {
if (!quiet) {
printf("Detected server failure while receiving acknowledgement for %s\n",
dest);
}
ZFreeNotice(&retnotice);
continue;
}
if (!strcmp(retnotice.z_message, ZSRVACK_SENT)) {
success = 1;
if (real && !quiet)
printf("sent\n");
} else if (!strcmp(retnotice.z_message, ZSRVACK_NOTSENT)) {
if (verbose && real && !quiet) {
if (strcmp(class, DEFAULT_CLASS)) {
fprintf(stderr, "Not logged in or not subscribing to class %s, instance %s\n",
class, inst);
} else {
fprintf(stderr,
"Not logged in or not subscribing to messages\n");
}
}
else if (!quiet) {
if (!nrecips) {
fprintf(stderr,
"No one subscribing to class %s, instance %s\n",
class, inst);
} else {
if (strcmp(class, DEFAULT_CLASS)) {
fprintf(stderr, "%s: Not logged in or not subscribing to class %s, instance %s\n",
notice->z_recipient, class, inst);
} else {
fprintf(stderr, "%s: Not logged in or not subscribing to messages\n",
notice->z_recipient);
}
}
}
}
else
printf("Internal failure - illegal message field in server response\n");
ZFreeNotice(&retnotice);
}
if (!success)
exit(1);
}
void
usage(char *s)
{
fprintf(stderr,
"Usage: %s [-a] [-o] [-d] [-v] [-q] [-n] [-t] [-u] [-l]\n\
\t[-c class] [-i inst] [-O opcode] [-f fsname] [-s signature] [-C]\n\
\t[user ...] [-F format] [-r realm] [-x charset] [-m message]\n", s);
fprintf(stderr,"\t-f and -c are mutually exclusive\n\
\t-f and -i are mutually exclusive\n\
\trecipients must be specified unless -c or -f specifies a class\n\
\tother than the default class or -i or -f specifies an instance\n\
\tother than the default or urgent instance\n");
exit(1);
}
/*
if the -f option is specified, this routine is called to canonicalize
an instance of the form hostname[:pack]. It turns the hostname into the
name returned by gethostbyname(hostname)
*/
char *
fix_filsrv_inst(char *str)
{
static char fsinst[BUFSIZ];
char *ptr;
struct hostent *hp;
ptr = strchr(str,':');
if (ptr)
*ptr = '\0';
hp = gethostbyname(str);
if (!hp) {
if (ptr)
*ptr = ':';
return(str);
}
(void) strcpy(fsinst, hp->h_name);
if (ptr) {
(void) strcat(fsinst, ":");
ptr++;
(void) strcat(fsinst, ptr);
}
return(fsinst);
}
/* convert tabs in the buffer into appropriate # of spaces.
slightly tricky since the buffer can have NUL's in it. */
#ifndef TABSTOP
#define TABSTOP 8 /* #chars between tabstops */
#endif /* ! TABSTOP */
void
un_tabify(char **bufp,
int *sizep)
{
register char *cp, *cp2;
char *cp3;
register int i;
register int column; /* column of next character */
register int size = *sizep;
for (cp = *bufp, i = 0; size; size--, cp++)
if (*cp == '\t')
i++; /* count tabs in buffer */
if (!i)
return; /* no tabs == no work */
/* To avoid allocation churning, allocate enough extra space to convert
every tab into TABSTOP spaces */
/* only add (TABSTOP-1)x because we re-use the cell holding the
tab itself */
cp = malloc((unsigned)(*sizep + (i * (TABSTOP-1))));
if (!cp) /* XXX */
return; /* punt expanding if memory fails */
cp3 = cp;
/* Copy buffer, converting tabs to spaces as we go */
for (cp2 = *bufp, column = 1, size = *sizep; size; cp2++, size--) {
switch (*cp2) {
case '\n':
case '\0':
/* newline or null: reset column */
column = 1;
*cp++ = *cp2; /* copy the newline */
break;
default:
/* copy the character */
*cp = *cp2;
cp++;
column++;
break;
case '\t':
/* it's a tab, compute how many spaces to expand into. */
i = TABSTOP - ((column - 1) % TABSTOP);
for (; i > 0; i--) {
*cp++ = ' '; /* fill in the spaces */
column++;
(*sizep)++; /* increment the size */
}
(*sizep)--; /* remove one (we replaced the tab) */
break;
}
}
free(*bufp); /* free the old buf */
*bufp = cp3;
return;
}