1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.
   4:  *
   5:  * Redistribution and use in source and binary forms, with or without
   6:  * modification, are permitted provided that the following conditions
   7:  * are met:
   8:  * 1. Redistributions of source code must retain the above copyright
   9:  *    notice, this list of conditions and the following disclaimer.
  10:  * 2. Redistributions in binary form must reproduce the above copyright
  11:  *    notice, this list of conditions and the following disclaimer in the
  12:  *    documentation and/or other materials provided with the distribution.
  13:  * 3. All advertising materials mentioning features or use of this software
  14:  *    must display the following acknowledgement:
  15:  *	This product includes software developed by the University of
  16:  *	California, Berkeley and its contributors.
  17:  * 4. Neither the name of the University nor the names of its contributors
  18:  *    may be used to endorse or promote products derived from this software
  19:  *    without specific prior written permission.
  20:  *
  21:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31:  * SUCH DAMAGE.
  32:  */
  33: 
  34: #if !defined(lint) && defined(DOSCCS)
  35: static char sccsid[] = "@(#)cmd2.c	5.14 (Berkeley) 6/25/90";
  36: #endif
  37: 
  38: #include "rcv.h"
  39: #include <sys/wait.h>
  40: 
  41: /*
  42:  * Mail -- a mail program
  43:  *
  44:  * More user commands.
  45:  */
  46: 
  47: /*
  48:  * If any arguments were given, go to the next applicable argument
  49:  * following dot, otherwise, go to the next applicable message.
  50:  * If given as first command with no arguments, print first message.
  51:  */
  52: 
  53: next(msgvec)
  54:     int *msgvec;
  55: {
  56:     register struct message *mp;
  57:     register int *ip, *ip2;
  58:     int list[2], mdot;
  59: 
  60:     if (*msgvec != NULL) {
  61: 
  62:         /*
  63: 		 * If some messages were supplied, find the
  64: 		 * first applicable one following dot using
  65: 		 * wrap around.
  66: 		 */
  67: 
  68:         mdot = dot - &message[0] + 1;
  69: 
  70:         /*
  71: 		 * Find the first message in the supplied
  72: 		 * message list which follows dot.
  73: 		 */
  74: 
  75:         for (ip = msgvec; *ip != NULL; ip++)
  76:             if (*ip > mdot)
  77:                 break;
  78:         if (*ip == NULL)
  79:             ip = msgvec;
  80:         ip2 = ip;
  81:         do {
  82:             mp = &message[*ip2 - 1];
  83:             if ((mp->m_flag & MDELETED) == 0) {
  84:                 dot = mp;
  85:                 goto hitit;
  86:             }
  87:             if (*ip2 != NULL)
  88:                 ip2++;
  89:             if (*ip2 == NULL)
  90:                 ip2 = msgvec;
  91:         } while (ip2 != ip);
  92:         printf("No messages applicable\n");
  93:         return(1);
  94:     }
  95: 
  96:     /*
  97: 	 * If this is the first command, select message 1.
  98: 	 * Note that this must exist for us to get here at all.
  99: 	 */
 100: 
 101:     if (!sawcom)
 102:         goto hitit;
 103: 
 104:     /*
 105: 	 * Just find the next good message after dot, no
 106: 	 * wraparound.
 107: 	 */
 108: 
 109:     for (mp = dot+1; mp < &message[msgCount]; mp++)
 110:         if ((mp->m_flag & (MDELETED|MSAVED)) == 0)
 111:             break;
 112:     if (mp >= &message[msgCount]) {
 113:         printf("At EOF\n");
 114:         return(0);
 115:     }
 116:     dot = mp;
 117: hitit:
 118:     /*
 119: 	 * Print dot.
 120: 	 */
 121: 
 122:     list[0] = dot - &message[0] + 1;
 123:     list[1] = NULL;
 124:     return(type(list));
 125: }
 126: 
 127: /*
 128:  * Save a message in a file.  Mark the message as saved
 129:  * so we can discard when the user quits.
 130:  */
 131: save(str)
 132:     char str[];
 133: {
 134: 
 135:     return save1(str, 1, "save", saveignore);
 136: }
 137: 
 138: /*
 139:  * Copy a message to a file without affected its saved-ness
 140:  */
 141: copycmd(str)
 142:     char str[];
 143: {
 144: 
 145:     return save1(str, 0, "copy", saveignore);
 146: }
 147: 
 148: /*
 149:  * Save/copy the indicated messages at the end of the passed file name.
 150:  * If mark is true, mark the message "saved."
 151:  */
 152: save1(str, mark, cmd, ignore)
 153:     char str[];
 154:     char *cmd;
 155:     struct ignoretab *ignore;
 156: {
 157:     register int *ip;
 158:     register struct message *mp;
 159:     char *file, *disp;
 160:     int f, *msgvec;
 161:     FILE *obuf;
 162: 
 163:     msgvec = (int *) salloc((msgCount + 2) * sizeof *msgvec);
 164:     if ((file = snarf(str, &f)) == NOSTR)
 165:         return(1);
 166:     if (!f) {
 167:         *msgvec = first(0, MMNORM);
 168:         if (*msgvec == NULL) {
 169:             printf("No messages to %s.\n", cmd);
 170:             return(1);
 171:         }
 172:         msgvec[1] = NULL;
 173:     }
 174:     if (f && getmsglist(str, msgvec, 0) < 0)
 175:         return(1);
 176:     if ((file = expand(file)) == NOSTR)
 177:         return(1);
 178:     printf("\"%s\" ", file);
 179:     fflush(stdout);
 180:     if (access(file, 0) >= 0)
 181:         disp = "[Appended]";
 182:     else
 183:         disp = "[New file]";
 184:     if ((obuf = Fopen(file, "a")) == NULL) {
 185:         perror(NOSTR);
 186:         return(1);
 187:     }
 188:     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
 189:         mp = &message[*ip - 1];
 190:         touch(mp);
 191:         if (send(mp, obuf, ignore, NOSTR) < 0) {
 192:             perror(file);
 193:             Fclose(obuf);
 194:             return(1);
 195:         }
 196:         if (mark)
 197:             mp->m_flag |= MSAVED;
 198:     }
 199:     fflush(obuf);
 200:     if (ferror(obuf))
 201:         perror(file);
 202:     Fclose(obuf);
 203:     printf("%s\n", disp);
 204:     return(0);
 205: }
 206: 
 207: /*
 208:  * Write the indicated messages at the end of the passed
 209:  * file name, minus header and trailing blank line.
 210:  */
 211: 
 212: swrite(str)
 213:     char str[];
 214: {
 215: 
 216:     return save1(str, 1, "write", ignoreall);
 217: }
 218: 
 219: /*
 220:  * Snarf the file from the end of the command line and
 221:  * return a pointer to it.  If there is no file attached,
 222:  * just return NOSTR.  Put a null in front of the file
 223:  * name so that the message list processing won't see it,
 224:  * unless the file name is the only thing on the line, in
 225:  * which case, return 0 in the reference flag variable.
 226:  */
 227: 
 228: char *
 229: snarf(linebuf, flag)
 230:     char linebuf[];
 231:     int *flag;
 232: {
 233:     register char *cp;
 234: 
 235:     *flag = 1;
 236:     cp = strlen(linebuf) + linebuf - 1;
 237: 
 238:     /*
 239: 	 * Strip away trailing blanks.
 240: 	 */
 241: 
 242:     while (cp > linebuf && isspace(*cp))
 243:         cp--;
 244:     *++cp = 0;
 245: 
 246:     /*
 247: 	 * Now search for the beginning of the file name.
 248: 	 */
 249: 
 250:     while (cp > linebuf && !isspace(*cp))
 251:         cp--;
 252:     if (*cp == '\0') {
 253:         printf("No file specified.\n");
 254:         return(NOSTR);
 255:     }
 256:     if (isspace(*cp))
 257:         *cp++ = 0;
 258:     else
 259:         *flag = 0;
 260:     return(cp);
 261: }
 262: 
 263: /*
 264:  * Delete messages.
 265:  */
 266: 
 267: delete(msgvec)
 268:     int msgvec[];
 269: {
 270:     delm(msgvec);
 271:     return 0;
 272: }
 273: 
 274: /*
 275:  * Delete messages, then type the new dot.
 276:  */
 277: 
 278: deltype(msgvec)
 279:     int msgvec[];
 280: {
 281:     int list[2];
 282:     int lastdot;
 283: 
 284:     lastdot = dot - &message[0] + 1;
 285:     if (delm(msgvec) >= 0) {
 286:         list[0] = dot - &message[0] + 1;
 287:         if (list[0] > lastdot) {
 288:             touch(dot);
 289:             list[1] = NULL;
 290:             return(type(list));
 291:         }
 292:         printf("At EOF\n");
 293:     } else
 294:         printf("No more messages\n");
 295:     return(0);
 296: }
 297: 
 298: /*
 299:  * Delete the indicated messages.
 300:  * Set dot to some nice place afterwards.
 301:  * Internal interface.
 302:  */
 303: 
 304: delm(msgvec)
 305:     int *msgvec;
 306: {
 307:     register struct message *mp;
 308:     register *ip;
 309:     int last;
 310: 
 311:     last = NULL;
 312:     for (ip = msgvec; *ip != NULL; ip++) {
 313:         mp = &message[*ip - 1];
 314:         touch(mp);
 315:         mp->m_flag |= MDELETED|MTOUCH;
 316:         mp->m_flag &= ~(MPRESERVE|MSAVED|MBOX);
 317:         last = *ip;
 318:     }
 319:     if (last != NULL) {
 320:         dot = &message[last-1];
 321:         last = first(0, MDELETED);
 322:         if (last != NULL) {
 323:             dot = &message[last-1];
 324:             return(0);
 325:         }
 326:         else {
 327:             dot = &message[0];
 328:             return(-1);
 329:         }
 330:     }
 331: 
 332:     /*
 333: 	 * Following can't happen -- it keeps lint happy
 334: 	 */
 335: 
 336:     return(-1);
 337: }
 338: 
 339: /*
 340:  * Undelete the indicated messages.
 341:  */
 342: 
 343: undelete(msgvec)
 344:     int *msgvec;
 345: {
 346:     register struct message *mp;
 347:     register *ip;
 348: 
 349:     for (ip = msgvec; *ip && ip-msgvec < msgCount; ip++) {
 350:         mp = &message[*ip - 1];
 351:         touch(mp);
 352:         dot = mp;
 353:         mp->m_flag &= ~MDELETED;
 354:     }
 355:     return 0;
 356: }
 357: 
 358: /*
 359:  * Interactively dump core on "core"
 360:  */
 361: 
 362: core()
 363: {
 364:     int pid;
 365:     extern union wait wait_status;
 366: 
 367:     switch (pid = vfork()) {
 368:     case -1:
 369:         perror("fork");
 370:         return(1);
 371:     case 0:
 372:         abort();
 373:         _exit(1);
 374:     }
 375:     printf("Okie dokie");
 376:     fflush(stdout);
 377:     wait_child(pid);
 378:     if (wait_status.w_coredump)
 379:         printf(" -- Core dumped.\n");
 380:     else
 381:         printf(" -- Can't dump core.\n");
 382:     return 0;
 383: }
 384: 
 385: /*
 386:  * Clobber as many bytes of stack as the user requests.
 387:  */
 388: clobber(argv)
 389:     char **argv;
 390: {
 391:     register int times;
 392: 
 393:     if (argv[0] == 0)
 394:         times = 1;
 395:     else
 396:         times = (atoi(argv[0]) + 511) / 512;
 397:     clob1(times);
 398:     return 0;
 399: }
 400: 
 401: /*
 402:  * Clobber the stack.
 403:  */
 404: clob1(n)
 405: {
 406:     char buf[512];
 407:     register char *cp;
 408: 
 409:     if (n <= 0)
 410:         return;
 411:     for (cp = buf; cp < &buf[512]; *cp++ = 0xFF)
 412:         ;
 413:     clob1(n - 1);
 414: }
 415: 
 416: /*
 417:  * Add the given header fields to the retained list.
 418:  * If no arguments, print the current list of retained fields.
 419:  */
 420: retfield(list)
 421:     char *list[];
 422: {
 423: 
 424:     return ignore1(list, ignore + 1, "retained");
 425: }
 426: 
 427: /*
 428:  * Add the given header fields to the ignored list.
 429:  * If no arguments, print the current list of ignored fields.
 430:  */
 431: igfield(list)
 432:     char *list[];
 433: {
 434: 
 435:     return ignore1(list, ignore, "ignored");
 436: }
 437: 
 438: saveretfield(list)
 439:     char *list[];
 440: {
 441: 
 442:     return ignore1(list, saveignore + 1, "retained");
 443: }
 444: 
 445: saveigfield(list)
 446:     char *list[];
 447: {
 448: 
 449:     return ignore1(list, saveignore, "ignored");
 450: }
 451: 
 452: ignore1(list, tab, which)
 453:     char *list[];
 454:     struct ignoretab *tab;
 455:     char *which;
 456: {
 457:     char field[BUFSIZ];
 458:     register int h;
 459:     register struct ignore *igp;
 460:     char **ap;
 461: 
 462:     if (*list == NOSTR)
 463:         return igshow(tab, which);
 464:     for (ap = list; *ap != 0; ap++) {
 465:         istrcpy(field, *ap);
 466:         if (member(field, tab))
 467:             continue;
 468:         h = hash(field);
 469:         igp = (struct ignore *) calloc(1, sizeof (struct ignore));
 470:         igp->i_field = calloc((unsigned) strlen(field) + 1,
 471:             sizeof (char));
 472:         strcpy(igp->i_field, field);
 473:         igp->i_link = tab->i_head[h];
 474:         tab->i_head[h] = igp;
 475:         tab->i_count++;
 476:     }
 477:     return 0;
 478: }
 479: 
 480: /*
 481:  * Print out all currently retained fields.
 482:  */
 483: igshow(tab, which)
 484:     struct ignoretab *tab;
 485:     char *which;
 486: {
 487:     register int h;
 488:     struct ignore *igp;
 489:     char **ap, **ring;
 490:     int igcomp();
 491: 
 492:     if (tab->i_count == 0) {
 493:         printf("No fields currently being %s.\n", which);
 494:         return 0;
 495:     }
 496:     ring = (char **) salloc((tab->i_count + 1) * sizeof (char *));
 497:     ap = ring;
 498:     for (h = 0; h < HSHSIZE; h++)
 499:         for (igp = tab->i_head[h]; igp != 0; igp = igp->i_link)
 500:             *ap++ = igp->i_field;
 501:     *ap = 0;
 502:     qsort((char *) ring, tab->i_count, sizeof (char *), igcomp);
 503:     for (ap = ring; *ap != 0; ap++)
 504:         printf("%s\n", *ap);
 505:     return 0;
 506: }
 507: 
 508: /*
 509:  * Compare two names for sorting ignored field list.
 510:  */
 511: igcomp(l, r)
 512:     char **l, **r;
 513: {
 514: 
 515:     return strcmp(*l, *r);
 516: }

Defined functions

clob1 defined in line 404; used 2 times
clobber defined in line 388; used 2 times
copycmd defined in line 141; used 2 times
core defined in line 362; used 3 times
delete defined in line 267; used 2 times
delm defined in line 304; used 2 times
deltype defined in line 278; used 3 times
igcomp defined in line 511; used 2 times
igfield defined in line 431; used 3 times
ignore1 defined in line 452; used 4 times
igshow defined in line 483; used 1 times
next defined in line 53; used 2 times
retfield defined in line 420; used 2 times
save defined in line 131; used 2 times
save1 defined in line 152; used 3 times
saveigfield defined in line 445; used 3 times
saveretfield defined in line 438; used 2 times
snarf defined in line 228; used 2 times
swrite defined in line 212; used 2 times
undelete defined in line 343; used 2 times

Defined variables

sccsid defined in line 35; never used
Last modified: 1992-10-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 3079
Valid CSS Valid XHTML 1.0 Strict