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

Defined functions

Fdopen defined in line 519; used 2 times
append defined in line 212; used 2 times
edstop defined in line 243; used 9 times
getfold defined in line 500; used 3 times
holdsigs defined in line 353; used 3 times
makemessage defined in line 180; used 1 times
  • in line 61
opentemp defined in line 377; used 1 times
  • in line 40
putline defined in line 118; used 3 times
relsesigs defined in line 364; used 8 times
setptr defined in line 26; used 1 times

Defined variables

omask defined in line 349; used 2 times
sccsid defined in line 8; never used
sigdepth defined in line 348; used 2 times
Last modified: 1985-09-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1899
Valid CSS Valid XHTML 1.0 Strict