1: #
   2: 
   3: #include "rcv.h"
   4: #include <sys/stat.h>
   5: #include <errno.h>
   6: 
   7: /*
   8:  * Mail -- a mail program
   9:  *
  10:  * File I/O.
  11:  */
  12: 
  13: static char *SccsId = "@(#)fio.c	2.15 6/17/83";
  14: 
  15: /*
  16:  * Set up the input pointers while copying the mail file into
  17:  * /tmp.
  18:  */
  19: 
  20: setptr(ibuf)
  21:     FILE *ibuf;
  22: {
  23:     register int c;
  24:     register char *cp, *cp2;
  25:     register int count, l;
  26:     long s;
  27:     off_t offset;
  28:     char linebuf[LINESIZE];
  29:     char wbuf[LINESIZE];
  30:     int maybe, mestmp, flag, inhead;
  31:     struct message this;
  32:     extern char tempSet[];
  33: 
  34:     if ((mestmp = opentemp(tempSet)) < 0)
  35:         exit(1);
  36:     msgCount = 0;
  37:     offset = 0;
  38:     s = 0L;
  39:     l = 0;
  40:     maybe = 1;
  41:     flag = MUSED|MNEW;
  42:     for (;;) {
  43:         cp = linebuf;
  44:         c = getc(ibuf);
  45:         while (c != EOF && c != '\n') {
  46:             if (cp - linebuf >= LINESIZE - 1) {
  47:                 ungetc(c, ibuf);
  48:                 *cp = 0;
  49:                 break;
  50:             }
  51:             *cp++ = c;
  52:             c = getc(ibuf);
  53:         }
  54:         *cp = 0;
  55:         if (cp == linebuf && c == EOF) {
  56:             this.m_flag = flag;
  57:             flag = MUSED|MNEW;
  58:             this.m_offset = offsetof(offset);
  59:             this.m_block = blockof(offset);
  60:             this.m_size = s;
  61:             this.m_lines = l;
  62:             if (append(&this, mestmp)) {
  63:                 perror(tempSet);
  64:                 exit(1);
  65:             }
  66:             fclose(ibuf);
  67:             makemessage(mestmp);
  68:             close(mestmp);
  69:             return;
  70:         }
  71:         count = cp - linebuf + 1;
  72:         for (cp = linebuf; *cp;)
  73:             putc(*cp++, otf);
  74:         putc('\n', otf);
  75:         if (ferror(otf)) {
  76:             perror("/tmp");
  77:             exit(1);
  78:         }
  79:         if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
  80:             msgCount++;
  81:             this.m_flag = flag;
  82:             flag = MUSED|MNEW;
  83:             inhead = 1;
  84:             this.m_block = blockof(offset);
  85:             this.m_offset = offsetof(offset);
  86:             this.m_size = s;
  87:             this.m_lines = l;
  88:             s = 0L;
  89:             l = 0;
  90:             if (append(&this, mestmp)) {
  91:                 perror(tempSet);
  92:                 exit(1);
  93:             }
  94:         }
  95:         if (linebuf[0] == 0)
  96:             inhead = 0;
  97:         if (inhead && index(linebuf, ':')) {
  98:             cp = linebuf;
  99:             cp2 = wbuf;
 100:             while (isalpha(*cp))
 101:                 *cp2++ = *cp++;
 102:             *cp2 = 0;
 103:             if (icequal(wbuf, "status")) {
 104:                 cp = index(linebuf, ':');
 105:                 if (index(cp, 'R'))
 106:                     flag |= MREAD;
 107:                 if (index(cp, 'O'))
 108:                     flag &= ~MNEW;
 109:                 inhead = 0;
 110:             }
 111:         }
 112:         offset += count;
 113:         s += (long) count;
 114:         l++;
 115:         maybe = 0;
 116:         if (linebuf[0] == 0)
 117:             maybe = 1;
 118:     }
 119: }
 120: 
 121: /*
 122:  * Drop the passed line onto the passed output buffer.
 123:  * If a write error occurs, return -1, else the count of
 124:  * characters written, including the newline.
 125:  */
 126: 
 127: putline(obuf, linebuf)
 128:     FILE *obuf;
 129:     char *linebuf;
 130: {
 131:     register int c;
 132: 
 133:     c = strlen(linebuf);
 134:     fputs(linebuf, obuf);
 135:     putc('\n', obuf);
 136:     if (ferror(obuf))
 137:         return(-1);
 138:     return(c+1);
 139: }
 140: 
 141: /*
 142:  * Quickly read a line from the specified input into the line
 143:  * buffer; return characters read.
 144:  */
 145: 
 146: freadline(ibuf, linebuf)
 147:     register FILE *ibuf;
 148:     register char *linebuf;
 149: {
 150:     register int c;
 151:     register char *cp;
 152: 
 153:     c = getc(ibuf);
 154:     cp = linebuf;
 155:     while (c != '\n' && c != EOF) {
 156:         if (c == 0) {
 157:             c = getc(ibuf);
 158:             continue;
 159:         }
 160:         if (cp - linebuf >= BUFSIZ-1) {
 161:             *cp = 0;
 162:             return(cp - linebuf + 1);
 163:         }
 164:         *cp++ = c;
 165:         c = getc(ibuf);
 166:     }
 167:     if (c == EOF && cp == linebuf)
 168:         return(0);
 169:     *cp = 0;
 170:     return(cp - linebuf + 1);
 171: }
 172: 
 173: /*
 174:  * Read up a line from the specified input into the line
 175:  * buffer.  Return the number of characters read.  Do not
 176:  * include the newline at the end.
 177:  */
 178: 
 179: readline(ibuf, linebuf)
 180:     FILE *ibuf;
 181:     char *linebuf;
 182: {
 183:     register char *cp;
 184:     register int c;
 185: 
 186:     do {
 187:         clearerr(ibuf);
 188:         c = getc(ibuf);
 189:         for (cp = linebuf; c != '\n' && c != EOF; c = getc(ibuf)) {
 190:             if (c == 0)
 191:                 continue;
 192:             if (cp - linebuf < LINESIZE-2)
 193:                 *cp++ = c;
 194:         }
 195:     } while (ferror(ibuf) && ibuf == stdin);
 196:     *cp = 0;
 197:     if (c == EOF && cp == linebuf)
 198:         return(0);
 199:     return(cp - linebuf + 1);
 200: }
 201: 
 202: /*
 203:  * Return a file buffer all ready to read up the
 204:  * passed message pointer.
 205:  */
 206: 
 207: FILE *
 208: setinput(mp)
 209:     register struct message *mp;
 210: {
 211:     off_t off;
 212: 
 213:     fflush(otf);
 214:     off = mp->m_block;
 215:     off <<= 9;
 216:     off += mp->m_offset;
 217:     if (fseek(itf, off, 0) < 0) {
 218:         perror("fseek");
 219:         panic("temporary file seek");
 220:     }
 221:     return(itf);
 222: }
 223: 
 224: /*
 225:  * Take the data out of the passed ghost file and toss it into
 226:  * a dynamically allocated message structure.
 227:  */
 228: 
 229: makemessage(f)
 230: {
 231:     register struct message *m;
 232:     register char *mp;
 233:     register count;
 234: 
 235:     mp = calloc((unsigned) (msgCount + 1), sizeof *m);
 236:     if (mp == NOSTR) {
 237:         printf("Insufficient memory for %d messages\n", msgCount);
 238:         exit(1);
 239:     }
 240:     if (message != (struct message *) 0)
 241:         cfree((char *) message);
 242:     message = (struct message *) mp;
 243:     dot = message;
 244:     lseek(f, 0L, 0);
 245:     while (count = read(f, mp, BUFSIZ))
 246:         mp += count;
 247:     for (m = &message[0]; m < &message[msgCount]; m++) {
 248:         m->m_size = (m+1)->m_size;
 249:         m->m_lines = (m+1)->m_lines;
 250:         m->m_flag = (m+1)->m_flag;
 251:     }
 252:     message[msgCount].m_size = 0L;
 253:     message[msgCount].m_lines = 0;
 254: }
 255: 
 256: /*
 257:  * Append the passed message descriptor onto the temp file.
 258:  * If the write fails, return 1, else 0
 259:  */
 260: 
 261: append(mp, f)
 262:     struct message *mp;
 263: {
 264:     if (write(f, (char *) mp, sizeof *mp) != sizeof *mp)
 265:         return(1);
 266:     return(0);
 267: }
 268: 
 269: /*
 270:  * Delete a file, but only if the file is a plain file.
 271:  */
 272: 
 273: remove(name)
 274:     char name[];
 275: {
 276:     struct stat statb;
 277:     extern int errno;
 278: 
 279:     if (stat(name, &statb) < 0)
 280:         return(-1);
 281:     if ((statb.st_mode & S_IFMT) != S_IFREG) {
 282:         errno = EISDIR;
 283:         return(-1);
 284:     }
 285:     return(unlink(name));
 286: }
 287: 
 288: /*
 289:  * Terminate an editing session by attempting to write out the user's
 290:  * file from the temporary.  Save any new stuff appended to the file.
 291:  */
 292: edstop()
 293: {
 294:     register int gotcha, c;
 295:     register struct message *mp;
 296:     FILE *obuf, *ibuf, *readstat;
 297:     struct stat statb;
 298:     char tempname[30], *id;
 299:     int (*sigs[3])();
 300: 
 301:     if (readonly)
 302:         return;
 303:     holdsigs();
 304:     if (Tflag != NOSTR) {
 305:         if ((readstat = fopen(Tflag, "w")) == NULL)
 306:             Tflag = NOSTR;
 307:     }
 308:     for (mp = &message[0], gotcha = 0; mp < &message[msgCount]; mp++) {
 309:         if (mp->m_flag & MNEW) {
 310:             mp->m_flag &= ~MNEW;
 311:             mp->m_flag |= MSTATUS;
 312:         }
 313:         if (mp->m_flag & (MODIFY|MDELETED|MSTATUS))
 314:             gotcha++;
 315:         if (Tflag != NOSTR && (mp->m_flag & (MREAD|MDELETED)) != 0) {
 316:             if ((id = hfield("article-id", mp)) != NOSTR)
 317:                 fprintf(readstat, "%s\n", id);
 318:         }
 319:     }
 320:     if (Tflag != NOSTR)
 321:         fclose(readstat);
 322:     if (!gotcha || Tflag != NOSTR)
 323:         goto done;
 324:     ibuf = NULL;
 325:     if (stat(editfile, &statb) >= 0 && statb.st_size > mailsize) {
 326:         strcpy(tempname, "/tmp/mboxXXXXXX");
 327:         mktemp(tempname);
 328:         if ((obuf = fopen(tempname, "w")) == NULL) {
 329:             perror(tempname);
 330:             relsesigs();
 331:             reset(0);
 332:         }
 333:         if ((ibuf = fopen(editfile, "r")) == NULL) {
 334:             perror(editfile);
 335:             fclose(obuf);
 336:             remove(tempname);
 337:             relsesigs();
 338:             reset(0);
 339:         }
 340:         fseek(ibuf, mailsize, 0);
 341:         while ((c = getc(ibuf)) != EOF)
 342:             putc(c, obuf);
 343:         fclose(ibuf);
 344:         fclose(obuf);
 345:         if ((ibuf = fopen(tempname, "r")) == NULL) {
 346:             perror(tempname);
 347:             remove(tempname);
 348:             relsesigs();
 349:             reset(0);
 350:         }
 351:         remove(tempname);
 352:     }
 353:     printf("\"%s\" ", editfile);
 354:     flush();
 355:     if ((obuf = fopen(editfile, "w")) == NULL) {
 356:         perror(editfile);
 357:         relsesigs();
 358:         reset(0);
 359:     }
 360:     c = 0;
 361:     for (mp = &message[0]; mp < &message[msgCount]; mp++) {
 362:         if ((mp->m_flag & MDELETED) != 0)
 363:             continue;
 364:         c++;
 365:         if (send(mp, obuf, 0) < 0) {
 366:             perror(editfile);
 367:             relsesigs();
 368:             reset(0);
 369:         }
 370:     }
 371:     gotcha = (c == 0 && ibuf == NULL);
 372:     if (ibuf != NULL) {
 373:         while ((c = getc(ibuf)) != EOF)
 374:             putc(c, obuf);
 375:         fclose(ibuf);
 376:     }
 377:     fflush(obuf);
 378:     if (ferror(obuf)) {
 379:         perror(editfile);
 380:         relsesigs();
 381:         reset(0);
 382:     }
 383:     fclose(obuf);
 384:     if (gotcha) {
 385:         remove(editfile);
 386:         printf("removed\n");
 387:     }
 388:     else
 389:         printf("complete\n");
 390:     flush();
 391: 
 392: done:
 393:     relsesigs();
 394: }
 395: 
 396: static int sigdepth = 0;        /* depth of holdsigs() */
 397: /*
 398:  * Hold signals SIGHUP - SIGQUIT.
 399:  */
 400: holdsigs()
 401: {
 402:     register int i;
 403: 
 404:     if (sigdepth++ == 0)
 405:         for (i = SIGHUP; i <= SIGQUIT; i++)
 406:             sighold(i);
 407: }
 408: 
 409: /*
 410:  * Release signals SIGHUP - SIGQUIT
 411:  */
 412: relsesigs()
 413: {
 414:     register int i;
 415: 
 416:     if (--sigdepth == 0)
 417:         for (i = SIGHUP; i <= SIGQUIT; i++)
 418:             sigrelse(i);
 419: }
 420: 
 421: /*
 422:  * Empty the output buffer.
 423:  */
 424: 
 425: clrbuf(buf)
 426:     register FILE *buf;
 427: {
 428: 
 429:     buf = stdout;
 430:     buf->_ptr = buf->_base;
 431:     buf->_cnt = BUFSIZ;
 432: }
 433: 
 434: /*
 435:  * Open a temp file by creating, closing, unlinking, and
 436:  * reopening.  Return the open file descriptor.
 437:  */
 438: 
 439: opentemp(file)
 440:     char file[];
 441: {
 442:     register int f;
 443: 
 444:     if ((f = creat(file, 0600)) < 0) {
 445:         perror(file);
 446:         return(-1);
 447:     }
 448:     close(f);
 449:     if ((f = open(file, 2)) < 0) {
 450:         perror(file);
 451:         remove(file);
 452:         return(-1);
 453:     }
 454:     remove(file);
 455:     return(f);
 456: }
 457: 
 458: /*
 459:  * Flush the standard output.
 460:  */
 461: 
 462: flush()
 463: {
 464:     fflush(stdout);
 465:     fflush(stderr);
 466: }
 467: 
 468: /*
 469:  * Determine the size of the file possessed by
 470:  * the passed buffer.
 471:  */
 472: 
 473: off_t
 474: fsize(iob)
 475:     FILE *iob;
 476: {
 477:     register int f;
 478:     struct stat sbuf;
 479: 
 480:     f = fileno(iob);
 481:     if (fstat(f, &sbuf) < 0)
 482:         return(0);
 483:     return(sbuf.st_size);
 484: }
 485: 
 486: /*
 487:  * Take a file name, possibly with shell meta characters
 488:  * in it and expand it by using "sh -c echo filename"
 489:  * Return the file name as a dynamic string.
 490:  */
 491: 
 492: char *
 493: expand(name)
 494:     char name[];
 495: {
 496:     char xname[BUFSIZ];
 497:     char cmdbuf[BUFSIZ];
 498:     register int pid, l, rc;
 499:     register char *cp, *Shell;
 500:     int s, pivec[2], (*sigint)();
 501:     struct stat sbuf;
 502: 
 503:     if (name[0] == '+' && getfold(cmdbuf) >= 0) {
 504:         sprintf(xname, "%s/%s", cmdbuf, name + 1);
 505:         return(expand(savestr(xname)));
 506:     }
 507:     if (!anyof(name, "~{[*?$`'\"\\"))
 508:         return(name);
 509:     if (pipe(pivec) < 0) {
 510:         perror("pipe");
 511:         return(name);
 512:     }
 513:     sprintf(cmdbuf, "echo %s", name);
 514:     if ((pid = vfork()) == 0) {
 515:         sigchild();
 516:         Shell = value("SHELL");
 517:         if (Shell == NOSTR)
 518:             Shell = SHELL;
 519:         close(pivec[0]);
 520:         close(1);
 521:         dup(pivec[1]);
 522:         close(pivec[1]);
 523:         close(2);
 524:         execl(Shell, Shell, "-c", cmdbuf, 0);
 525:         _exit(1);
 526:     }
 527:     if (pid == -1) {
 528:         perror("fork");
 529:         close(pivec[0]);
 530:         close(pivec[1]);
 531:         return(NOSTR);
 532:     }
 533:     close(pivec[1]);
 534:     l = read(pivec[0], xname, BUFSIZ);
 535:     close(pivec[0]);
 536:     while (wait(&s) != pid);
 537:         ;
 538:     s &= 0377;
 539:     if (s != 0 && s != SIGPIPE) {
 540:         fprintf(stderr, "\"Echo\" failed\n");
 541:         goto err;
 542:     }
 543:     if (l < 0) {
 544:         perror("read");
 545:         goto err;
 546:     }
 547:     if (l == 0) {
 548:         fprintf(stderr, "\"%s\": No match\n", name);
 549:         goto err;
 550:     }
 551:     if (l == BUFSIZ) {
 552:         fprintf(stderr, "Buffer overflow expanding \"%s\"\n", name);
 553:         goto err;
 554:     }
 555:     xname[l] = 0;
 556:     for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
 557:         ;
 558:     *++cp = '\0';
 559:     if (any(' ', xname) && stat(xname, &sbuf) < 0) {
 560:         fprintf(stderr, "\"%s\": Ambiguous\n", name);
 561:         goto err;
 562:     }
 563:     return(savestr(xname));
 564: 
 565: err:
 566:     return(NOSTR);
 567: }
 568: 
 569: /*
 570:  * Determine the current folder directory name.
 571:  */
 572: getfold(name)
 573:     char *name;
 574: {
 575:     char *folder;
 576: 
 577:     if ((folder = value("folder")) == NOSTR)
 578:         return(-1);
 579:     if (*folder == '/')
 580:         strcpy(name, folder);
 581:     else
 582:         sprintf(name, "%s/%s", homedir, folder);
 583:     return(0);
 584: }
 585: 
 586: /*
 587:  * A nicer version of Fdopen, which allows us to fclose
 588:  * without losing the open file.
 589:  */
 590: 
 591: FILE *
 592: Fdopen(fildes, mode)
 593:     char *mode;
 594: {
 595:     register int f;
 596:     FILE *fdopen();
 597: 
 598:     f = dup(fildes);
 599:     if (f < 0) {
 600:         perror("dup");
 601:         return(NULL);
 602:     }
 603:     return(fdopen(f, mode));
 604: }

Defined functions

Fdopen defined in line 591; used 2 times
append defined in line 261; used 2 times
edstop defined in line 292; used 9 times
flush defined in line 462; used 9 times
freadline defined in line 146; never used
getfold defined in line 572; used 3 times
holdsigs defined in line 400; used 3 times
makemessage defined in line 229; used 1 times
  • in line 67
opentemp defined in line 439; used 1 times
  • in line 34
putline defined in line 127; used 3 times
relsesigs defined in line 412; used 8 times
setptr defined in line 20; used 1 times

Defined variables

SccsId defined in line 13; never used
sigdepth defined in line 396; used 2 times
Last modified: 1983-07-08
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1459
Valid CSS Valid XHTML 1.0 Strict