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