restore creation of y.tab.c
[unix-history] / usr / src / usr.bin / mail / collect.c
CommitLineData
06300dd9
KS
1#
2
3/*
4 * Mail -- a mail program
5 *
6 * Collect input from standard input, handling
7 * ~ escapes.
8 */
9
99f2cebd 10static char *SccsId = "@(#)collect.c 2.10 %G%";
06300dd9
KS
11
12#include "rcv.h"
13#include <sys/stat.h>
14
15/*
16 * Read a message from standard output and return a read file to it
17 * or NULL on error.
18 */
19
20/*
21 * The following hokiness with global variables is so that on
22 * receipt of an interrupt signal, the partial message can be salted
23 * away on dead.letter. The output file must be available to flush,
24 * and the input to read. Several open files could be saved all through
25 * Mail if stdio allowed simultaneous read/write access.
26 */
27
28static int (*savesig)(); /* Previous SIGINT value */
7feecf47 29static int (*savehup)(); /* Previous SIGHUP value */
ea394d88 30# ifdef VMUNIX
2d55c063 31static int (*savecont)(); /* Previous SIGCONT value */
ea394d88 32# endif VMUNIX
06300dd9
KS
33static FILE *newi; /* File for saving away */
34static FILE *newo; /* Output side of same */
35static int hf; /* Ignore interrups */
06300dd9
KS
36static int hadintr; /* Have seen one SIGINT so far */
37
38static jmp_buf coljmp; /* To get back to work */
39
40FILE *
41collect(hp)
42 struct header *hp;
43{
44 FILE *ibuf, *fbuf, *obuf;
0fa68535 45 int lc, cc, escape, collrub(), intack(), collhup, collcont(), eof;
06300dd9
KS
46 register int c, t;
47 char linebuf[LINESIZE], *cp;
48 extern char tempMail[];
97bff179 49 int notify();
ea394d88 50 extern collintsig(), collhupsig();
06300dd9
KS
51
52 noreset++;
06300dd9
KS
53 ibuf = obuf = NULL;
54 if (value("ignore") != NOSTR)
55 hf = 1;
56 else
57 hf = 0;
06300dd9 58 hadintr = 0;
ea394d88 59# ifdef VMUNIX
7feecf47
KS
60 if ((savesig = sigset(SIGINT, SIG_IGN)) != SIG_IGN)
61 sigset(SIGINT, hf ? intack : collrub), sighold(SIGINT);
62 if ((savehup = sigset(SIGHUP, SIG_IGN)) != SIG_IGN)
ea394d88 63 sigset(SIGHUP, collrub), sighold(SIGHUP);
2d55c063 64 savecont = sigset(SIGCONT, collcont);
ea394d88
KS
65# else VMUNIX
66 savesig = signal(SIGINT, SIG_IGN);
67 savehup = signal(SIGHUP, SIG_IGN);
68# endif VMUNIX
06300dd9
KS
69 newi = NULL;
70 newo = NULL;
71 if ((obuf = fopen(tempMail, "w")) == NULL) {
72 perror(tempMail);
73 goto err;
74 }
75 newo = obuf;
76 if ((ibuf = fopen(tempMail, "r")) == NULL) {
77 perror(tempMail);
78 newo = NULL;
79 fclose(obuf);
80 goto err;
81 }
82 newi = ibuf;
83 remove(tempMail);
84
85 /*
86 * If we are going to prompt for a subject,
87 * refrain from printing a newline after
88 * the headers (since some people mind).
89 */
90
91 t = GTO|GSUBJECT|GCC|GNL;
92 c = 0;
93 if (intty && sflag == NOSTR && hp->h_subject == NOSTR && value("ask"))
94 t &= ~GNL, c++;
95 if (hp->h_seq != 0) {
96 puthead(hp, stdout, t);
97 fflush(stdout);
98 }
99 if (c)
100 grabh(hp, GSUBJECT);
101 escape = ESCAPE;
102 if ((cp = value("escape")) != NOSTR)
103 escape = *cp;
0fa68535 104 eof = 0;
06300dd9
KS
105 for (;;) {
106 setjmp(coljmp);
ea394d88 107# ifdef VMUNIX
7feecf47
KS
108 sigrelse(SIGINT);
109 sigrelse(SIGHUP);
ea394d88
KS
110# else VMUNIX
111 if (savesig != SIG_IGN)
112 signal(SIGINT, hf ? intack : collintsig);
113 if (savehup != SIG_IGN)
114 signal(SIGHUP, collhupsig);
115# endif VMUNIX
06300dd9 116 flush();
0fa68535
KS
117 if (readline(stdin, linebuf) <= 0) {
118 if (intty && value("ignoreeof") != NOSTR) {
119 if (++eof > 35)
120 break;
ef45c47a 121 printf("Use \".\" to terminate letter\n",
0fa68535
KS
122 escape);
123 continue;
124 }
06300dd9 125 break;
0fa68535
KS
126 }
127 eof = 0;
06300dd9 128 hadintr = 0;
b068a67e
KS
129 if (intty && equal(".", linebuf) &&
130 (value("dot") != NOSTR || value("ignoreeof") != NOSTR))
06300dd9 131 break;
3dffb9c8 132 if (linebuf[0] != escape || rflag != NOSTR) {
06300dd9
KS
133 if ((t = putline(obuf, linebuf)) < 0)
134 goto err;
135 continue;
136 }
137 c = linebuf[1];
06300dd9
KS
138 switch (c) {
139 default:
140 /*
141 * On double escape, just send the single one.
142 * Otherwise, it's an error.
143 */
144
145 if (c == escape) {
146 if (putline(obuf, &linebuf[1]) < 0)
147 goto err;
148 else
149 break;
150 }
151 printf("Unknown tilde escape.\n");
152 break;
153
154 case 'C':
155 /*
156 * Dump core.
157 */
158
159 core();
160 break;
161
162 case '!':
163 /*
164 * Shell escape, send the balance of the
165 * line to sh -c.
166 */
167
168 shell(&linebuf[2]);
169 break;
170
171 case ':':
172 case '_':
173 /*
174 * Escape to command mode, but be nice!
175 */
176
343c874e 177 execute(&linebuf[2], 1);
06300dd9
KS
178 break;
179
180 case '.':
181 /*
182 * Simulate end of file on input.
183 */
ea394d88 184 goto eofl;
06300dd9
KS
185
186 case 'q':
187 case 'Q':
188 /*
189 * Force a quit of sending mail.
190 * Act like an interrupt happened.
191 */
192
06300dd9
KS
193 hadintr++;
194 collrub(SIGINT);
195 exit(1);
196
197 case 'h':
198 /*
199 * Grab a bunch of headers.
200 */
201 if (!intty || !outtty) {
202 printf("~h: no can do!?\n");
203 break;
204 }
205 grabh(hp, GTO|GSUBJECT|GCC|GBCC);
206 printf("(continue)\n");
207 break;
208
209 case 't':
210 /*
211 * Add to the To list.
212 */
213
214 hp->h_to = addto(hp->h_to, &linebuf[2]);
215 hp->h_seq++;
216 break;
217
218 case 's':
219 /*
220 * Set the Subject list.
221 */
222
223 cp = &linebuf[2];
224 while (any(*cp, " \t"))
225 cp++;
226 hp->h_subject = savestr(cp);
227 hp->h_seq++;
228 break;
229
230 case 'c':
231 /*
232 * Add to the CC list.
233 */
234
235 hp->h_cc = addto(hp->h_cc, &linebuf[2]);
236 hp->h_seq++;
237 break;
238
239 case 'b':
240 /*
241 * Add stuff to blind carbon copies list.
242 */
243 hp->h_bcc = addto(hp->h_bcc, &linebuf[2]);
244 hp->h_seq++;
245 break;
246
247 case 'd':
248 copy(deadletter, &linebuf[2]);
249 /* fall into . . . */
250
251 case 'r':
252 /*
253 * Invoke a file:
254 * Search for the file name,
255 * then open it and copy the contents to obuf.
256 */
257
258 cp = &linebuf[2];
259 while (any(*cp, " \t"))
260 cp++;
261 if (*cp == '\0') {
262 printf("Interpolate what file?\n");
263 break;
264 }
265 cp = expand(cp);
266 if (cp == NOSTR)
267 break;
268 if (isdir(cp)) {
269 printf("%s: directory\n");
270 break;
271 }
272 if ((fbuf = fopen(cp, "r")) == NULL) {
273 perror(cp);
274 break;
275 }
276 printf("\"%s\" ", cp);
277 flush();
278 lc = 0;
279 cc = 0;
280 while (readline(fbuf, linebuf) > 0) {
281 lc++;
282 if ((t = putline(obuf, linebuf)) < 0) {
283 fclose(fbuf);
284 goto err;
285 }
286 cc += t;
287 }
288 fclose(fbuf);
289 printf("%d/%d\n", lc, cc);
290 break;
291
292 case 'w':
293 /*
294 * Write the message on a file.
295 */
296
297 cp = &linebuf[2];
298 while (any(*cp, " \t"))
299 cp++;
300 if (*cp == '\0') {
301 fprintf(stderr, "Write what file!?\n");
302 break;
303 }
304 if ((cp = expand(cp)) == NOSTR)
305 break;
306 fflush(obuf);
307 rewind(ibuf);
308 exwrite(cp, ibuf, 1);
309 break;
310
311 case 'm':
312 case 'f':
313 /*
314 * Interpolate the named messages, if we
315 * are in receiving mail mode. Does the
316 * standard list processing garbage.
317 * If ~f is given, we don't shift over.
318 */
319
320 if (!rcvmode) {
321 printf("No messages to send from!?!\n");
322 break;
323 }
324 cp = &linebuf[2];
325 while (any(*cp, " \t"))
326 cp++;
327 if (forward(cp, obuf, c) < 0)
328 goto err;
329 printf("(continue)\n");
330 break;
331
332 case '?':
06300dd9
KS
333 if ((fbuf = fopen(THELPFILE, "r")) == NULL) {
334 printf("No help just now.\n");
335 break;
336 }
337 t = getc(fbuf);
338 while (t != -1) {
339 putchar(t);
340 t = getc(fbuf);
341 }
342 fclose(fbuf);
343 break;
344
345 case 'p':
346 /*
347 * Print out the current state of the
348 * message without altering anything.
349 */
350
351 fflush(obuf);
352 rewind(ibuf);
06300dd9
KS
353 printf("-------\nMessage contains:\n");
354 puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL);
355 t = getc(ibuf);
356 while (t != EOF) {
357 putchar(t);
358 t = getc(ibuf);
359 }
360 printf("(continue)\n");
361 break;
362
363 case '^':
364 case '|':
365 /*
366 * Pipe message through command.
367 * Collect output as new message.
368 */
369
370 obuf = mespipe(ibuf, obuf, &linebuf[2]);
371 newo = obuf;
372 ibuf = newi;
373 newi = ibuf;
374 printf("(continue)\n");
375 break;
376
377 case 'v':
378 case 'e':
379 /*
380 * Edit the current message.
381 * 'e' means to use EDITOR
382 * 'v' means to use VISUAL
383 */
384
385 if ((obuf = mesedit(ibuf, obuf, c)) == NULL)
386 goto err;
387 newo = obuf;
388 ibuf = newi;
389 printf("(continue)\n");
390 break;
391 break;
392 }
393 }
ea394d88 394eofl:
06300dd9
KS
395 fclose(obuf);
396 rewind(ibuf);
7feecf47
KS
397 sigset(SIGINT, savesig);
398 sigset(SIGHUP, savehup);
ea394d88 399# ifdef VMUNIX
97bff179 400 sigset(SIGCONT, savecont);
ea394d88 401# endif VMUNIX
06300dd9
KS
402 noreset = 0;
403 return(ibuf);
404
405err:
406 if (ibuf != NULL)
407 fclose(ibuf);
408 if (obuf != NULL)
409 fclose(obuf);
7feecf47
KS
410 sigset(SIGINT, savesig);
411 sigset(SIGHUP, savehup);
ea394d88 412# ifdef VMUNIX
2d55c063 413 sigset(SIGCONT, savecont);
ea394d88 414# endif VMUNIX
06300dd9
KS
415 noreset = 0;
416 return(NULL);
417}
418
419/*
420 * Non destructively interrogate the value of the given signal.
421 */
422
423psig(n)
424{
425 register (*wassig)();
426
7feecf47
KS
427 wassig = sigset(n, SIG_IGN);
428 sigset(n, wassig);
06300dd9
KS
429 return((int) wassig);
430}
431
432/*
433 * Write a file, ex-like if f set.
434 */
435
436exwrite(name, ibuf, f)
437 char name[];
438 FILE *ibuf;
439{
440 register FILE *of;
441 register int c;
442 long cc;
443 int lc;
444 struct stat junk;
445
446 if (f) {
447 printf("\"%s\" ", name);
448 fflush(stdout);
449 }
6d1cdf8d 450 if (stat(name, &junk) >= 0 && (junk.st_mode & S_IFMT) == S_IFREG) {
06300dd9
KS
451 if (!f)
452 fprintf(stderr, "%s: ", name);
453 fprintf(stderr, "File exists\n", name);
454 return(-1);
455 }
456 if ((of = fopen(name, "w")) == NULL) {
457 perror(NOSTR);
458 return(-1);
459 }
460 lc = 0;
461 cc = 0;
462 while ((c = getc(ibuf)) != EOF) {
463 cc++;
464 if (c == '\n')
465 lc++;
466 putc(c, of);
467 if (ferror(of)) {
468 perror(name);
469 fclose(of);
470 return(-1);
471 }
472 }
473 fclose(of);
474 printf("%d/%ld\n", lc, cc);
475 fflush(stdout);
476 return(0);
477}
478
479/*
480 * Edit the message being collected on ibuf and obuf.
481 * Write the message out onto some poorly-named temp file
482 * and point an editor at it.
483 *
484 * On return, make the edit file the new temp file.
485 */
486
487FILE *
488mesedit(ibuf, obuf, c)
489 FILE *ibuf, *obuf;
490{
491 int pid, s;
492 FILE *fbuf;
493 register int t;
97bff179 494 int (*sig)(), (*scont)(), foonly();
06300dd9
KS
495 struct stat sbuf;
496 extern char tempMail[], tempEdit[];
497 register char *edit;
498
7feecf47 499 sig = sigset(SIGINT, SIG_IGN);
ea394d88 500# ifdef VMUNIX
97bff179 501 scont = sigset(SIGCONT, foonly);
ea394d88 502# endif VMUNIX
06300dd9
KS
503 if (stat(tempEdit, &sbuf) >= 0) {
504 printf("%s: file exists\n", tempEdit);
505 goto out;
506 }
507 close(creat(tempEdit, 0600));
508 if ((fbuf = fopen(tempEdit, "w")) == NULL) {
509 perror(tempEdit);
510 goto out;
511 }
512 fflush(obuf);
513 rewind(ibuf);
514 t = getc(ibuf);
515 while (t != EOF) {
516 putc(t, fbuf);
517 t = getc(ibuf);
518 }
519 fflush(fbuf);
520 if (ferror(fbuf)) {
521 perror(tempEdit);
522 remove(tempEdit);
523 goto fix;
524 }
525 fclose(fbuf);
526 if ((edit = value(c == 'e' ? "EDITOR" : "VISUAL")) == NOSTR)
527 edit = c == 'e' ? EDITOR : VISUAL;
528 pid = vfork();
529 if (pid == 0) {
5388d5b8 530 sigchild();
06300dd9 531 if (sig != SIG_IGN)
7feecf47 532 sigsys(SIGINT, SIG_DFL);
06300dd9
KS
533 execl(edit, edit, tempEdit, 0);
534 perror(edit);
535 _exit(1);
536 }
537 if (pid == -1) {
538 perror("fork");
539 remove(tempEdit);
540 goto out;
541 }
542 while (wait(&s) != pid)
543 ;
5b0c1c37 544 if ((s & 0377) != 0) {
06300dd9
KS
545 printf("Fatal error in \"%s\"\n", edit);
546 remove(tempEdit);
547 goto out;
548 }
549
550 /*
551 * Now switch to new file.
552 */
553
554 if ((fbuf = fopen(tempEdit, "a")) == NULL) {
555 perror(tempEdit);
556 remove(tempEdit);
557 goto out;
558 }
559 if ((ibuf = fopen(tempEdit, "r")) == NULL) {
560 perror(tempEdit);
561 fclose(fbuf);
562 remove(tempEdit);
563 goto out;
564 }
565 remove(tempEdit);
566 fclose(obuf);
567 fclose(newi);
568 obuf = fbuf;
569 goto out;
570fix:
571 perror(tempEdit);
572out:
ea394d88 573# ifdef VMUNIX
97bff179 574 sigset(SIGCONT, scont);
ea394d88 575# endif VMUNIX
7feecf47 576 sigset(SIGINT, sig);
06300dd9
KS
577 newi = ibuf;
578 return(obuf);
579}
580
97bff179
KS
581/*
582 * Currently, Berkeley virtual VAX/UNIX will not let you change the
583 * disposition of SIGCONT, except to trap it somewhere new.
584 * Hence, sigset(SIGCONT, foonly) is used to ignore continue signals.
585 */
586foonly() {}
587
06300dd9
KS
588/*
589 * Pipe the message through the command.
590 * Old message is on stdin of command;
591 * New message collected from stdout.
592 * Sh -c must return 0 to accept the new message.
593 */
594
595FILE *
596mespipe(ibuf, obuf, cmd)
597 FILE *ibuf, *obuf;
598 char cmd[];
599{
600 register FILE *ni, *no;
601 int pid, s;
602 int (*savesig)();
603 char *Shell;
604
605 newi = ibuf;
606 if ((no = fopen(tempEdit, "w")) == NULL) {
607 perror(tempEdit);
608 return(obuf);
609 }
610 if ((ni = fopen(tempEdit, "r")) == NULL) {
611 perror(tempEdit);
612 fclose(no);
613 remove(tempEdit);
614 return(obuf);
615 }
616 remove(tempEdit);
7feecf47 617 savesig = sigset(SIGINT, SIG_IGN);
06300dd9
KS
618 fflush(obuf);
619 rewind(ibuf);
620 if ((Shell = value("SHELL")) == NULL)
621 Shell = "/bin/sh";
622 if ((pid = vfork()) == -1) {
623 perror("fork");
624 goto err;
625 }
626 if (pid == 0) {
627 /*
628 * stdin = current message.
629 * stdout = new message.
630 */
631
5388d5b8 632 sigchild();
06300dd9
KS
633 close(0);
634 dup(fileno(ibuf));
635 close(1);
636 dup(fileno(no));
637 for (s = 4; s < 15; s++)
638 close(s);
639 execl(Shell, Shell, "-c", cmd, 0);
640 perror(Shell);
641 _exit(1);
642 }
643 while (wait(&s) != pid)
644 ;
645 if (s != 0 || pid == -1) {
646 fprintf(stderr, "\"%s\" failed!?\n", cmd);
647 goto err;
648 }
649 if (fsize(ni) == 0) {
650 fprintf(stderr, "No bytes from \"%s\" !?\n", cmd);
651 goto err;
652 }
653
654 /*
655 * Take new files.
656 */
657
658 newi = ni;
659 fclose(ibuf);
660 fclose(obuf);
7feecf47 661 sigset(SIGINT, savesig);
06300dd9
KS
662 return(no);
663
664err:
665 fclose(no);
666 fclose(ni);
7feecf47 667 sigset(SIGINT, savesig);
06300dd9
KS
668 return(obuf);
669}
670
671/*
672 * Interpolate the named messages into the current
673 * message, preceding each line with a tab.
674 * Return a count of the number of characters now in
675 * the message, or -1 if an error is encountered writing
676 * the message temporary. The flag argument is 'm' if we
677 * should shift over and 'f' if not.
678 */
06300dd9
KS
679forward(ms, obuf, f)
680 char ms[];
681 FILE *obuf;
682{
683 register int *msgvec, *ip;
684 extern char tempMail[];
685
686 msgvec = (int *) salloc((msgCount+1) * sizeof *msgvec);
687 if (msgvec == (int *) NOSTR)
688 return(0);
689 if (getmsglist(ms, msgvec, 0) < 0)
690 return(0);
691 if (*msgvec == NULL) {
692 *msgvec = first(0, MMNORM);
693 if (*msgvec == NULL) {
694 printf("No appropriate messages\n");
695 return(0);
696 }
697 msgvec[1] = NULL;
698 }
699 printf("Interpolating:");
700 for (ip = msgvec; *ip != NULL; ip++) {
701 touch(*ip);
702 printf(" %d", *ip);
703 if (f == 'm') {
704 if (transmit(&message[*ip-1], obuf) < 0) {
705 perror(tempMail);
706 return(-1);
707 }
708 } else
99f2cebd 709 if (send(&message[*ip-1], obuf, 0) < 0) {
06300dd9
KS
710 perror(tempMail);
711 return(-1);
712 }
713 }
714 printf("\n");
715 return(0);
716}
717
718/*
719 * Send message described by the passed pointer to the
720 * passed output buffer. Insert a tab in front of each
721 * line. Return a count of the characters sent, or -1
722 * on error.
723 */
724
725transmit(mailp, obuf)
726 struct message *mailp;
727 FILE *obuf;
728{
729 register struct message *mp;
730 register int c, ch;
731 int n, bol;
732 FILE *ibuf;
733
734 mp = mailp;
735 ibuf = setinput(mp);
736 c = msize(mp);
737 n = c;
738 bol = 1;
739 while (c-- > 0) {
740 if (bol) {
741 bol = 0;
742 putc('\t', obuf);
743 n++;
744 if (ferror(obuf)) {
745 perror("/tmp");
746 return(-1);
747 }
748 }
749 ch = getc(ibuf);
750 if (ch == '\n')
751 bol++;
752 putc(ch, obuf);
753 if (ferror(obuf)) {
754 perror("/tmp");
755 return(-1);
756 }
757 }
758 return(n);
759}
760
2d55c063
KS
761/*
762 * Print (continue) when continued after ^Z.
763 */
764collcont(s)
765{
766
767 printf("(continue)\n");
768 fflush(stdout);
769}
770
06300dd9
KS
771/*
772 * On interrupt, go here to save the partial
7feecf47 773 * message on ~/dead.letter.
06300dd9
KS
774 * Then restore signals and execute the normal
775 * signal routine. We only come here if signals
776 * were previously set anyway.
777 */
778
ea394d88
KS
779# ifndef VMUNIX
780collintsig()
781{
782 signal(SIGINT, SIG_IGN);
783 collrub(SIGINT);
784}
785
786collhupsig()
787{
788 signal(SIGHUP, SIG_IGN);
789 collrub(SIGHUP);
790}
791# endif VMUNIX
792
06300dd9
KS
793collrub(s)
794{
795 register FILE *dbuf;
796 register int c;
797
7feecf47 798 if (s == SIGINT && hadintr == 0) {
06300dd9
KS
799 hadintr++;
800 clrbuf(stdout);
801 printf("\n(Interrupt -- one more to kill letter)\n");
ea394d88 802# ifdef VMUNIX
97bff179 803 sigrelse(s);
ea394d88 804# endif VMUNIX
06300dd9
KS
805 longjmp(coljmp, 1);
806 }
807 fclose(newo);
808 rewind(newi);
7feecf47 809 if (s == SIGINT && value("nosave") != NOSTR || fsize(newi) == 0)
06300dd9
KS
810 goto done;
811 if ((dbuf = fopen(deadletter, "w")) == NULL)
812 goto done;
813 chmod(deadletter, 0600);
814 while ((c = getc(newi)) != EOF)
815 putc(c, dbuf);
816 fclose(dbuf);
817
818done:
819 fclose(newi);
7feecf47
KS
820 sigset(SIGINT, savesig);
821 sigset(SIGHUP, savehup);
ea394d88 822# ifdef VMUNIX
2d55c063 823 sigset(SIGCONT, savecont);
ea394d88 824# endif VMUNIX
7feecf47
KS
825 if (rcvmode) {
826 if (s == SIGHUP)
827 hangup(SIGHUP);
828 else
2d55c063 829 stop(s);
7feecf47 830 }
06300dd9
KS
831 else
832 exit(1);
833}
834
835/*
836 * Acknowledge an interrupt signal from the tty by typing an @
837 */
838
839intack(s)
840{
841
06300dd9
KS
842 puts("@");
843 fflush(stdout);
844 clearerr(stdin);
06300dd9
KS
845}
846
847/*
848 * Add a string to the end of a header entry field.
849 */
850
851char *
852addto(hf, news)
853 char hf[], news[];
854{
855 register char *cp, *cp2, *linebuf;
856
857 if (hf == NOSTR)
858 hf = "";
859 if (*news == '\0')
860 return(hf);
861 linebuf = salloc(strlen(hf) + strlen(news) + 2);
862 for (cp = hf; any(*cp, " \t"); cp++)
863 ;
864 for (cp2 = linebuf; *cp;)
865 *cp2++ = *cp++;
866 *cp2++ = ' ';
867 for (cp = news; any(*cp, " \t"); cp++)
868 ;
869 while (*cp != '\0')
870 *cp2++ = *cp++;
871 *cp2 = '\0';
872 return(linebuf);
873}