|
|
1.1 root 1: static char *rcsrev = "$Revision: 3.4 $";
2: static char *rcshdr =
3: "$Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $";
4: /*
5: * $Header: /usr/local/src/dist/mail/usermail/RCS/mail.c,v 3.4 91/02/18 17:14:10 piggy Exp $
6: * $Log: /usr/local/src/dist/mail/usermail/RCS/mail.c,v $
7: * Revision 3.4 91/02/18 17:14:10 piggy
8: * Fixed "q" command so that it works with a non-setuid mail.
9: *
10: * Revision 3.3 91/02/18 09:30:09 piggy
11: * Fixed two mishandlings of args[].
12: *
13: * Revision 3.2 91/02/08 15:16:07 piggy
14: * Updated error messages to include malloc failures.
15: *
16: * Revision 3.1 91/02/08 14:34:28 piggy
17: * Made csplit non-destructive.
18: *
19: * Revision 3.0 91/02/07 15:19:14 piggy
20: * *** empty log message ***
21: *
22: * Revision 2.13 90/03/30 16:16:19 wgl
23: * Correct seek pointer work within readmail.
24: *
25: * Revision 2.12 90/03/12 14:19:08 wgl
26: * New version of send doing aliases in a different place.
27: *
28: * Revision 2.11 90/03/08 16:41:15 wgl
29: * Add code to get signature file.
30: *
31: * Revision 2.10 90/03/02 10:41:59 wgl
32: * Add the -a flag so that uucp does not look like it is coming from
33: * somewhere else.
34: *
35: * Revision 2.9 90/03/01 11:17:19 wgl
36: * Final conversion to rely soley on ^A^A as separators.
37: * Effectively delete concept of m_hsize.
38: *
39: * Revision 2.8 90/03/01 10:14:31 wgl
40: * Go buy separators, not "From_" lines.
41: *
42: * Revision 2.7 90/02/28 17:11:41 wgl
43: * Add version print, add some changes to the message-id field.
44: *
45: * Revision 2.6 90/02/28 16:42:09 wgl
46: * Version number fakeout.
47: *
48: * Revision 2.5 90/02/28 16:19:44 wgl
49: * Try again to get versioin number right.
50: *
51: * Revision 2.4 90/02/28 16:18:56 wgl
52: * Get version number right.
53: *
54: * Revision 2.3 90/02/28 16:04:59 wgl
55: * Many changes; ripped out send.
56: * Changes are to make it work with uucp and internet mail.
57: *
58: * Revision 1.6 89/02/22 05:34:00 bin
59: * Changes by rec to integrate with lauren's uumail.
60: *
61: * Revision 1.5 88/09/01 14:49:01 bin
62: * Source administration: Re-install declaration of getenv.
63: * It was inserted after epstein made his copy.
64: *
65: * Revision 1.4 88/09/01 14:44:49 bin
66: * Mark Epsteins changes for ASKCC and for message scrolling, and interrupt
67: * handling during processing.
68: *
69: * Revision 1.3 88/09/01 14:27:41 bin
70: * declare getenv to get rid of integer pointer pun error message.
71: *
72: * Revision 1.2 88/09/01 11:02:23 bin
73: * Remove extra declaration of header which had rcs stuff in it.
74: *
75: * Revision 1.1 88/09/01 10:55:34 bin
76: * Initial revision
77: *
78: */
79: /*
80: * The mail command.
81: * Coherent electronic postal system, user agent.
82: * With v3.0 this program no longer runs setuid.
83: * Modifications by rec january 1986 to include xmail.
84: * by epstein november 1987 to include CC:
85: * by epstein november 1987 to allow ^C exit to leave you in
86: * mail command processor
87: * by epstein november 1987 to substitute /usr/games/fortune
88: * for printing encrypted messages
89: * by rec february 1989 to tail to lauren weinstein's
90: * mail for alias expansion and uucp queuing.
91: * by wgl January 1990 to handle uucp mail more directly.
92: */
93:
94: char isummary[] = "\
95: \
96: Command summary:\n\
97: d Delete current message and print the next message\n\
98: m [user ...] Mail current message to each named 'user'\n\
99: p Print current message again\n\
100: q Quit and update the mailbox\n\
101: r Reverse direction of scan\n\
102: s [file ...] Save message in each named 'file'\n\
103: t [user ...] Mail standard input to each named 'user'\n\
104: w [file ...] Save message in each named 'file' without its header\n\
105: x Exit without updating mailbox\n\
106: newline Print the next message\n\
107: . Print current message again\n\
108: + Print the next message\n\
109: - Print the previous message\n\
110: EOF Put undeleted mail back into mailbox and quit\n\
111: ? Print this command summary\n\
112: !command Pass 'command' to the shell to execute\n\
113: If no 'file' is specified, 'mbox' in user's home directory is default.\n\
114: If no 'user' is specified, the invoking user is default.\n\
115: If the 'm', 'p', 't' commands are followed by an 'x',\n\
116: then the public key cryptosystem is applied to the message.\n\
117: \
118: ";
119:
120: #include "mail.h"
121:
122: #define NARGS 64 /* Maximum # args to interactive command */
123:
124: extern char *getenv();
125: extern int optind;
126: extern char *optarg;
127: extern char getopt();
128: extern char *malloc();
129: int csplit();
130: char *eat_ws();
131: char *find_ws();
132: char *revnop();
133:
134: int mflag; /* `You have mail.' message to recipient */
135: int rflag; /* Reverse order of print */
136: int qflag; /* Exit after interrrupts */
137: int pflag; /* Print mail */
138: int verbflag; /* verbose */
139: int callmexmail; /* Xmail modifier present */
140: int callmermail; /* rmail modifier present */
141: struct msg {
142: struct msg *m_next; /* Link to next message */
143: struct msg *m_prev; /* Link to previous message */
144: int m_flag; /* Flags - non-zero if deleted */
145: int m_hsize; /* Size of header of message */
146: fsize_t m_seek; /* Start position of message */
147: fsize_t m_end; /* End of message */
148: };
149: struct msg *m_first = NULL; /* First message */
150: struct msg *m_last = NULL; /* Last message */
151:
152: struct tm *tp;
153:
154: char iusage[] = "Bad command--type '?' for command summary\n";
155: char nombox[] = "No mailbox '%s'.\n";
156: char nomail[] = "No mail.\n";
157: char noperm[] = "Mailbox '%s' access denied.\n";
158: char moerr[] = "Cannot open mailbox '%s'\n";
159: char wrerr[] = "Write error on '%s'\n";
160: char nosave[] = "Cannot save letter in '%s'\n";
161: char allocerr[] = "%s: Can't malloc.\n";
162:
163: FILE *mfp; /* Mailbox stream */
164: int myuid; /* User-id of mail user */
165: int mygid; /* Group-id of mail user */
166: char myname[25]; /* User name */
167: char myfullname[50];
168: char mymbox[256]; /* $HOME/mbox */
169: char mydead[256]; /* $HOME/dead.letter */
170: char mysig[256]; /* $HOME/.sig.mail */
171: char myalias[256]; /* $HOME/.aliases */
172: char spoolname[50] = SPOOLDIR;
173: char *mailbox = spoolname;
174: char cmdname[1024]; /* Command for x{en,de}code filter */
175: /* and for tail recursion to uumail */
176: /* and for editor recursion */
177:
178: char *args[NARGS]; /* Interactive command arglist */
179: char msgline[NLINE];
180: char cline[NCLINE] = "+\n";
181: char *temp; /* Currently open temp file */
182: char templ[] = "/tmp/mailXXXXXX"; /* Temp file name template */
183: char *editname; /* name of editor */
184: char *scatname; /* name of scat filter */
185: char *askcc; /* Ask for CC: list? (YES/NO) */
186:
187: fsize_t ftell();
188: char *getlogin();
189: char *mktemp();
190: int catchintr();
191: int catchpipe();
192: char asuser [32];
193:
194: main(argc, argv)
195: char *argv[];
196: {
197: register char *ap;
198: char c, *foo;
199: int i;
200:
201: logopen();
202:
203: /* Explicitly NULL out args. */
204: for (i = 0; i < NARGS; ++i) {
205: args[i] = NULL;
206: }
207:
208: ap = argv[0];
209: if ( (foo=rindex(ap, '/')) != NULL )
210: ap = foo+1;
211: callmermail = (strcmp(ap, "rmail") == 0);
212: callmexmail = (strcmp(ap, "xmail") == 0);
213:
214: if (callmermail)
215: logdump("argv0 = rmail\n");
216:
217: asuser [0] = '\0';
218: signal(SIGINT, catchintr);
219: signal(SIGPIPE, catchpipe);
220: while ((c = getopt(argc, argv, "a:f:mpqrv")) != EOF) {
221: switch(c) {
222: case 'f':
223: if (!callmermail)
224: mailbox = optarg;
225: break;
226: case 'a':
227: strcpy(asuser, optarg);
228: break;
229: case 'm':
230: mflag++;
231: break;
232: case 'p':
233: pflag++;
234: break;
235: case 'q':
236: qflag++;
237: break;
238: case 'r':
239: rflag++;
240: break;
241: case 'v':
242: fprintf(stderr, "mail, ver. %s\n", revnop());
243: verbflag++;
244: break;
245: default:
246: usage();
247: }
248: }
249: if (callmermail)
250: verbflag = mflag = pflag = rflag = 0;
251: setname();
252: if (optind < argc) {
253: qflag = 1;
254: if ( send2(stdin, &argv[optind], (fsize_t)0,
255: (fsize_t)MAXLONG, 1) != 0 )
256: rmexit(1);
257: } else {
258: if ( ! pflag)
259: callmexmail = 0;
260: commands();
261: }
262: rmexit(0);
263: }
264:
265: /*
266: * Setup all the identities for the current user.
267: */
268: setname()
269: {
270: register struct passwd *pwp;
271: register char *np;
272: extern struct passwd * getpwnam();
273:
274: if (strlen(asuser) > 0) {
275: if((pwp = getpwnam(asuser)) == NULL)
276: merr("No such user %s.\n", asuser);
277: myuid = pwp -> pw_uid;
278: } else
279: myuid = getuid();
280: if ((pwp = getpwuid(myuid)) == NULL)
281: merr("Who are you?\n");
282: np = pwp->pw_name;
283: mygid = pwp->pw_gid;
284: strcat(spoolname, np);
285: strcpy(myname, np);
286: strcpy(myfullname, pwp->pw_gecos);
287: strcpy(mymbox, pwp->pw_dir);
288: strcat(mymbox, "/mbox");
289: strcpy(mydead, pwp->pw_dir);
290: strcat(mydead, "/dead.letter");
291: strcpy(mysig, pwp->pw_dir);
292: strcat(mysig, "/.sig.mail");
293: strcpy(myalias, pwp->pw_dir);
294: strcat(myalias, "/.aliases");
295: mktemp(templ);
296:
297: if ((editname=getenv("EDITOR"))==NULL)
298: editname = "/bin/ed";
299:
300: if ( ((scatname=getenv("PAGER")) != NULL) &&
301: (strlen(scatname) == 0) )
302: scatname = NULL;
303:
304: if ((askcc=getenv("ASKCC")) != NULL)
305: if ( strcmp(askcc, "YES") )
306: askcc = NULL;
307: }
308:
309: /*
310: * Process mail's interactive commands
311: * for reading/deleting/saving mail.
312: */
313: commands()
314: {
315: register struct msg *mp;
316: struct msg *dest;
317: register char **fnp;
318: register FILE *fp;
319: fsize_t seek;
320:
321: readmail();
322: mprint(mp = rflag ? m_last : m_first);
323: for (;;) {
324: readmail();
325: intcheck();
326: if ( ! pflag) {
327: callmexmail = 0;
328: mmsg("? ");
329: if (fgets(cline, sizeof cline, stdin) == NULL) {
330: if (intcheck())
331: continue;
332: break;
333: }
334: }
335: switch (cline[0]) {
336: case 'd':
337: if (cline[1] != '\n')
338: goto usage;
339: mp->m_flag += 1;
340: goto advance;
341:
342: case 'm':
343: case 't':
344: if (csplit(cline, args) == 1) {
345: /* We don't want to put anything into
346: args that we didn't get from malloc. */
347:
348: if (args[1] != NULL) {
349: free(args[1]);
350: }
351: args[1] = malloc(strlen(myname) + 1);
352: strcpy(args[1], myname);
353: args[2] = NULL;
354: }
355: callmexmail = (cline[1] == 'x');
356: if (cline[0] == 'm') {
357: send2(mfp, args+1, mp->m_seek, mp->m_end - 3, 0);
358: fseek(mfp, mp->m_seek, 0);
359: } else
360: send2(stdin, args+1, 0L, (fsize_t)MAXLONG, 1);
361: break;
362:
363: case '.':
364: case 'p':
365: if (cline[1] == 'x') {
366: callmexmail = 1;
367: if (cline[2] != '\n')
368: goto usage;
369: } else if (cline[1] != '\n')
370: goto usage;
371: if (mprint(mp))
372: break;
373: goto advance;
374:
375: case 'q':
376: if (cline[1] != '\n')
377: goto usage;
378: mquit();
379: /* NOTREACHED */
380:
381: case 'r':
382: if (cline[1] != '\n')
383: goto usage;
384: rflag = ! rflag;
385: break;
386: case 's':
387: case 'w':
388: if (csplit(cline, args) == 1) {
389: /* We don't want to put anything into
390: args that we didn't get from malloc. */
391:
392: if (args[1] != NULL) {
393: free(args[1]);
394: }
395: args[1] = malloc(strlen(mymbox) + 1);
396: strcpy(args[1], mymbox);
397: args[2] = NULL;
398: }
399: seek = mp->m_seek;
400: if (cline[0] == 'w')
401: seek += mp->m_hsize;
402: for (fnp = &args[1]; *fnp != NULL; fnp++) {
403: fp = NULL;
404: if (maccess(*fnp) < 0
405: || (fp = fopen(*fnp, "a")) == NULL
406: || mcopy(mfp, fp, seek, mp->m_end, 0))
407: mmsg(nosave, *fnp);
408: if (fp != NULL) {
409: fclose(fp);
410: chown(*fnp, myuid, mygid);
411: }
412: }
413: break;
414:
415: case 'x':
416: if (cline[1] != '\n')
417: goto usage;
418: rmexit(0);
419: /* NOTREACHED */
420:
421: case '!':
422: if (system(cline+1) == 127)
423: mmsg("Try again\n");
424: else
425: mmsg("!\n");
426: break;
427:
428: case '?':
429: mmsg(isummary);
430: break;
431:
432: case '-':
433: if (cline[1] != '\n')
434: goto usage;
435: dest = rflag ? m_last : m_first;
436: goto nextmsg;
437:
438: case '+':
439: if (cline[1] != '\n')
440: goto usage;
441: case '\n':
442: advance:
443: dest = rflag ? m_first : m_last;
444: nextmsg:
445: do {
446: if (mp == dest) {
447: if (pflag)
448: return;
449: mmsg("No more messages.\n");
450: break;
451: }
452: mp = (dest==m_last) ? mp->m_next : mp->m_prev;
453: } while (mprint(mp) == 0);
454: break;
455:
456: default:
457: usage:
458: mmsg(iusage);
459: break;
460: }
461: }
462: putc('\n', stderr);
463: mquit();
464: }
465:
466: /*
467: * Read through the mail-box file
468: * constructing list of letters.
469: * On subsequent calls, append any additional mail
470: * and notify the user.
471: */
472: readmail()
473: {
474: register struct msg *mp;
475: struct stat sb;
476: static long m_last_end;
477: int datasw;
478:
479: if (m_first == NULL) {
480: if (stat(mailbox, &sb) < 0)
481: merr(nombox, mailbox);
482: if (sb.st_size == 0)
483: merr(nomail);
484: if (access(mailbox, AREAD) < 0)
485: merr(noperm, mailbox);
486: if ((mfp = fopen(mailbox, "r")) == NULL)
487: merr(moerr, mailbox);
488: m_last_end = 0;
489: } else {
490: fstat(fileno(mfp), &sb);
491: if (sb.st_size == m_last_end)
492: return;
493: mmsg("More mail received.\n");
494: }
495:
496: for(mlock(myuid);;) {
497: fseek(mfp, m_last_end, 0);
498: datasw = 0;
499: while (fgets(msgline, sizeof msgline, mfp) != NULL) {
500: /* NB: this means the implicit message
501: seperator is actually "\n\1\1\n". */
502: if(!(datasw = strcmp("\1\1\n", msgline))) {
503: /* message seperator */
504: mp = (struct msg *)myalloc(sizeof(*mp));
505: mp->m_next = NULL;
506: mp->m_prev = m_last;
507: mp->m_flag = mp->m_hsize = 0;
508: mp->m_seek = m_last_end;
509: mp->m_end = m_last_end = ftell(mfp);
510: if (m_first == NULL)
511: m_last = m_first = mp;
512: else
513: m_last = m_last->m_next = mp;
514: }
515: }
516:
517: if(!datasw) /* data ended with message seperator */
518: break;
519:
520: /* unterminated data, patch and retry */
521: fclose(mfp);
522: if ((mfp = fopen(mailbox, "a")) == NULL)
523: merr(moerr, mailbox);
524: fprintf(mfp, "\1\1\n"); /* terminate it */
525: fclose(mfp);
526: if ((mfp = fopen(mailbox, "r")) == NULL)
527: merr(moerr, mailbox);
528: mmsg("Incomplete message found.\n");
529: }
530: munlock();
531: }
532:
533: /*
534: * Lock the appropriately-numbered mailbox
535: * (numbered by user-number) from multiple
536: * accesses. There is a (small) race here
537: * which will be overlooked for now.
538: */
539: char *lockname;
540:
541: mlock(uid)
542: int uid;
543: {
544: register int fd;
545: static char lock[32];
546:
547: lockname = lock;
548: sprintf(lock, "/tmp/maillock%d", uid);
549: while (access(lockname, 0) == 0)
550: sleep(1);
551: if ((fd = creat(lockname, 0)) >= 0)
552: close(fd);
553: }
554:
555: /*
556: * Unlock the currently-set lock (by `mlock')
557: * also called from rmexit.
558: */
559: munlock()
560: {
561: if (lockname != NULL)
562: unlink(lockname);
563: lockname = NULL;
564: }
565:
566: /*
567: * Exit, after rewriting the
568: * mailbox
569: */
570: mquit()
571: {
572: register struct msg *mp;
573: register FILE *nfp, *tmpfp;
574: struct stat sb;
575:
576: /* Get new stuff. */
577: readmail();
578: /* There is a slight race here. We really should
579: lock BEFORE the readmail(), but readmail() does unlocks...
580: FIX ME. */
581: mlock(myuid);
582:
583: if (mailbox != spoolname && maccess(mailbox) < 0)
584: merr(noperm, mailbox);
585: fstat(fileno(mfp), &sb);
586: signal(SIGINT, SIG_IGN);
587: signal(SIGPIPE, SIG_IGN);
588:
589: /* Make a copy of the mail box; we're going to overwrite it. */
590: tmpfp = tmp_copy(mfp);
591: fclose(mfp);
592:
593: if ((nfp = fopen(mailbox, "w")) == NULL)
594: merr("Cannot re-write '%s'\n", mailbox);
595: chown(mailbox, sb.st_uid, sb.st_gid);
596: chmod(mailbox, sb.st_mode&0777);
597: for (mp = m_first; mp != NULL; mp = mp->m_next) {
598:
599: if (mp->m_flag == 0) {
600: if (mcopy(tmpfp, nfp, mp->m_seek, mp->m_end, 0)) {
601: merr(wrerr, mailbox);
602: }
603: } /* if (mp->m_flag == 0) */
604:
605: } /* for (walk through the linked list of messages) */
606:
607: fclose(nfp);
608: fclose(tmpfp);
609: munlock();
610: rmexit(0);
611: }
612:
613: /*
614: * Print the current message, given by
615: * the message pointer (`mp').
616: */
617: mprint(mp)
618: register struct msg *mp;
619: {
620: FILE *xfp;
621:
622: if (mp->m_flag)
623: return 0;
624: if (callmexmail) {
625: if (scatname != NULL)
626: sprintf(cmdname, "xdecode | %s", scatname);
627: else
628: sprintf(cmdname, "xdecode");
629: if ((xfp = popen(cmdname, "w")) == NULL)
630: return 0;
631: mcopy(mfp, xfp, mp->m_seek+mp->m_hsize, mp->m_end, 1);
632: pclose(xfp);
633: } else {
634: fseek(mfp, mp->m_seek, 0);
635: if (fgets(msgline, sizeof msgline, mfp) != NULL &&
636: strncmp(msgline, "From xmail", 10) == 0) {
637: printf("From xmail\n");
638: system("/usr/games/fortune");
639: return(1);
640: }
641: if (scatname != NULL) {
642: sprintf(cmdname, "%s", scatname);
643: if ((xfp = popen(cmdname, "w")) == NULL)
644: return(0);
645: mcopy(mfp, xfp, mp->m_seek, mp->m_end - 3, 1);
646: if ( ((pclose(xfp)>>8)&0xFF) == SIGINT )
647: putc('\n', stdout);
648: } else {
649: mcopy(mfp, stdout, mp->m_seek, mp->m_end - 3, 1);
650: }
651: }
652: return (1);
653: }
654:
655: /*
656: * Get additional users to receive message (CC:)
657: */
658:
659: char **
660: getcc()
661: {
662: static char names[NCLINE];
663: static char *ccargs[NARGS];
664:
665: ccargs[0] = NULL;
666: mmsg("CC: ");
667: if ( fgets(names, sizeof names, stdin) == NULL )
668: return(ccargs);
669:
670: csplit(names, ccargs);
671: return(ccargs);
672: }
673:
674:
675: /*
676: * Errors, usage, and exit removing
677: * any tempfiles left around.
678: */
679: mmsg(x)
680: {
681: fprintf(stderr, "%r", &x);
682: }
683:
684: merr(x, s)
685: char *x, *s;
686: {
687: mmsg(x, s);
688: logdump("merr: ");
689: logdump(x, s);
690: rmexit(1);
691: }
692:
693: rmexit(s)
694: int s;
695: {
696: if (temp != NULL)
697: unlink(temp);
698: munlock();
699:
700: logdump("About to exit, status = 0x%04x\n", s);
701: logclose();
702:
703: exit(s);
704: }
705:
706: /*
707: * Catch interrupts, taking the
708: * appropriate action based on
709: * the `-q' option.
710: */
711: int intrflag; /* On when interrupt sent */
712: int pipeflag; /* On when broken pipe caught */
713:
714: catchintr()
715: {
716: logdump("Caught SIGINT\n");
717: if (qflag)
718: rmexit(1);
719: intrflag = 1;
720: signal(SIGINT, catchintr);
721: }
722:
723: catchpipe()
724: {
725: logdump("Caught SIGPIPE\n");
726: pipeflag = 1;
727: signal(SIGPIPE, catchpipe);
728: }
729:
730: intcheck()
731: {
732: if (intrflag || pipeflag) {
733: if (intrflag)
734: putc('\n', stdout);
735: intrflag = pipeflag = 0;
736: return (1);
737: }
738: return (0);
739: }
740:
741: /*
742: * Call the system to execute a command line
743: * which is passed as an argument.
744: * Change the user id and group id.
745: */
746: system(line)
747: char *line;
748: {
749: int status, pid;
750: register wpid;
751: register int (*intfun)(), (*quitfun)();
752:
753: if ((pid = fork()) < 0)
754: return (-1);
755: if (pid == 0) { /* Child */
756: setuid(myuid);
757: setgid(mygid);
758: execl("/bin/sh", "sh", "-c", line, NULL);
759: exit(0177);
760: }
761: intfun = signal(SIGINT, SIG_IGN);
762: quitfun = signal(SIGQUIT, SIG_IGN);
763: while ((wpid = wait(&status))!=pid && wpid>=0)
764: ;
765: if (wpid < 0)
766: status = wpid;
767: signal(SIGINT, intfun);
768: signal(SIGQUIT, quitfun);
769: return (status);
770: }
771:
772: char *
773: revnop()
774: {
775: register char *cp;
776: register char c;
777: static char revnobuf[32];
778:
779: if ((cp = index(rcsrev, ' ')) != NULL) {
780: while (((c = *++cp) == ' ') && (c != '\0'))
781: ;
782: strcpy(revnobuf, cp);
783: if ((cp = index(revnobuf, ' ')) != NULL)
784: *cp = '\0';
785: return (revnobuf);
786: } else
787: return("OOPS");
788: }
789:
790: /*
791: * Split a command line up into
792: * argv (passed) and argc (returned).
793: * We assume that elements of "args" are either NULL or they were
794: * returned from malloc, so that they can be freed.
795: */
796: int
797: csplit(command, args)
798: char *command;
799: char **args;
800: {
801: register char *cp;
802: int i, argsize;
803:
804: i = 0; /* Start filling in at the zero'th arg. */
805: cp = eat_ws(command);
806:
807: /* Walk "cp" through "command", copying segments as we go. */
808: while ( *cp != CNULL ) {
809: /* We've found an argument; find some space. */
810: if (args[i] != NULL ) {
811: free(args[i]);
812: }
813:
814: /* Figure out how big the argment is. */
815: argsize = (int) (find_ws(cp) - cp);
816:
817: /* Alloc enough space for it--include the trailing NULL. */
818: if ((args[i] = malloc(argsize + 1)) == NULL) {
819: mmsg(allocerr, "csplit");
820: return(0); /* Is this the approriate action?? */
821: }
822:
823: /* Copy the argument into the space. */
824: memcpy(args[i], cp, argsize);
825: args[i][argsize] = CNULL; /* This may be redundant. */
826:
827: /* Make sure that cp points to after the argument. */
828: cp += argsize;
829:
830: cp = eat_ws(cp);
831: ++i;
832: } /* while (walk "cp" through "command") */
833:
834: args[i] = NULL;
835: return (i);
836: }
837:
838: /*
839: * Find the next occurence of non-white space in character string s.
840: */
841: char *
842: eat_ws(s)
843: char *s;
844: {
845: while(isspace(*s)){
846: ++s;
847: }
848: return(s);
849: }
850:
851: /*
852: * Find next occurence of white space in character string s.
853: */
854: char *
855: find_ws(s)
856: register char *s;
857: {
858: while((*s != CNULL) && !isspace(*s) ){
859: ++s;
860: }
861: return(s);
862: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.