# 2.11BSD#431 - /usr/src/ucb/Mail/fio.c

##### Functions

    append            X
    expand            X
    fsize             X
    getdeadletter     X
    getfold           X
    holdsigs          X
    makemessage       X
    putline           X
    readline          X
    relsesigs         X
    rm                X
    setinput          X
    setptr            X

       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[] = "@(#)fio.c	5.24.2 (2.11BSD) 1997/11/3";
      36: #endif
      37:
      38: #include "rcv.h"
      39: #include <sys/stat.h>
      40: #include <sys/file.h>
      41: #include <sys/wait.h>
      42: #include <paths.h>
      43: #include <errno.h>
      44:
      45: /*
      46:  * Mail -- a mail program
      47:  *
      48:  * File I/O.
      49:  */
      50:
      51: /*
      52:  * Set up the input pointers while copying the mail file into /tmp.
      53:  */
      54: setptr(ibuf)
      55:     register FILE *ibuf;
      56: {
      57:     register int c, count;
      58:     register char *cp, *cp2;
      59:     struct message this;
      60:     FILE *mestmp;
      61:     off_t offset;
      62:     int maybe, inhead;
      63:     char linebuf[LINESIZE];
      64:
      65:     /* Get temporary file. */
      66:     (void)sprintf(linebuf, "%smail.XXXXXX", _PATH_TMP);
      67:     if ((c = mkstemp(linebuf)) == -1 ||
      68:         (mestmp = Fdopen(c, "r+")) == NULL) {
      69:         (void)fprintf(stderr, "mail: can't open %s\n", linebuf);
      70:         exit(1);
      71:     }
      72:     (void)unlink(linebuf);
      73:
      74:     msgCount = 0;
      75:     maybe = 1;
      76:     inhead = 0;
      77:     offset = 0;
      78:     this.m_flag = MUSED|MNEW;
      79:     this.m_size = 0;
      80:     this.m_lines = 0;
      81:     this.m_block = 0;
      82:     this.m_offset = 0;
      83:     for (;;) {
      84:         if (fgets(linebuf, LINESIZE, ibuf) == NULL) {
      85:             if (append(&this, mestmp)) {
      86:                 perror("temporary file");
      87:                 exit(1);
      88:             }
      89:             makemessage(mestmp);
      90:             return;
      91:         }
      92:         count = strlen(linebuf);
      93:         (void) fwrite(linebuf, sizeof *linebuf, count, otf);
      94:         if (ferror(otf)) {
      95:             perror("/tmp");
      96:             exit(1);
      97:         }
      98:         linebuf[count - 1] = 0;
      99:         if (maybe && linebuf[0] == 'F' && ishead(linebuf)) {
     100:             msgCount++;
     101:             if (append(&this, mestmp)) {
     102:                 perror("temporary file");
     103:                 exit(1);
     104:             }
     105:             this.m_flag = MUSED|MNEW;
     106:             this.m_size = 0;
     107:             this.m_lines = 0;
     108:             this.m_block = blockof(offset);
     109:             this.m_offset = offstof(offset);
     110:             inhead = 1;
     111:         } else if (linebuf[0] == 0) {
     112:             inhead = 0;
     113:         } else if (inhead) {
     114:             for (cp = linebuf, cp2 = "status";; cp++) {
     115:                 if ((c = *cp2++) == 0) {
     116:                     while (isspace(*cp++))
     117:                         ;
     118:                     if (cp[-1] != ':')
     119:                         break;
     120:                     while (c = *cp++)
     121:                         if (c == 'R')
     122:                             this.m_flag |= MREAD;
     123:                         else if (c == 'O')
     124:                             this.m_flag &= ~MNEW;
     125:                     inhead = 0;
     126:                     break;
     127:                 }
     128:                 if (*cp != c && *cp != toupper(c))
     129:                     break;
     130:             }
     131:         }
     132:         offset += count;
     133:         this.m_size += count;
     134:         this.m_lines++;
     135:         maybe = linebuf[0] == 0;
     136:     }
     137: }
     138:
     139: /*
     140:  * Drop the passed line onto the passed output buffer.
     141:  * If a write error occurs, return -1, else the count of
     142:  * characters written, including the newline.
     143:  */
     144: putline(obuf, linebuf)
     145:     register FILE *obuf;
     146:     char *linebuf;
     147: {
     148:     register int c;
     149:
     150:     c = strlen(linebuf);
     151:     (void) fwrite(linebuf, sizeof *linebuf, c, obuf);
     152:     (void) putc('\n', obuf);
     153:     if (ferror(obuf))
     154:         return (-1);
     155:     return (c + 1);
     156: }
     157:
     158: /*
     159:  * Read up a line from the specified input into the line
     160:  * buffer.  Return the number of characters read.  Do not
     161:  * include the newline at the end.
     162:  */
     163: readline(ibuf, linebuf, linesize)
     164:     FILE *ibuf;
     165:     register char *linebuf;
     166: {
     167:     register int n;
     168:
     169:     clearerr(ibuf);
     170:     if (fgets(linebuf, linesize, ibuf) == NULL)
     171:         return -1;
     172:     n = strlen(linebuf);
     173:     if (n > 0 && linebuf[n - 1] == '\n')
     174:         linebuf[--n] = '\0';
     175:     return n;
     176: }
     177:
     178: /*
     179:  * Return a file buffer all ready to read up the
     180:  * passed message pointer.
     181:  */
     182: FILE *
     183: setinput(mp)
     184:     register struct message *mp;
     185: {
     186:
     187:     fflush(otf);
     188:     if (fseek(itf, positionof(mp->m_block, mp->m_offset), 0) < 0) {
     189:         perror("fseek");
     190:         panic("temporary file seek");
     191:     }
     192:     return (itf);
     193: }
     194:
     195: /*
     196:  * Take the data out of the passed ghost file and toss it into
     197:  * a dynamically allocated message structure.
     198:  */
     199: makemessage(f)
     200:     FILE *f;
     201: {
     202:     register size = (msgCount + 1) * sizeof (struct message);
     203:
     204:     if (message != 0)
     205:         free((char *) message);
     206:     if ((message = (struct message *) malloc((unsigned) size)) == 0)
     207:         panic("Insufficient memory for %d messages", msgCount);
     208:     dot = message;
     209:     size -= sizeof (struct message);
     210:     fflush(f);
     211:     (void) lseek(fileno(f), (long) sizeof *message, 0);
     212:     if (read(fileno(f), (char *) message, size) != size)
     213:         panic("Message temporary file corrupted");
     214:     message[msgCount].m_size = 0;
     215:     message[msgCount].m_lines = 0;
     216:     Fclose(f);
     217: }
     218:
     219: /*
     220:  * Append the passed message descriptor onto the temp file.
     221:  * If the write fails, return 1, else 0
     222:  */
     223: append(mp, f)
     224:     struct message *mp;
     225:     FILE *f;
     226: {
     227:     return fwrite((char *) mp, sizeof *mp, 1, f) != 1;
     228: }
     229:
     230: /*
     231:  * Delete a file, but only if the file is a plain file.
     232:  */
     233: rm(name)
     234:     char *name;
     235: {
     236:     struct stat sb;
     237:
     238:     if (stat(name, &sb) < 0)
     239:         return(-1);
     240:     if (!S_ISREG(sb.st_mode)) {
     241:         errno = EISDIR;
     242:         return(-1);
     243:     }
     244:     return(unlink(name));
     245: }
     246:
     247: static int sigdepth;        /* depth of holdsigs() */
     248: static long omask;
     249: /*
     250:  * Hold signals SIGHUP, SIGINT, and SIGQUIT.
     251:  */
     252: holdsigs()
     253: {
     254:
     255:     if (sigdepth++ == 0)
     256:         omask = sigblock(sigmask(SIGHUP)|sigmask(SIGINT)|sigmask(SIGQUIT));
     257: }
     258:
     259: /*
     260:  * Release signals SIGHUP, SIGINT, and SIGQUIT.
     261:  */
     262: relsesigs()
     263: {
     264:
     265:     if (--sigdepth == 0)
     266:         sigsetmask(omask);
     267: }
     268:
     269: /*
     270:  * Determine the size of the file possessed by
     271:  * the passed buffer.
     272:  */
     273: off_t
     274: fsize(iob)
     275:     FILE *iob;
     276: {
     277:     struct stat sbuf;
     278:
     279:     if (fstat(fileno(iob), &sbuf) < 0)
     280:         return 0;
     281:     return sbuf.st_size;
     282: }
     283:
     284: /*
     285:  * Evaluate the string given as a new mailbox name.
     286:  * Supported meta characters:
     287:  *	%	for my system mail box
     288:  *	%user	for user's system mail box
     289:  *	#	for previous file
     290:  *	&	invoker's mbox file
     291:  *	+file	file in folder directory
     292:  *	any shell meta character
     293:  * Return the file name as a dynamic string.
     294:  */
     295: char *
     296: expand(name)
     297:     register char *name;
     298: {
     299:     char xname[PATHSIZE];
     300:     char cmdbuf[PATHSIZE];      /* also used for file names */
     301:     register int pid, l;
     302:     register char *cp, *shell;
     303:     int pivec[2];
     304:     struct stat sbuf;
     305:     extern union wait wait_status;
     306:
     307:     /*
     308: 	 * The order of evaluation is "%" and "#" expand into constants.
     309: 	 * "&" can expand into "+".  "+" can expand into shell meta characters.
     310: 	 * Shell meta characters expand into constants.
     311: 	 * This way, we make no recursive expansion.
     312: 	 */
     313:     switch (*name) {
     314:     case '%':
     315:         findmail(name[1] ? name + 1 : myname, xname);
     316:         return savestr(xname);
     317:     case '#':
     318:         if (name[1] != 0)
     319:             break;
     320:         if (prevfile[0] == 0) {
     321:             printf("No previous file\n");
     322:             return NOSTR;
     323:         }
     324:         return savestr(prevfile);
     325:     case '&':
     326:         if (name[1] == 0 && (name = value("MBOX")) == NOSTR)
     327:             name = "~/mbox";
     328:         /* fall through */
     329:     }
     330:     if (name[0] == '+' && getfold(cmdbuf) >= 0) {
     331:         sprintf(xname, "%s/%s", cmdbuf, name + 1);
     332:         name = savestr(xname);
     333:     }
     334:     /* catch the most common shell meta character */
     335:     if (name[0] == '~' && (name[1] == '/' || name[1] == '\0')) {
     336:         sprintf(xname, "%s%s", homedir, name + 1);
     337:         name = savestr(xname);
     338:     }
     339:     if (!anyof(name, "~{[*?$`'\"\\"))
     340:         return name;
     341:     if (pipe(pivec) < 0) {
     342:         perror("pipe");
     343:         return name;
     344:     }
     345:     sprintf(cmdbuf, "echo %s", name);
     346:     if ((shell = value("SHELL")) == NOSTR)
     347:         shell = _PATH_CSHELL;
     348:     pid = start_command(shell, 0L, -1, pivec[1], "-c", cmdbuf, NOSTR);
     349:     if (pid < 0) {
     350:         close(pivec[0]);
     351:         close(pivec[1]);
     352:         return NOSTR;
     353:     }
     354:     close(pivec[1]);
     355:     l = read(pivec[0], xname, BUFSIZ);
     356:     close(pivec[0]);
     357:     if (wait_child(pid) < 0 && wait_status.w_termsig != SIGPIPE) {
     358:         fprintf(stderr, "\"%s\": Expansion failed.\n", name);
     359:         return NOSTR;
     360:     }
     361:     if (l < 0) {
     362:         perror("read");
     363:         return NOSTR;
     364:     }
     365:     if (l == 0) {
     366:         fprintf(stderr, "\"%s\": No match.\n", name);
     367:         return NOSTR;
     368:     }
     369:     if (l == BUFSIZ) {
     370:         fprintf(stderr, "\"%s\": Expansion buffer overflow.\n", name);
     371:         return NOSTR;
     372:     }
     373:     xname[l] = 0;
     374:     for (cp = &xname[l-1]; *cp == '\n' && cp > xname; cp--)
     375:         ;
     376:     cp[1] = '\0';
     377:     if (index(xname, ' ') && stat(xname, &sbuf) < 0) {
     378:         fprintf(stderr, "\"%s\": Ambiguous.\n", name);
     379:         return NOSTR;
     380:     }
     381:     return savestr(xname);
     382: }
     383:
     384: /*
     385:  * Determine the current folder directory name.
     386:  */
     387: getfold(name)
     388:     char *name;
     389: {
     390:     register char *folder;
     391:
     392:     if ((folder = value("folder")) == NOSTR)
     393:         return (-1);
     394:     if (*folder == '/')
     395:         strcpy(name, folder);
     396:     else
     397:         sprintf(name, "%s/%s", homedir, folder);
     398:     return (0);
     399: }
     400:
     401: /*
     402:  * Return the name of the dead.letter file.
     403:  */
     404: char *
     405: getdeadletter()
     406: {
     407:     register char *cp;
     408:
     409:     if ((cp = value("DEAD")) == NOSTR || (cp = expand(cp)) == NOSTR)
     410:         cp = expand("~/dead.letter");
     411:     else if (*cp != '/') {
     412:         char buf[PATHSIZE];
     413:
     414:         (void) sprintf(buf, "~/%s", cp);
     415:         cp = expand(buf);
     416:     }
     417:     return cp;
     418: }

#### Defined functions

append defined in line 223; used 2 times

- in line 85, 101

expand defined in line 295; used 16 times

- in line 409-415(3)
- in /usr/src/ucb/Mail/aux.c line 269
- in /usr/src/ucb/Mail/cmd2.c line 176
- in /usr/src/ucb/Mail/cmd3.c line 170, 555
- in /usr/src/ucb/Mail/collect.c line 270, 307
- in /usr/src/ucb/Mail/def.h line 286
- in /usr/src/ucb/Mail/lex.c line 68
- in /usr/src/ucb/Mail/main.c line 212
- in /usr/src/ucb/Mail/names.c line 236
- in /usr/src/ucb/Mail/quit.c line 197
- in /usr/src/ucb/Mail/send.c line 352, 378

fsize defined in line 273; used 7 times

- in /usr/src/ucb/Mail/collect.c line 477, 609
- in /usr/src/ucb/Mail/def.h line 309
- in /usr/src/ucb/Mail/edit.c line 113
- in /usr/src/ucb/Mail/lex.c line 131
- in /usr/src/ucb/Mail/send.c line 310, 370

getdeadletter defined in line 404; used 3 times

- in /usr/src/ucb/Mail/collect.c line 255, 611
- in /usr/src/ucb/Mail/def.h line 287

getfold defined in line 387; used 3 times

- in line 330
- in /usr/src/ucb/Mail/cmd1.c line 432
- in /usr/src/ucb/Mail/lex.c line 592

holdsigs defined in line 252; used 2 times

- in /usr/src/ucb/Mail/lex.c line 108
- in /usr/src/ucb/Mail/quit.c line 393

makemessage defined in line 199; used 1 times

- in line 89

putline defined in line 144; used 3 times

- in /usr/src/ucb/Mail/collect.c line 170, 182, 287

readline defined in line 163; used 10 times

- in /usr/src/ucb/Mail/aux.c line 137, 167, 189, 526, 537
- in /usr/src/ucb/Mail/cmd1.c line 173, 381
- in /usr/src/ucb/Mail/collect.c line 153, 285
- in /usr/src/ucb/Mail/lex.c line 195

relsesigs defined in line 262; used 8 times

- in /usr/src/ucb/Mail/lex.c line 144
- in /usr/src/ucb/Mail/quit.c line 423, 430, 441, 450, 461, 474, 486

rm defined in line 233; used 11 times

- in /usr/src/ucb/Mail/collect.c line 99
- in /usr/src/ucb/Mail/lex.c line 140
- in /usr/src/ucb/Mail/quit.c line 129, 207-212(2), 429, 440-444(2), 479
- in /usr/src/ucb/Mail/send.c line 440
- in /usr/src/ucb/Mail/v7.local.c line 64

setinput defined in line 182; used 7 times

- in /usr/src/ucb/Mail/aux.c line 134, 524
- in /usr/src/ucb/Mail/cmd1.c line 173, 376
- in /usr/src/ucb/Mail/def.h line 280
- in /usr/src/ucb/Mail/edit.c line 107
- in /usr/src/ucb/Mail/send.c line 78

setptr defined in line 54; used 1 times

- in /usr/src/ucb/Mail/lex.c line 141

#### Defined variables

omask defined in line 248; used 2 times

- in line 256, 266

sccsid defined in line 35; never used
sigdepth defined in line 247; used 2 times

- in line 255, 265

Last modified: 1997-11-04 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1124 |