sources-request@mirror.UUCP (11/06/86)
Submitted by: seismo!rick (Rick Adams) Mod.sources: Volume 7, Issue 51 Archive-name: 2.11news/Part11 [ Again, notice the different between the Part# in the Subject line and the Part# in the Archive-name. --r$ ] # To extract, sh this file # # news 2.11 source part 1 of 9 # if test ! -d src then mkdir src fi echo x - src/visual.c 1>&2 sed 's/.//' >src/visual.c <<'*-*-END-of-src/visual.c-*-*' -/* - * visual - visual news interface. - * Kenneth Almquist - */ - -#ifdef SCCSID -static char *SccsId = "@(#)visual.c 1.32 10/23/86"; -#endif /* SCCSID */ - -#include "rparams.h" -#ifdef USG -#include <sys/ioctl.h> -#include <termio.h> -#include <fcntl.h> -#else /* !USG */ -#include <sgtty.h> -#endif /* !USG */ - -#include <errno.h> -#if defined(BSD4_2) || defined(BSD4_1C) -#include <sys/dir.h> -#else -#include "ndir.h" -#endif -#ifdef BSD4_2 -#ifndef sigmask -#define sigmask(m) (1<<((m)-1)) -#endif /* !sigmask */ -#endif /* BSD4_2 */ -#ifdef MYDB -#include "db.h" -#endif /* MYDB */ - -extern int errno; - -#ifdef SIGTSTP -#include <setjmp.h> -#endif /* SIGTSTP */ - -#define ARTWLEN (ROWS-2)/* number of lines used to display article */ -#define even(cols) ((cols&1) ? cols + 1 : cols) -#ifdef STATTOP -#define PRLINE 0 /* prompter line */ -#define SPLINE 1 /* secondary prompt line */ -#define ARTWIN 2 /* first line of article window */ -#define SECPRLEN 81 /* length of secondary prompter */ -#else -#define PRLINE (ROWS-1)/* prompter line */ -#define SPLINE (ROWS-2)/* secondary prompt line */ -#define ARTWIN 0 /* first line of article window */ -#define SECPRLEN 100 /* length of secondary prompter */ -#endif - -#define PIPECHAR '|' /* indicate save command should pipe to program */ -#define META 0200 /* meta character bit (as in emacs) */ -/* print (display) flags */ -#define HDRONLY 0001 /* print header only */ -#define NOPRT 0002 /* don't print at all */ -#define NEWART 0004 /* force article display to be regenerated */ -#define HELPMSG 0010 /* display currently contains help message */ -/* prun flags */ -#define CWAIT 0001 /* type "continue?" and wait for return */ -#define BKGRND 0002 /* run process in the background */ -/* values of curflag */ -#define CURP1 1 /* cursor after prompt */ -#define CURP2 2 /* cursor after secondary prompt */ -#define CURHOME 3 /* cursor at home position */ -/* flags for vsave routine */ -#define SVHEAD 01 /* write out article header */ -#define OVWRITE 02 /* overwrite the file if it already exists */ -/* other files */ - -#define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize -#define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines)) - -/* terminal handler stuff */ -extern int _junked; -#define clearok(xxx, flag) _junked = flag -extern int COLS; -extern int ROWS; -extern int hasscroll; - -FILE *tmpfile(); -char *getmailname(); -#ifdef MYDB -char *findparent(); -#endif /* MYDB */ -int onint(); -int onstop(); -int xxit(); - -char *Progname = "vnews"; /* for xerror */ - -/* variables shared between vnews routines */ -static char linebuf[LBUFLEN]; /* temporary workspace */ -static FILE *tfp; /* temporary file */ -static char tfname[] = "/tmp/vnXXXXXX"; /* name of temp file */ -static long artbody; /* offset of body into article */ -static int quitflg; /* if set, then quit */ -static int erased; /* current article has been erased */ -static int artlines; /* # lines in article body */ -static int artread; /* entire article has been read */ -static int hdrstart; /* beginning of header */ -static int hdrend; /* end of header */ -static int lastlin; /* number of lines in tempfile */ -static int tflinno = 0; /* next line in tempfile */ -static int maxlinno; /* number of lines in file + folded */ -static char secpr[SECPRLEN]; /* secondary prompt */ -static char prompt[30]; /* prompter */ -static short prflags; /* print flags (controls updscr) */ -static short curflag; /* where to locate cursor */ -static int dlinno; /* top line on screen */ -static char timestr[20]; /* current time */ -static int ismail; /* true if user has mail */ -static char *mailf; /* user's mail file */ -static int alflag; /* set if unprocessed alarm signal */ -static int atend; /* set if at end of article */ -static char cerase; /* erase character */ -static char ckill; /* kill character */ -static char cintr; /* interrupt character */ -#ifdef TIOCGLTC -static char cwerase; /* word erase character */ -#endif /* TIOCGLTC */ -short ospeed; /* terminal speed NOT STATIC */ -static int intflag; /* set if interrupt received */ - -#ifdef SIGTSTP -static int reading; /* to keep stupid BSD from restarting reads */ -jmp_buf intjmp, alrmjmp; -#endif /* SIGTSTP */ - -#ifdef MYDB -static int hasdb; /* true if article data base exists */ -#endif /* MYDB */ - -#ifdef DIGPAGE -static int endsuba; /* end of sub-article in digest */ -#endif - -#ifdef MYDEBUG -FILE *debugf; /* file to write debugging info on */ -#endif - -char *tft = "/tmp/folXXXXXX"; - -/* - * These were made static for u370 with its buggy cc. - * I judged it better to have one copy with no ifdefs than - * to conditionally compile them as automatic variables - * in readr (which they originally were). Performance - * considerations might warrant moving some of the simple - * things into register variables, but I don't know what - * breaks the u370 cc. - */ -static char goodone[BUFLEN]; /* last decent article */ -static char ogroupdir[BUFLEN]; /* last groupdir */ -static char edcmdbuf[128]; -static int rfq = 0; /* for last article */ -static long ongsize; /* Previous ngsize */ -static long pngsize; /* Printing ngsize */ -static char *bptr; /* temp pointer. */ -static char *tfilename; /* temporary file name */ -static char ofilename1[BUFLEN]; /* previous file name */ -static struct hbuf hbuf1, hbuf2; /* for minusing */ -static struct hbuf *h = &hbuf1, /* current header */ - *hold = &hbuf2, /* previous header */ - *hptr; /* temporary */ -static char *ptr1, *ptr2, *ptr3; /* for reply manipulation */ -static int aabs = FALSE; /* TRUE if we asked absolutely */ -static char *ed, tf[100]; -static long oobit; /* last bit, really */ -static int dgest = 0; -static FILE *fp; /* current article to be printed*/ - -readr() -{ - -#ifdef MYDEBUG - debugf = fopen("DEBUG", "w"); - setbuf(debugf, (char *)NULL); -#endif - if (aflag) { - if (*datebuf) { - if ((atime = cgtdate(datebuf)) == -1) - xerror("Cannot parse date string"); - } else - atime = 0; - } - - if (SigTrap) - xxit(1); - (void) mktemp(tfname); - (void) close(creat(tfname,0666)); - if ((tfp = fopen(tfname, "w+")) == NULL) - xerror("Can't create temp file"); - (void) unlink(tfname); - mailf = getmailname(); -#ifdef MYDB - if (opendb() >= 0) { - hasdb = 1; - fputs("Using article data base\n", stderr); /*DEBUG*/ - getng(); - } -#endif - ttysave(); - (void) signal(SIGINT, onint); - (void) signal(SIGQUIT, xxit); - if (SigTrap) - xxit(1); - ttyraw(); - timer(); - - /* loop reading articles. */ - fp = NULL; - obit = -1; - nextng(); - quitflg = 0; - while (quitflg == 0) { - if (getnextart(FALSE)) - break; - (void) strcpy(goodone, filename); - if (SigTrap) - return; - vcmd(); - } - - if (!news) { - fprintf(stderr, "No news.\n"); - } -} - -/* - * Read and execute a command. - */ -vcmd() { - register c; - char *p; - long count; - int countset; - - if (prflags & HDRONLY) - appfile(fp, lastlin + 1); - else - appfile(fp, dlinno + ARTWLEN + 1); - -#ifdef DIGPAGE - endsuba = findend(dlinno); - if (artlines > dlinno + ARTWLEN - || endsuba > 0 && endsuba < artlines -#else - if (artlines > dlinno + ARTWLEN -#endif - || (prflags & HDRONLY) && artlines > hdrend) { - atend = 0; - if (prflags&HDRONLY || maxlinno == 0) - (void) strcpy(prompt, "more? "); - else -#ifdef DIGPAGE - (void) sprintf(prompt, "more(%d%%)? ", - ((((endsuba > 0) ? - endsuba : (dlinno + ARTWLEN)) - - hdrend) * 100) / maxlinno); -#else /* !DIGPAGE */ - (void) sprintf(prompt, "more(%d%%)? ", - ((dlinno + ARTWLEN - hdrend) * 100) / maxlinno); -#endif /* !DIGPAGE */ - } else { - atend = 1; - (void) strcpy(prompt, "next? "); - if (!erased) - clear(bit); /* article read */ - } - curflag = CURP1; - p = prompt + strlen(prompt); - countset = 0; - count = 0; - /* - * Loop while accumulating a count, until an action character - * is entered. Also handle "meta" here. - * - * Count is the current count. Countset=0 means no count - * currently exists. Countset=1, count=0 is valid and means - * a count of 0 has been entered - */ - for (;;) { - c = vgetc(); - if (c == cerase || c == '\b' || c == '\177') { - if (countset == 0) - break; /* Use as action char */ - if (count < 10) - countset = 0; /* Erase only char of count */ - else - count /= 10L; /* Erase 1 char of count */ - } else { -#ifdef TIOCGLTC - if (c == ckill || c == cwerase) { -#else - if (c == ckill) { -#endif - if (countset == 0) - break; - countset = 0; - } else if (c < '0' || c > '9') - break; - else { - countset = 1; - count = (count * 10) + (c - '0'); - } - } - if (countset) { - (void) sprintf(p, "%ld", count); - } else { - *p = '\0'; - count = 0; - } - } - - if (c == '\033') { /* escape */ - (void) strcat(prompt, "M-"); - c = vgetc(); - if (c != cintr) - c |= META; - } - secpr[0] = '\0'; - if (countset == 0) - count = 1; - docmd(c, count); - if (c != '?' && c != 'H') /* UGGH */ - prflags &=~ HELPMSG; - if (dlinno > hdrstart) - prflags &=~ HDRONLY; -} - - -/* - * Process one command, which has already been typed in. - */ -docmd(c, count) -int c; -long count; -{ - int i; - long nart, Hoffset; - char *findhist(); - - switch (c) { - - /* Show more of current article, or advance to next article */ - case '\n': - case ' ': -#ifdef DIGPAGE - case 'm': -#endif /* DIGPAGE */ - case '\06': /* Control-F for vi compat */ - prflags &=~ NOPRT; - if (atend) - goto next; - else if (prflags & HDRONLY) { - prflags &=~ HDRONLY; - if (hasscroll) - dlinno = hdrstart;} -#ifdef DIGPAGE - else if (endsuba > 0) - dlinno = endsuba; - else if (c == 'm') { - do { - if (lastlin >= maxlinno) - goto next; - else - appfile(fp, lastlin + 1); - } while(strncmp(linebuf, "------------------------", 24) - != 0); - dlinno = endsuba = lastlin; - } -#endif - else if ((appfile(fp, dlinno + 2 * ARTWLEN), artread) - && hasscroll && artlines - dlinno <= ARTWLEN + 2) - dlinno = artlines - ARTWLEN; - else - dlinno += ARTWLEN * count; - break; - - /* No. Go on to next article. */ - case '.': /* useful if you have a keypad */ -next: case 'n': - readmode = NEXT; - FCLOSE(fp); - clear(bit); - saveart; - nextbit(); - break; - - - /* Back up count pages */ - case '\b': - case '\177': - if (dlinno == 0) - goto backupone; - /* NO BREAK */ - case META|'v': - case '\002': /* Control-B */ - dlinno -= ARTWLEN * count; - if (dlinno < 0) - dlinno = 0; - break; - - /* forward half a page */ - case '\004': /* Control-D, as in vi */ - if (!atend) - dlinno += ARTWLEN/2 * count; - break; - - /* backward half a page */ - case '\025': /* Control-U */ - dlinno -= ARTWLEN/2 * count; - if (dlinno < 0) - dlinno = 0; - break; - - /* forward count lines */ - case '\016': /* Control-N */ - case '\005': /* Control-E */ - dlinno += count; - break; - - /* backwards count lines */ - case '\020': /* Control-P */ - case '\031': /* Control-Y */ - dlinno -= count; - if (dlinno < 0) - dlinno = 0; - break; - - /* Turn displaying of article back on */ - case 'l': - case 'd': - prflags &=~ NOPRT; - break; - - /* display header */ - case 'h': - dlinno = hdrstart; - prflags |= HDRONLY; - prflags &=~ NOPRT; - break; - - /* - * Unsubscribe to the newsgroup and go on to next group - */ - - case 'U': - case 'u': - strcat(prompt, "u"); - c = vgetc(); - if (c == 'g') { - obit = -1; - FCLOSE(fp); - zapng = TRUE; - saveart; - if (nextng()) { - if (actdirect == BACKWARD) - msg("Can't back up."); - else - quitflg = 1; /* probably unnecessary */ - } - } else { - if (c != cintr && c != ckill) - beep(); - msg("Illegal command"); - } - break; - - /* Print the current version of news */ - case 'v': - msg("News version: %s", news_version); - break; - - - /* Decrypt joke. Always does rot 13 */ - case 'D': - appfile(fp, 32767); - for (i = hdrend ; i < artlines ; i++) { - register char ch, *p; - tfget(linebuf, i); - for (p = linebuf ; (ch = *p) != '\0' ; p++) { - if (ch >= 'a' && ch <= 'z') - *p = (ch - 'a' + 13) % 26 + 'a'; - else if (ch >= 'A' && ch <= 'Z') - *p = (ch - 'A' + 13) % 26 + 'A'; - } - tfput(linebuf, i); - } - prflags |= NEWART; - prflags &=~ (HDRONLY|NOPRT); - break; - - /* write out the article someplace */ - /* w writes out without the header */ - case 's': - case 'w': { - char *grn = groupdir; - int wflags; - - msg("file: "); - curflag = CURP2; - while ((wflags = vgetc()) == ' '); - if (wflags == cintr) { - secpr[0] = '\0'; - break; - } - if (wflags == '|') { - linebuf[0] = '|'; - if (prget("| ", linebuf+1)) - break; - } else { - pushback(wflags); - if (prget("file: ", linebuf)) - break; - } - wflags = 0; - if (c == 's') - wflags |= SVHEAD; - if (count != 1) - wflags |= OVWRITE; - bptr = linebuf; - while( *bptr == ' ') - bptr++; /* strip leading spaces */ - - if (*bptr != PIPECHAR && *bptr != '/') { - char hetyped[BUFLEN]; - char *boxptr; - (void) strcpy(hetyped, bptr); - if (hetyped[0] == '~' && hetyped[1] == '/') { - strcpy(hetyped, bptr+2); - strcpy(bptr, userhome); - } else if (boxptr = getenv("NEWSBOX")) { - if (index(boxptr, '%')) { - struct stat stbf; - sprintf(bptr, boxptr, grn); - if (stat(bptr,&stbf) < 0) { - if (mkdir(bptr, 0777) < 0) { - msg("Cannot create directory %s", bptr); - break; - } - } else if ((stbf.st_mode&S_IFMT) != S_IFDIR) { - msg("%s not a directory", bptr); - break; - } - } else - strcpy(bptr, boxptr); - } else - bptr[0] = '\0'; - - if (bptr[0]) - (void) strcat(bptr, "/"); - if (hetyped[0] != '\0') - (void) strcat(bptr, hetyped); - else - (void) strcat(bptr, "Articles"); - } - vsave(bptr, wflags); - break; - } - - /* back up */ - case '-': -caseminus: - aabs = TRUE; - if (!*ofilename1) { - msg("Can't back up."); - break; - } - FCLOSE(fp); - hptr = h; - h = hold; - hold = hptr; - (void) strcpy(bfr, filename); - (void) strcpy(filename, ofilename1); - (void) strcpy(ofilename1, bfr); - obit = bit; - if (strcmp(groupdir, ogroupdir)) { - (void) strcpy(bfr, groupdir); - selectng(ogroupdir, FALSE, FALSE); - (void) strcpy(groupdir, ogroupdir); - (void) strcpy(ogroupdir, bfr); - ngrp = 1; - back(); - } - bit = oobit; - oobit = obit; - obit = -1; - getnextart(TRUE); - break; - - /* skip forwards */ - case '+': - case '=': -caseplus: if (count == 0) - break; - saveart; - last = bit; - for (i = 0; i < count; i++) { - nextbit(); - if ((bit > pngsize) || (rflag && bit < 1)) - break; - } - FCLOSE(fp); - obit = -1; - break; - - /* exit - time updated to that of most recently read article */ - case 'q': - quitflg = 1; - break; - - case 'x': - xxit(0); - break; - - /* cancel the article. */ - case 'c': - strcpy(prompt, "cancel [n]? "); - if (vgetc() != 'y') { - msg("Article not cancelled"); - break; - } - cancel_command(); - break; - - /* escape to shell */ - case '!': { - register char *p; - int flags; - - p = linebuf; - if (prget("!", p)) - break; - flags = CWAIT; - if (*p == '\0') { - (void) strcpy(linebuf, SHELL); - flags = 0; - } - while (*p) p++; - while (p > linebuf && p[-1] == ' ') - p--; - if (*--p == '&') { - *p = '\0'; - flags = BKGRND; - } else if (*p == '|') { - *p = '\0'; - (void) sprintf(bfr, "(%s)|mail '%s'", linebuf, username); - (void) strcpy(linebuf, bfr); - flags |= BKGRND; - } else { - prflags |= NOPRT; - } - shcmd(linebuf, flags); - break; - } - - /* mail reply */ - case 'r': - reply(FALSE); - break; - - case 'R': - reply(TRUE); - break; - - case META|'r': - direct_reply(); - break; - - /* next newsgroup */ - case 'N': - FCLOSE(fp); - if (next_ng_command()) - quitflg = 1; - break; - - /* mark the rest of the articles in this group as read */ - case 'K': - saveart; - while (bit <= ngsize && bit >= minartno) { - clear(bit); - nextbit(); - } - FCLOSE(fp); - break; - - /* Print the full header */ - case 'H': - if (fp == NULL) { - msg("No current article"); - break; - } - move(ARTWIN, 0); - Hoffset = ftell(fp); - (void) fseek(fp, 0L, 0); - for (i = 0; i < ARTWLEN; i++) { - if (fgets(linebuf, COLS, fp) == NULL) - break; - if (linebuf[0] == '\n') - break; - linebuf[COLS] = '\0'; - addstr(linebuf); - } - (void) fseek(fp, Hoffset, 0); - for(; i < ARTWLEN; i++) - addstr(linebuf); - prflags |= HELPMSG|NEWART; - break; - case 'b': /* backup 1 article */ -backupone: - count = bit - 1; - /* NO BREAK */ - - case 'A': /* specific number */ - if (count > pngsize) { - msg("not that many articles"); - break; - } - readmode = SPEC; - aabs = TRUE; - bit = count; - obit = -1; - FCLOSE(fp); - break; - - /* display parent article */ - case 'p': -#ifdef MYDB - if (hasdb && (ptr3 = findparent(h->ident, &nart)) != NULL) { - msg("parent: %s/%ld", ptr3, nart); /*DEBUG*/ - updscr(); /*DEBUG*/ - goto selectart; - } -#endif - if (h->followid[0] == '\0') { - msg("no references line"); - break; - } - ptr1 = h->followid + strlen(h->followid); - do { - ptr2 = ptr1; - if (*ptr2 == '\0') - ptr1 = rindex(h->followid, ' '); - else { - *ptr2 = '\0'; - ptr1 = rindex(h->followid, ' '); - *ptr2 = ' '; - } - } while (ptr1 != NULL && --count > 0); - if (ptr1 == NULL) - ptr1 = h->followid; - else ++ptr1; - (void) strncpy(linebuf, ptr1, ptr2 - ptr1); - linebuf[ptr2 - ptr1] = '\0'; - msg("%s", linebuf); - curflag = CURP2; - updscr(); /* may take this out later */ - goto searchid; - /* specific message ID. */ - case '<': - /* could improve this */ - linebuf[0] = '<'; - if (prget("<", linebuf+1)) - break; -searchid: secpr[0] = '\0'; - if (index(linebuf, '@') == NULL && index(linebuf, '>') == NULL) { - ptr1 = linebuf; - if (*ptr1 == '<') - ptr1++; - ptr2 = index(ptr1, '.'); - if (ptr2 != NULL) { - *ptr2++ = '\0'; - (void) sprintf(bfr, "<%s@%s.UUCP>", ptr2, ptr1); - (void) strcpy(linebuf, bfr); - } - } - if (index(linebuf, '>') == NULL) - (void) strcat(linebuf, ">"); - - ptr1 = findhist(linebuf); - if (ptr1 == NULL) { - msg("%s not found", linebuf); - break; - } - ptr2 = index(ptr1, '\t'); - ptr3 = index(++ptr2, '\t'); - ptr2 = index(++ptr3, ' '); - if (ptr2) - *ptr2 = '\0'; - ptr2 = index(ptr3, '/'); - if (!ptr2) { - if (strcmp(++ptr3, "cancelled") == 0) - msg("%s has been cancelled", linebuf); - else - msg("%s has expired", linebuf); - break; - } - *ptr2++ = '\0'; - (void) sscanf(ptr2, "%ld", &nart); - - /* - * Go to a given article. Ptr3 specifies the newsgroup - * and nart specifies the article number. - */ -#ifdef MYDB -selectart: -#endif /* MYDB */ - aabs = TRUE; - FCLOSE(fp); - saveart; - (void) strcpy(ogroupdir, ptr3); - if (strcmp(groupdir, ogroupdir)) { - (void) strcpy(bfr, groupdir); - selectng(ogroupdir, TRUE, PERHAPS); - (void) strcpy(groupdir, ogroupdir); - (void) strcpy(ogroupdir, bfr); - ngrp = 1; - back(); - } - bit = nart; - oobit = obit; - obit = -1; - getnextart(TRUE); - if (bit != nart || strcmp(groupdir, ptr3) != 0) { - msg("can't read %s/%ld", ptr3, nart); - goto caseminus; - } - rfq = 0; - break; - - /* follow-up article */ - case 'f': - if (strcmp(h->followto, "poster") == 0) { - reply(FALSE); - break; - } - (void) sprintf(bfr, "%s/%s %s", BIN, "postnews", goodone); - shcmd(bfr, CWAIT); - break; - - /* erase - pretend we haven't seen this article. */ - case 'e': - erased = 1; - set(bit); - goto caseplus; /* skip this article for now */ - - case '#': - msg("Article %ld of %ld", rfq ? oobit : bit, pngsize); - break; - - /* error */ - case '?': - { - FILE *helpf; - (void) sprintf(linebuf, "%s/vnews.help", LIB); - if ((helpf = fopen(linebuf, "r")) == NULL) { - msg("Can't open help file"); - break; - } - move(ARTWIN, 0); - while (fgets(linebuf, LBUFLEN, helpf) != NULL) - addstr(linebuf); - (void) fclose(helpf); - prflags |= HELPMSG|NEWART; - } - break; - - default: - if (c != ckill && c != cintr && c != cerase) -#ifdef TIOCGLTC - if (c != cwerase) -#endif - { - beep(); - msg("Illegal command"); - } - break; - } -} - -cancel_command() -{ - int notauthor; - - tfilename = filename; - (void) strcpy(rcbuf, h->path); - ptr1 = index(rcbuf, ' '); - if (ptr1) - *ptr1 = 0; - notauthor = strcmp(username, rcbuf); - if (uid != ROOTID && uid && notauthor) { - msg("Can't cancel what you didn't write."); - return; - } - if (!cancel(stderr, h, notauthor)) { - clear(bit); - saveart; - nextbit(); - obit = -1; - fp = NULL; - } - FCLOSE(fp); -} -/* - * Generate replies - */ - -reply(include) - int include; -{ - char *arg[4]; - register FILE *rfp; - char subj[132]; - register char *p; - char *replyname(); - struct stat statb; - time_t creatm; - - /* Put the user in the editor to create the body of the reply. */ - ed = getenv("EDITOR"); - if (ed == NULL || *ed == '\0') - ed = DFTEDITOR; - if (ed == NULL) { - msg("You don't have an editor"); - return; - } - - arg[0] = "/bin/sh"; - arg[1] = "-c"; - - (void) strcpy(tf, tft); - (void) mktemp(tf); - (void) close(creat(tf,0600)); - if ((rfp = fopen(tf, "w")) == NULL) { - msg("Can't create %s", tf) ; - return; - } - (void) strcpy(subj, h->title); - if (!prefix(subj, "Re:")){ - (void) strcpy(bfr, subj); - (void) sprintf(subj, "Re: %s", bfr); - } - - p = replyname(h); - fprintf(rfp, "To: %s\n", p); - fprintf(rfp, "Subject: %s\n", subj); - fprintf(rfp, "In-reply-to: your article %s\n", h->ident); -#ifdef INTERNET - fprintf(rfp, "News-Path: %s\n", h->path); -#endif /* INTERNET */ - (void) sprintf(rcbuf, "%s -t < %s; rm -f %s", MAILPARSER, tf, tf); - putc('\n', rfp); - if (include) { - FILE *of; - char buf[BUFSIZ]; - - of = xart_open(goodone, "r"); - while (fgets(buf, sizeof buf, of) != NULL) - if (buf[0] == '\n') - break; - while (fgets(buf, sizeof buf, of) != NULL) - fprintf(rfp, "> %s", buf); - fclose(of); - putc('\n', rfp); - } - fflush(rfp); - (void) fstat(fileno(rfp), &statb); - creatm = statb.st_mtime; - (void) fclose(rfp); - - (void) sprintf(edcmdbuf, "exec %s %s", ed, tf); - arg[2] = edcmdbuf; - arg[3] = NULL; - if (prun(arg, 0) != 0) { - msg("Couldn't run editor"); - (void) unlink(tf); - return; - } - - if (access(tf, 4) || stat(tf, &statb)) { - msg("No input file - mail not sent"); - (void) unlink(tf); - return; - } - if (statb.st_mtime == creatm || statb.st_size < 5) { - msg("File unchanged - no message posted"); - (void) unlink(tf); - return; - } - - arg[2] = rcbuf; - arg[3] = NULL; - prun(arg, BKGRND); - prflags |= NOPRT; -} - -direct_reply() -{ - register char *p; - register char *q; - char *arg[4]; - char address[PATHLEN]; - extern char *replyname(); - extern char *getenv(); - - arg[0] = "/bin/sh"; - arg[1] = "-c"; - p = replyname(h); - q = address; - while (*p != '\0') { - if (index("\"\\$", *p) != 0) - *q++ = '\\'; - *q++ = *p++; - } - *q++ = '\0'; - if ((MAILER = getenv("MAILER")) == NULL) - MAILER = "mail"; - sprintf(rcbuf, MAILER, hptr->title); - sprintf(bfr, "%s %s", rcbuf, address); - arg[2] = bfr; - arg[3] = NULL; - if (prun(arg, 0) != 0) { - msg("Couldn't run mailer"); - return; - } - prflags |= NOPRT; -} - -next_ng_command() -{ - obit = -1; - if (prget("group? ", linebuf)) - return FALSE; - bptr = linebuf; - if (!*bptr || *bptr == '-') { - if (*bptr) - actdirect = BACKWARD; - saveart; - if (nextng()) { - if (actdirect == BACKWARD) - msg("Can't back up."); - else - return TRUE; - } - return FALSE; - } - while (isspace(*bptr)) - bptr++; - if (!validng(bptr)) { - msg("No such group."); - return FALSE; - } - saveart; - back(); - selectng(bptr, TRUE, TRUE); - return FALSE; -} - -/* - * Find the next article we want to consider, if we're done with - * the last one, and show the header. - */ -getnextart(minus) -int minus; -{ - int noaccess; - register DIR *dirp; - register struct direct *dir; - long nextnum, tnum; - long atol(); - - noaccess = 0; - if (minus) - goto nextart2; /* Kludge for "-" command. */ - - if (bit == obit) /* Return if still on same article as last time */ - return 0; - -nextart: - if (news) { - curflag = CURHOME; - _amove(0, 0); - vflush(); - } - dgest = 0; - - /* If done with this newsgroup, find the next one. */ - while (ngsize <= 0 || (!rflag && ((long) bit > ngsize)) || (rflag && bit < minartno)) { - if (nextng()) { - if (actdirect == BACKWARD) { - msg("Can't back up."); - actdirect = FORWARD; - continue; - } - else /* if (rfq++ || pflag || cflag) */ - return 1; - } - if (rflag) - bit = ngsize + 1; - else - bit = -1; - noaccess = 2; - } - - /* speed things up by not searching for article -1 */ - if (bit < 0) { - bit = minartno - 1; - nextbit(); - aabs = FALSE; - goto nextart; - } - -nextart2: - if (rcreadok) - rcreadok = 2; /* have seen >= 1 article */ - (void) sprintf(filename, "%s/%ld", dirname(groupdir), bit); - if (rfq && goodone[0]) /* ??? */ - strcpy(filename, goodone); - if (SigTrap == SIGHUP) - return 1; - /* Decide if we want to show this article. */ - if ((fp = art_open(filename, "r")) == NULL) { - /* since there can be holes in legal article numbers, */ - /* we wait till we hit 5 consecutive bad articles */ - /* before we haul off and scan the directory */ - if (++noaccess < 5) - goto badart; - noaccess = 0; - dirp = opendir(dirname(groupdir)); - if (dirp == NULL) { - if (errno != EACCES) - msg("Can't open %s", dirname(groupdir)); - goto nextart; - } - nextnum = rflag ? minartno - 1 : ngsize + 1; - while ((dir = readdir(dirp)) != NULL) { - if (!dir->d_ino) - continue; - tnum = atol(dir->d_name); - if (tnum <= 0) - continue; - if (rflag ? (tnum > nextnum && tnum < bit) - : (tnum < nextnum && tnum > bit)) - nextnum = tnum; - } - closedir(dirp); - if (rflag ? (nextnum >= bit) : (nextnum <= bit)) - goto badart; - do { - clear(bit); - nextbit(); - } while (rflag ? (nextnum < bit) : (nextnum > bit)); - obit = -1; - aabs = FALSE; - goto nextart; - } else - noaccess = 0; - - if (hread(h, fp, TRUE) == NULL || (!rfq && !aselect(h, aabs))) { -badart: - FCLOSE(fp); - clear(bit); - obit = -1; - nextbit(); - aabs = FALSE; - goto nextart; - } - aabs = FALSE; - actdirect = FORWARD; - news = TRUE; - artbody = ftell(fp); - fmthdr(); - artlines = lastlin; - artread = 0; - prflags |= NEWART; - prflags &=~ NOPRT; - if (! cflag && hdrend < ARTWLEN && !cflag) - prflags |= HDRONLY; - dlinno = 0; - maxlinno = NLINES(h, fp); - erased = 0; - - obit = bit; - return 0; -} - -/* - * Print out whatever the appropriate header is - */ -fmthdr() { - char *briefdate(); - static FILE *ngfd = NULL; - static int triedopen = 0; - char pbuf[BUFLEN], *printbuffer = groupdir; - - lastlin = 0; - if (ngrp) { - pngsize = ngsize; - ngrp--; - if (!hflag) { - if (!triedopen) { - (void) sprintf(pbuf,"%s/newsgroups", LIB); - ngfd = fopen(pbuf, "r"); - triedopen++; - } - if (ngfd != NULL) { - register char *p; - char ibuf[BUFLEN]; - rewind(ngfd); - while (fgets(ibuf, BUFLEN, ngfd) != NULL) { - p = index(ibuf, '\t'); - if (p) - *p++ = '\0'; - if (strcmp(ibuf, groupdir) == 0) { - register char *q; - q = rindex(p, '\t'); - if (q) { - p = q; - *p++ = '\0'; - } - if (p) { - q = index(p, '\n'); - if (q) - *q = '\0'; - if (*--q == '.') - *q = '\0'; - (void) sprintf(pbuf,"%s (%s)", - groupdir, p); - printbuffer = pbuf; - } - break; - } - } - } - (void) sprintf(linebuf, "Newsgroup %s", printbuffer); - tfappend(linebuf); - } - } - hdrstart = lastlin; - if (!hflag) { - (void) sprintf(linebuf, "Article %s %s", - h->ident, briefdate(h->subdate)); - tfappend(linebuf); - } - xtabs(h); - vhprint(h, pflag ? 1 : 0); - (void) sprintf(linebuf, "(%d lines)", NLINES(h, fp)); tfappend(linebuf); - tfappend(""); - hdrend = lastlin; -} - -/* - * Grow tabs into spaces in header fields, 'cause the rest of this - * lax program drops turds all over tabs (so it does with \b's, but ..) - */ -xtabs(p) -register struct hbuf *p; -{ - xtabf(p->from, sizeof p->from); - xtabf(p->path, sizeof p->path); - xtabf(p->nbuf, sizeof p->nbuf); - xtabf(p->title, sizeof p->title); - xtabf(p->ident, sizeof p->ident); - xtabf(p->replyto, sizeof p->replyto); - xtabf(p->followid, sizeof p->followid); - xtabf(p->subdate, sizeof p->subdate); - xtabf(p->expdate, sizeof p->expdate); - xtabf(p->ctlmsg, sizeof p->ctlmsg); - xtabf(p->sender, sizeof p->sender); - xtabf(p->followto, sizeof p->followto); - xtabf(p->distribution, sizeof p->distribution); - xtabf(p->organization, sizeof p->organization); - xtabf(p->numlines, sizeof p->numlines); - xtabf(p->keywords, sizeof p->keywords); - xtabf(p->summary, sizeof p->summary); - xtabf(p->approved, sizeof p->approved); - xtabf(p->nf_id, sizeof p->nf_id); - xtabf(p->nf_from, sizeof p->nf_from); -#ifdef DOXREFS - xtabf(p->xref, sizeof p->xref); -#endif /* DOXREFS */ -} - -xtabf(s, size) -char *s; -int size; -{ - register char *p, *str; - register c, i; - char buf[LBUFLEN]; - - str = s; - if (index(str, '\t') == NULL) - return; - i = 0; - for (p = buf; c = *str++; i++) { - if (c == '\t') { - *p++ = ' '; - if ((i & 7) != 7) - str--; - } else if (c == '\n') { - i = -1; - *p++ = c; - } else - *p++ = c; - } - *p = '\0'; - strncpy(s, buf, size - 1); -} - -/* - * Print the file header to the temp file. - */ -vhprint(hp, verbose) -register struct hbuf *hp; -int verbose; -{ - register char *p1, *p2; - char fname[BUFLEN]; - char *tailpath(); - - fname[0] = '\0'; /* init name holder */ - - p1 = index(hp->from, '('); /* Find the sender's full name. */ - if (p1 == NULL && hp->path[0]) - p1 = index(hp->path, '('); - if (p1 != NULL) { - (void) strcpy(fname, p1+1); - p2 = index(fname, ')'); - if (p2 != NULL) - *p2 = '\0'; - } - - (void) sprintf(linebuf, "Subject: %s", hp->title); - tfappend(linebuf); - if (!hflag && hp->summary[0]) - (void) sprintf(linebuf, "Summary: %s", hp->summary), tfappend(linebuf); - if (!hflag && hp->keywords[0]) - (void) sprintf(linebuf, "Keywords: %s", hp->keywords), tfappend(linebuf); - if (verbose) { - (void) sprintf(linebuf, "From: %s", hp->from); tfappend(linebuf); - (void) sprintf(linebuf, "Path: %s", hp->path); tfappend(linebuf); - if (hp->organization[0]) { - (void) sprintf(linebuf, "Organization: %s", hp->organization); - tfappend(linebuf); - } - } - else { - if (p1 != NULL) - *--p1 = '\0'; /* bump over the '(' */ -#ifdef INTERNET - /* - * Prefer Path line if it's in internet format, or if we don't - * understand internet format here, or if there is no reply-to. - */ - (void) sprintf(linebuf, "From: %s", hp->from); -#else - (void) sprintf(linebuf, "Path: %s", tailpath(hp)); -#endif - if (fname[0] || (hp->organization[0] && !hflag)) { - (void) strcat(linebuf, " ("); - if (fname[0] == '\0') { - (void) strcpy(fname, hp->from); - p2 = index(fname,'@'); - if (p2) - *p2 = '\0'; - } - (void) strcat(linebuf, fname); - if (hp->organization[0] && !hflag) { - (void) strcat(linebuf, " @ "); - (void) strcat(linebuf, hp->organization); - } - (void) strcat(linebuf, ")"); - } - tfappend(linebuf); - if (p1 != NULL) - *p1 = ' '; - if (hp->ctlmsg[0]) { - (void) sprintf(linebuf, "Control: %s", hp->ctlmsg); - tfappend(linebuf); - } - } - - if (verbose) { - (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); tfappend(linebuf); - (void) sprintf(linebuf, "Date: %s", hp->subdate); tfappend(linebuf); - if (hp->sender[0]) { - (void) sprintf(linebuf, "Sender: %s", hp->sender); - tfappend(linebuf); - } - if (hp->replyto[0]) { - (void) sprintf(linebuf, "Reply-To: %s", hp->replyto); - tfappend(linebuf); - } - if (hp->followto[0]) { - (void) sprintf(linebuf, "Followup-To: %s", hp->followto); - tfappend(linebuf); - } - } - else if (strcmp(hp->nbuf, groupdir) != 0) { - (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); - tfappend(linebuf); - timer(); - } -} - -#ifdef MYDB - -char * -findparent(id, num) -char *id; -long *num; -{ - struct artrec a; - char idbuf[BUFSIZE]; - char *ngname(); - - strcpy(idbuf, id); - lcase(idbuf); - - if (lookart(id, &a) == DNULL) - return NULL; - if (a.parent == DNULL) - return NULL; - readrec(a.parent, &a); - *num = a.groups[0].artno; - return ngname(a.groups[0].newsgroup); -} - -#endif - - -/* - * Append file to temp file, handling control characters, folding lines, etc. - * We don't grow the temp file to more than nlines so that a user won't have - * to wait for 20 seconds to read in a monster file from net.sources. - * What we really want is coroutines--any year now. - */ - -#define ULINE 0200 -static char *maxcol; - -appfile(iop, nlines) -register FILE *iop; -{ - register int c; - register char *icol; /* &linebuf[0] <= icol <= maxcol */ - - if (artread || artlines >= nlines || iop == NULL) - return; - maxcol = linebuf; - icol = linebuf; - while ((c = getc(iop)) != EOF) { - switch (c) { - case ' ': - if (icol == maxcol && icol < linebuf + LBUFLEN - 1) { - *icol++ = ' '; - maxcol = icol; - } else { - if (*icol == '_') - *icol++ = ULINE | ' '; - else - icol++; - } - break; - case '\t': - icol = (icol - linebuf &~ 07) + 8 + linebuf; - growline(icol); - break; - case '\b': - if (icol > linebuf) --icol; - break; - case '\n': - outline(); - if (artlines >= nlines) - return; - icol = linebuf; - break; - case '\r': - icol = linebuf; - break; - case '\f': - outline(); outline(); outline(); - if (artlines >= nlines) - return; - icol = linebuf; - break; - default: - if (c < ' ' || c > '~') - break; - else if (icol >= linebuf + LBUFLEN - 1) - icol++; - else if (icol == maxcol) { - *icol++ = c; - maxcol = icol; } - else if (c == '_') - *icol++ |= ULINE; - else if (*icol == '_') - *icol++ = (c | ULINE); - else *icol++ = c; - break; - } - } - if (maxcol != linebuf) /* file not terminated with newline */ - outline(); - artread++; -} - -growline(col) -char *col; -{ - while (maxcol < col && maxcol < linebuf + LBUFLEN - 1) - *maxcol++ = ' '; -} - -outline() -{ - *maxcol = '\0'; - if (strncmp(linebuf, ">From ", 6) == 0) { - register char *p; - for (p = linebuf ; (*p = p[1]) != '\0' ; p++); - } - tfappend(linebuf); - if (maxcol > linebuf) - artlines = lastlin; - maxcol = linebuf; -} - -prget(prompter, buf) -char *prompter, *buf; -{ - char *p, *q, *r; - int c, lastc; - - curflag = CURP2; - r = buf; - lastc = '\0'; - for (;;) { - *r = '\0'; - p = secpr; - for (q = prompter ; *q ; q++) - *p++ = *q; - for (q = buf ; *q ; q++) { - if (p < &secpr[SECPRLEN-1] && *q >= ' ' && *p <= '~') - *p++ = *q; - } - *p = '\0'; - c = vgetc(); - if (c == '\n' || c == cintr) { - break; - } - if (c == cerase || c == '\b' || c == '\177') { - if (lastc == '\\') - r[-1] = c; - else if (r > buf) - r--; - } else if (c == ckill) { - if (lastc == '\\') - r[-1] = c; - else - r = buf; -#ifdef TIOCGLTC - } else if (c == cwerase) { - if (lastc == '\\') - r[-1] = c; - else { - while (r > buf && (r[-1] == ' ' || r[-1] == '\t')) - r--; - while (r > buf && r[-1] != ' ' && r[-1] != '\t') - r--; - } -#endif - } else { - *r++ = c; - } - lastc = c; - } - curflag = CURHOME; - secpr[0] = '\0'; - return (c == cintr); -} - - - -/* - * Execute a shell command. - */ - -shcmd(cmd, flags) -char *cmd; -{ - char *arg[4]; - - arg[0] = SHELL, arg[1] = "-c", arg[2] = cmd, arg[3] = NULL; - return prun(arg, flags); -} - - -prun(args, flags) -char **args; -{ - int pid; - int i; - int (*savequit)(); - char *env[100], **envp, **oenvp; - char a[BUFLEN + 2]; - extern char **environ; - int pstatus, retval; - - if (!(flags & BKGRND)) { - botscreen(); - ttycooked(); -#ifdef SIGTSTP - (void) signal(SIGTSTP, SIG_DFL); - (void) signal(SIGTTIN, SIG_DFL); - (void) signal(SIGTTOU, SIG_DFL); -#endif - } -#ifdef BSD4_2 - while ((pid = vfork()) == -1) -#else /* !BSD4_2 */ - /* 4.1 BSD (at least) can't handle this vfork with -ljobs */ - while ((pid = fork()) == -1) -#endif /* !BSD4_2 */ - sleep(1); /* must not clear alarm */ - if (pid == 0) { - for (i = 3 ; i < 20 ; i++) - close(i); - if (flags & BKGRND) { - (void) signal(SIGINT, SIG_IGN); - (void) signal(SIGQUIT, SIG_IGN); -#ifdef SIGTSTP - (void) signal(SIGTSTP, SIG_IGN); - (void) signal(SIGTTIN, SIG_IGN); - (void) signal(SIGTTOU, SIG_IGN); -#endif - (void) close(0); - (void) close(1); - (void) open("/dev/null", 2); - (void) dup(0); - } - /* set $A */ - (void) sprintf(a, "A=%s", filename); - oenvp = environ; - env[0] = a; - for (envp = env + 1 ; *oenvp != NULL && envp < env + 98 ; oenvp++) - if ((*oenvp)[0] != 'A' || (*oenvp)[1] != '=') - *envp++ = *oenvp; - *envp = NULL; - - (void) umask(savmask); - execve(args[0], args, env); - perror(args[0]); - exit(20); - } - if (!(flags & BKGRND)) { - savequit = signal(SIGQUIT, SIG_IGN); - while ((i = wait(&pstatus)) != pid && (i != -1 || errno == EINTR)) - ; - if (i == -1) - retval = 1; - else - retval = pstatus; - if (flags & CWAIT) { - fprintf(stderr, "[Hit return to continue]"); - while ((errno = 0, i = getchar()) != '\n' - && (i != EOF || errno == EINTR)); - } - (void) signal(SIGQUIT, savequit); - ttyraw(); - clearok(curscr, 1); -#ifdef SIGTSTP - (void) signal(SIGTSTP, onstop); - (void) signal(SIGTTIN, onstop); - (void) signal(SIGTTOU, onstop); -#endif - return retval; - } else - return 0; -} - -#ifdef DIGPAGE - - -/* - * Find end of current subarticle in digest. - */ - -findend(l) -{ - register int i, n; - register char *p; - - for (i = l ; i < l + ARTWLEN && i < lastlin ; i++) { - tfget(linebuf, i); - for (p = linebuf ; *p == '-' ; p++) - ; - n = (int)p - (int)linebuf; - if ( (n > 23 && n < 33) || (n > 65 && n < 79)) { - tfget(linebuf, ++i); - if (linebuf[0] == '\0') - return i + 1; - } - } - return 0; -} - -#endif - - -/*** Routines for handling temporary file ***/ - -/* - * Append to temp file. - * Long lines are folded. - */ - -tfappend(tline) -register char *tline; -{ - register char *nxtlin; - - do { - nxtlin = index(tline, '\n'); - if (nxtlin) - *nxtlin++ = '\0'; - - while (strlen(tline) > COLS) { - tfput(tline, lastlin++); - tline += COLS; - maxlinno++; - } - tfput(tline, lastlin++); - } while ((tline = nxtlin) != NULL); -} - - -tfput(tline, linno) -char *tline; -{ - register char *p; - register FILE *rtfp; /* try to make it a little faster */ - register int i; - - p = tline, i = even(COLS); - tfseek(linno, 1); - rtfp = tfp; - while (--i >= 0) { - if (*p) - putc(*p++, rtfp); - else - putc('\0', rtfp); - } - tflinno++; -} - - -tfget(tline, linno) -char *tline; -{ - tfseek(linno, 0); - fread(tline, even(COLS), 1, tfp); - tline[COLS] = '\0'; - tflinno++; -} - - -tfseek(linno, wrflag) -{ - static int lastwrflag = 1; - - if (linno != tflinno || wrflag != lastwrflag) { - (void) fseek(tfp, (long)linno * even(COLS), 0); - tflinno = linno; - lastwrflag = wrflag; - } -} - -/* VARARGS1 */ -msg(s, a1, a2, a3, a4) -char *s; -{ - (void) sprintf(secpr, s, a1, a2, a3, a4); -} - - -/* - * Update the display. - * The display is entirely controlled by this routine, - * which means that this routine may get pretty snarled. - */ - -static int savelinno = -1; /* dlinno on last call to updscr */ -static int savepr; /* prflags on last call */ -#ifdef TIOCGWINSZ -static int UPDATING = 0, WINCH = 0; - -/* - * called by winch() from virtterm.c -- resets state information back - * to start-up state and forces a full redraw of the screen. The - * current article is rewound to the beginning because it's would - * be very difficult to get the screen to return to the exact point - * in the file that the user left off (I know, I tried). - */ -winch_upd() -{ - if(UPDATING) /* concurrency. wow! */ - WINCH++; - else if((WINCH == 0) && (savelinno >= 0)) { - int saveline = dlinno, saveflag = curflag; - - /* reread the article */ - FCLOSE(fp); - obit = -1; - getnextart(FALSE); - appfile(fp, dlinno + ARTWLEN + 1); - - /* fix up the screen */ - curflag = saveflag; - strcpy(prompt,"more? "); - clearok(curscr, 1); - updscr(); - } -} -#endif /* TIOCGWINSZ */ - - -updscr() -{ - int count; - int i; - -#ifdef TIOCGWINSZ - UPDATING++; -#endif /* TIOCGWINSZ */ - if (checkin()) - return; - if ((prflags & HELPMSG) == 0 - && (dlinno != savelinno || savepr != prflags) - && quitflg == 0) { - if (dlinno != savelinno) - prflags &=~ NOPRT; - count = ARTWLEN; - if (prflags & NOPRT) - count = 0; - if ((prflags & HDRONLY) && count > hdrend) - count = hdrend - dlinno; -#ifdef DIGPAGE - if (endsuba > 0 && count > endsuba - dlinno) - count = endsuba - dlinno; -#endif - if ((prflags & NEWART) == 0) - ushift(ARTWIN, ARTWIN+ARTWLEN-1, dlinno - savelinno); - if (count > lastlin - dlinno) - count = lastlin - dlinno; - for (i = ARTWIN ; i < ARTWIN + ARTWLEN ; i++) - clrline(i); - for (i = 0 ; i < count ; i++) { - tfget(linebuf, dlinno + i); - mvaddstr(ARTWIN + i, 0, linebuf); - } - prflags &=~ NEWART; - savepr = prflags; - savelinno = dlinno; - } - clrline(SPLINE), clrline(PRLINE); -#ifdef STATTOP - mvaddstr(PRLINE, 0, prompt); -#else - if (strlen(secpr) <= COLS) - mvaddstr(PRLINE, 0, prompt); -#endif - mvaddstr(PRLINE, 59, timestr); - mvaddstr(PRLINE, 17, groupdir); - addch(' '); addnum(bit); addch('/'); addnum(pngsize); addch(' '); - if (ismail) - mvaddstr(PRLINE, 75, ismail > 1? "MAIL" : "mail"); - mvaddstr(SPLINE, 0, secpr); - if (curflag == CURP1) - move(PRLINE, strlen(prompt)); - else if (curflag == CURHOME) - move(0, 0); - refresh(); -#ifdef TIOCGWINSZ - UPDATING=0; - if (WINCH) { /* window changed while updating screen */ - WINCH = 0; - winch_upd(); - } -#endif /* TIOCGWINSZ */ -} - -addnum(n) -register long n; -{ - if (n >= 10) - addnum(n / 10); - addch((char)(n % 10 + '0')); -} - -/* - * Called on alarm signal. - * Simply sets flag, signal processed later. - */ - -onalarm() -{ -#ifdef SIGTSTP - int dojump = reading; - - reading = FALSE; - alflag++; - if (dojump) - longjmp(alrmjmp, 1); -#else /* !SIGTSTP */ - alflag++; -#endif -} - -/* - * Process alarm signal (or start clock) - */ -timer() -{ - time_t tod; - int hour; - int i; - struct tm *t; - struct stat statb; - struct tm *localtime(); - static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; - static long oldmsize = 1000000L; - static int rccount = 10; - static time_t lastismail = 0; - - alflag = 0; - (void) signal(SIGALRM, onalarm); - (void) time(&tod); - t = localtime(&tod); - i = 60 - t->tm_sec; - (void) alarm(i > 30? 30 : i); /* reset alarm */ - hour = t->tm_hour % 12; - if (hour == 0) hour = 12; - (void) sprintf(timestr, "%.3s %d %d:%02d", - months + 3 * t->tm_mon, t->tm_mday, hour, t->tm_min); - if (mailf == NULL || stat(mailf, &statb) < 0) { - statb.st_size = 0; - } - if (statb.st_size > oldmsize) { - ismail = 2; - beep(); - } else { - if (statb.st_size == 0) - ismail = 0; - /* force MAIL for at least 30 seconds */ - else if (ismail > 1 && (lastismail+30) < tod) - ismail = 1; - } - oldmsize = statb.st_size; - lastismail = tod; - if (uflag && !xflag && --rccount < 0) { - writeoutrc(); - if (secpr[0] == '\0') - (void) strcpy(secpr, ".newsrc updated"); - rccount = 10; - } -} - -char * -getmailname() -{ - static char mailname[32]; - register char *p; - - if( (p = getenv("MAIL")) != NULL) - return p; -#ifndef MMDF - if (username[0] == '\0' || strlen(username) > 15) - return NULL; -#ifdef USG - (void) sprintf(mailname, "/usr/mail/%s", username); -#else /* !USG */ - (void) sprintf(mailname, "/usr/spool/mail/%s", username); -#endif /* !USG */ -#else /* MMDF */ - (void) sprintf(mailname, "%s/mailbox", userhome); -#endif /* MMDF */ - return mailname; -} - - - -/*** Terminal I/O ***/ - -#define INBUFSIZ 8 - -char inbuf[INBUFSIZ]; /* input buffer */ -char outbuf[BUFSIZ]; /* output buffer */ -int innleft = 0; /* # of chars in input buffer */ -int outnleft = BUFSIZ; /* room left in output buffer */ -char *innext; /* next input character */ -char *outnext = outbuf; /* next space in output buffer */ -#ifdef USG -int oflags; /* fcntl flags (for nodelay read) */ -#endif - -/* - * Input a character - */ - -vgetc() -{ - register c; -#if defined(BSD4_2) || defined(BSD4_1C) - int readfds, exceptfds; -#endif - -recurse: - if (--innleft >= 0) { - c = *innext++; - } else { - if (alflag) - timer(); - updscr(); /* update the display */ - for (;;) { - if (innleft > 0 || alflag) - goto recurse; - intflag = 0; -#ifdef USG - if (oflags & O_NDELAY) { - oflags &=~ O_NDELAY; - fcntl(0, F_SETFL, oflags); - } -#endif -#ifdef SIGTSTP - if (setjmp(alrmjmp)) - continue; - if (setjmp(intjmp)) - return cintr; - reading = TRUE; -#endif /* SIGTSTP */ -#if defined(BSD4_2) || defined(BSD4_1C) - /* Use a select because it can be interrupted. */ - readfds = 1; exceptfds = 1; - select(1, &readfds, (int *)0, &exceptfds, (int *)0); - if (!(readfds & 1)) - break; -#endif - innleft = read(0, inbuf, INBUFSIZ); -#ifdef SIGTSTP - reading = FALSE; -#endif /* SIGTSTP */ - if (innleft > 0) - break; - if (innleft == 0) { - quitflg++; - return cintr; - } - if (errno != EINTR) - abort(); /* "Can't happen" */ - if (intflag) { - intflag--; - return cintr; - } - } - innext = inbuf + 1; - innleft--; - c = inbuf[0]; - } -#ifndef USG -#ifndef CBREAK - c &= 0177; - if (c == '\034') /* FS character */ - xxit(0); -#endif -#endif - if (c == '\f') { - clearok(curscr, 1); - prflags &=~ NOPRT; - goto recurse; - } - if (c == '\r') - c = '\n'; - return c; -} - - -/* - * Push a character back onto the input stream. - */ - -pushback(c) -{ - if (innext <= inbuf) - abort(); - *--innext = c; - innleft++; -} - -/* - * Check for terminal input - */ - -checkin() -{ -#ifdef FIONREAD - int count; -#endif -#ifdef STATTOP - if (innleft > 0) -#else - if (innleft > 0 || alflag) -#endif - return 1; -#if defined(USG) || defined(FIONREAD) - if (ospeed >= B9600) - return 0; - vflush(); - if (ospeed <= B300) - ttyowait(); -#ifdef USG - if ((oflags & O_NDELAY) == 0) { - oflags |= O_NDELAY; - (void) fcntl(0, F_SETFL, oflags); - } - if ((innleft = read(0, inbuf, INBUFSIZ)) > 0) { - innext = inbuf; - return 1; - } -#endif -#ifdef FIONREAD - count = 0; /* in case FIONREAD fails */ - (void) ioctl(0, FIONREAD, (char *)&count); - if (count) - return 1; -#endif -#endif - return 0; -} - - - -/* - * flush terminal input queue. - */ - -clearin() -{ -#ifdef USG - (void) ioctl(0, TCFLSH, (char *)0); -#else -#ifdef TIOCFLUSH - (void) ioctl(0, TIOCFLUSH, (char *)0); -#else - struct sgttyb tty; - (void) ioctl(0, TIOCGETP, &tty); - (void) ioctl(0, TIOCSETP, &tty); -#endif -#endif - innleft = 0; -} - -vputc(c) -{ - if (--outnleft < 0) { - vflush(); - outnleft--; - } - *outnext++ = c; -} - -/* - * Flush the output buffer - */ - -vflush() -{ - register char *p; - register int i; -#ifdef BSD4_2 - int mask; -#else - unsigned oalarm; -#endif - -#ifdef BSD4_2 - mask = sigblock(1 << (SIGALRM-1)); -#else - oalarm = alarm(0); -#endif - for (p = outbuf ; p < outnext ; p += i) { - if ((i = write(1, p, outnext - p)) < 0) { - if (errno != EINTR) - abort(); /* "Can't happen" */ - i = 0; - } - } - outnleft = BUFSIZ; - outnext = outbuf; -#ifdef BSD4_2 - sigsetmask(mask); -#else - (void) alarm(oalarm); -#endif -} - -/*** terminal modes ***/ - -#ifdef USG -static struct termio oldtty, newtty; - -/* - * Save tty modes - */ - -ttysave() -{ - if (ioctl(1, TCGETA, &oldtty) < 0) - xerror("Can't get tty modes"); - newtty = oldtty; - newtty.c_iflag &=~ (INLCR|IGNCR|ICRNL); - newtty.c_oflag &=~ (OPOST); - newtty.c_lflag &=~ (ICANON|ECHO|ECHOE|ECHOK|ECHONL); - newtty.c_lflag |= (NOFLSH); - newtty.c_cc[VMIN] = 1; - newtty.c_cc[VTIME] = 0; - cerase = oldtty.c_cc[VERASE]; - ckill = oldtty.c_cc[VKILL]; - cintr = oldtty.c_cc[VINTR]; - ospeed = oldtty.c_cflag & CBAUD; - initterm(); -} - - -/* - * Set tty modes for visual processing - */ - -ttyraw() -{ - while (ioctl(1, TCSETAF, &newtty) < 0 && errno == EINTR) - ; - rawterm(); -} - -ttyowait() -{ /* wait for output queue to drain */ - while (ioctl(1, TCSETAW, &newtty) < 0 && errno == EINTR) - ; -} - -/* - * Restore tty modes - */ - -ttycooked() -{ - cookedterm(); - vflush(); - while (ioctl(1, TCSETAF, &oldtty) < 0 && errno == EINTR) - ; - oflags &=~ O_NDELAY; - (void) fcntl(0, F_SETFL, oflags) ; -} - -#else - -static struct sgttyb oldtty, newtty; -#ifdef TIOCGLTC -static struct ltchars oldltchars, newltchars; -#endif - -/* - * Save tty modes - */ - -ttysave() -{ -#ifdef CBREAK - struct tchars tchars; /* special characters, including interrupt */ -#endif -#ifdef SIGTSTP - int getpgrp(); -#if defined(BSD4_2) || defined(BSD4_1C) - int tpgrp; -#else /* BSD4_1 */ - short tpgrp; -#endif /* BSD4_1 */ - -retry: -#ifdef BSD4_2 - (void) sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)); -#else /* !BSD4_2 */ - (void) signal(SIGTSTP, SIG_HOLD); - (void) signal(SIGTTIN, SIG_HOLD); - (void) signal(SIGTTOU, SIG_HOLD); -#endif /* !BSD4_2 */ - if (ioctl(2, TIOCGPGRP, (char *)&tpgrp) < 0) - goto nottty; - if (tpgrp != getpgrp(0)) { /* not in foreground */ - (void) signal(SIGTTOU, SIG_DFL); -#ifdef BSD4_2 - (void) sigsetmask(sigblock(0) & ~sigmask(SIGTTOU)); -#endif /* BSD4_2 */ - (void) kill(0, SIGTTOU); - /* job stops here waiting for SIGCONT */ - goto retry; - } - (void) signal(SIGTTIN, SIG_DFL); - (void) signal(SIGTTOU, SIG_DFL); - (void) signal(SIGTSTP, SIG_DFL); -#ifdef BSD4_2 - (void) sigsetmask(sigblock(0) & ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU))); -#endif /* BSD4_2 */ -#endif /* SIGTSTP */ - if (ioctl(1, TIOCGETP, (char *)&oldtty) < 0) -nottty: xerror("Can't get tty modes"); - newtty = oldtty; - newtty.sg_flags &=~ (CRMOD|ECHO|XTABS); -#ifdef CBREAK - newtty.sg_flags |= CBREAK; - ioctl(1, TIOCGETC, (char *)&tchars); - cintr = tchars.t_intrc; -#else /* !CBREAK */ - newtty.sg_flags |= RAW; - cintr = '\0177'; /* forcibly this on V6 systems */ -#endif /* !CBREAK */ - cerase = oldtty.sg_erase; - ckill = oldtty.sg_kill; - ospeed = oldtty.sg_ospeed; -#ifdef TIOCGLTC - if (ioctl(1, TIOCGLTC, (char *)&oldltchars) >= 0) { - newltchars = oldltchars; - newltchars.t_dsuspc = -1; - cwerase = oldltchars.t_werasc; - } -#endif - initterm(); -#ifdef SIGTSTP - (void) signal(SIGTTIN, onstop); - (void) signal(SIGTTOU, onstop); - (void) signal(SIGTSTP, onstop); -#endif /* SIGTSTP */ -} - - -/* - * Set tty modes for visual processing - */ - -ttyraw() -{ - while (ioctl(1, TIOCSETN, (char *)&newtty) < 0 && errno == EINTR) - ; -#ifdef TIOCGLTC - if (newltchars.t_dsuspc == '\377') - while (ioctl(1, TIOCSLTC, (char *)&newltchars) < 0 && errno == EINTR) - ; -#endif - rawterm(); -} - -ttyowait() -{ /* wait for output queue to drain */ -#ifdef TIOCDRAIN /* This ioctl is a local mod on linus */ - (void) ioctl(1, TIOCDRAIN, (char *)0); -#endif -} - - -/* - * Restore tty modes - */ - -ttycooked() -{ - cookedterm(); - vflush(); - while (ioctl(1, TIOCSETN, (char *)&oldtty) < 0 && errno == EINTR) - ; -#ifdef TIOCGLTC - if (newltchars.t_dsuspc == '\377') - while (ioctl(1, TIOCSLTC, (char *)&oldltchars) < 0 && errno == EINTR) - ; -#endif -} - -#endif - - - -/*** signal handlers ***/ - -onint() { -#ifdef SIGTSTP - int dojump = reading; - - reading = FALSE; -#endif /* SIGTSTP */ - if (!news) { - ttycooked(); - xxit(1); - } - (void) signal(SIGINT, onint); - clearin(); /* flush input queue */ -#ifdef SIGTSTP - if (dojump) - longjmp(intjmp, 1); -#endif /* SIGTSTP */ - intflag++; -} - -#ifdef SIGTSTP -onstop(signo) -int signo; -{ - /* restore old terminal state */ - botscreen(); - vflush(); - ttycooked(); - (void) signal(signo, SIG_DFL); -#ifdef BSD4_2 - (void) sigblock(sigmask(SIGALRM)|sigmask(SIGINT)); - (void) sigsetmask(sigblock(0) & ~sigmask(signo)); -#else /* BSD4_1 */ - (void) alarm(0); -#endif /* BSD4_1 */ - (void) kill(0, signo); /* stop here until continued */ - - (void) signal(signo, onstop); - /* restore our special terminal state */ - ttyraw(); -#ifdef TIOCGWINSZ - winch(); /* get current window size and redraw screen */ -#endif /* TIOCGWINSZ */ - clearok(curscr, 1); - updscr(); -#ifdef BSD4_2 - (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM)|sigmask(SIGINT))); -#else /* BSD4_1 */ - timer(); -#endif /* BSD4_1 */ -} -#endif - -/*** stolen from rfuncs2.c and modified ***/ - -vsave(to, flags) -register char *to; -{ - register FILE *ufp; - int isprogram = 0; - int isnew = 1; - long saveoff; - char temp[20]; - char *fname; - char prog[BUFLEN + 24]; - - saveoff = ftell(fp); - (void) fseek(fp, artbody, 0); - fname = to; - if (*to == PIPECHAR) { - if (strlen(to) > BUFLEN) { - msg("Command name too long"); - goto out; - } - flags |= OVWRITE; - (void) strcpy(temp, "/tmp/vnXXXXXX"); - (void) mktemp(temp); - fname = temp; - _amove(ROWS - 1, 0); - vflush(); - } - if ((flags & OVWRITE) == 0) { - ufp = fopen(fname, "r"); - if (ufp != NULL) { - (void) fclose(ufp); - isnew = 0; - } - } - (void) umask(savmask); - - if (*to == PIPECHAR) - isprogram++; - if ((ufp = fopen(fname, (flags & OVWRITE) == 0? "a" : "w")) == NULL) { - msg("Cannot open %s", fname); - goto out; - } - /* - * V7MAIL code is here to conform to V7 mail format. - * If you need a different format to be able to - * use your local mail command (such as four ^A's - * on the end of articles) substitute it here. - */ - if (flags & SVHEAD) { -#ifdef MMDF - if (!isprogram) - fprintf(ufp, "\001\001\001\001\n"); -#endif /* MMDF */ -#ifdef V7MAIL - h->subtime = cgtdate(h->subdate); - fprintf(ufp, "From %s %s", replyname(h), ctime(&h->subtime)); -#endif - hprint(h, ufp, 2); -#ifdef V7MAIL - tprint(fp, ufp, TRUE); - putc('\n', ufp); /* force blank line at end (ugh) */ -#else - tprint(fp, ufp, FALSE); -#endif - } else { - tprint(fp, ufp, FALSE); - } - - fclose(ufp); - if (isprogram) { - (void) sprintf(prog, "(%s)<%s", to + 1, fname); - shcmd(prog, CWAIT); - prflags |= NOPRT; - } else { - if ((flags & OVWRITE) == 0) - msg("file: %s %s", to, isnew ? "created" : "appended"); - else - msg("file: %s written", to); - } - -out: - if (isprogram) { - (void) unlink(fname); - } - (void) umask(N_UMASK); - (void) fseek(fp, saveoff, 0); -} - -xxit(status) -int status; -{ - (void) unlink(infile); - (void) unlink(outfile); -#ifdef SORTACTIVE - if (strncmp(ACTIVE,"/tmp/", 5) == 0) - (void) unlink(ACTIVE); -#endif /* SORTACTIVE */ - if (ospeed) { /* is == 0, we haven't been in raw mode yet */ - botscreen(); - vflush(); - ttycooked(); - } - exit(status); -} *-*-END-of-src/visual.c-*-* echo x - src/recmail.c 1>&2 sed 's/.//' >src/recmail.c <<'*-*-END-of-src/recmail.c-*-*' -/* - * This software is Copyright (c) 1986 by Rick Adams. - * - * Permission is hereby granted to copy, reproduce, redistribute or - * otherwise use this software as long as: there is no monetary - * profit gained specifically from the use or reproduction or this - * software, it is not sold, rented, traded or otherwise marketed, and - * this copyright notice is included prominently in any copy - * made. - * - * The author make no claims as to the fitness or correctness of - * this software for any use whatsoever, and it is provided as is. - * Any use of this software is at the user's own risk. - * - * recmail: read a mail message on stdin, grab all addresses in To and Cc - * lines, and pass the full message to all addressees. This is useful to - * send the output of a recently edited mail message (with headers edited too). - * It is similar to sendmail -t, but only assumes /bin/mail. - * To use your own mailer, e. g. nmail, compile with -DMAILER=my_mailer. - */ - -#ifdef SCCSID -static char *SccsId = "@(#)recmail.c 1.15 10/23/86"; -#endif /* SCCSID */ - -#include "params.h" - -#ifndef MAILER -#define MAILER "/bin/mail" -#endif -char mailer[] = MAILER; - -#define MAXRECIPS 100 -char *recips[MAXRECIPS]; -int nrecips = 0; - -main() -{ - FILE *fd; - char *tmpf; - FILE *errfd; - char *errf; - char linebuf[1024]; - int i, pid, wpid; - int exstat; - char *mypath; - int goodcnt, badcnt; - char *mktemp(), *getenv(); - - tmpf = mktemp("/tmp/rmXXXXXX"); - (void) close(creat(tmpf,0666)); - fd = fopen(tmpf, "w"); - errf = mktemp("/tmp/rmXXXXXX"); - (void) close(creat(errf,0666)); - errfd = fopen(errf, "w"); - fprintf(errfd, "Subject: Returned mail\n"); - fprintf(errfd, "\n ----- Transcript of session follows -----\n"); - (void) fflush(errfd); - goodcnt = badcnt = 0; - - while (fgets(linebuf, sizeof linebuf, stdin) != NULL) { - if ((strncmp(linebuf, "Bcc: ", 5) == 0 || - strncmp(linebuf, "bcc: ", 5) == 0 || - strncmp(linebuf, "BCC: ", 5) == 0)) { - if (linebuf[5] != '\n') - addrecips(linebuf+5); - } - else if (fputs(linebuf, fd) == EOF) - goto werror; - if (linebuf[0] == '\n') - break; - if ((strncmp(linebuf, "To: ", 4) == 0 || - strncmp(linebuf, "to: ", 4) == 0 || - strncmp(linebuf, "TO: ", 4) == 0 || - strncmp(linebuf, "Cc: ", 4) == 0 || - strncmp(linebuf, "cc: ", 4) == 0 || - strncmp(linebuf, "CC: ", 4) == 0) && - linebuf[4] != '\n') - addrecips(linebuf+4); - } - if (!feof(stdin)) { - while (fgets(linebuf, sizeof linebuf, stdin) != NULL) { - if (fputs(linebuf, fd) == EOF) { -werror: - printf("write error on temp file\n"); - exit(2); - } - } - } - /* - * Append the contents of the .signature file (if it exists) to - * the end of the mail message - */ - { - char sigbuf[BUFSIZ]; - register c; - register char *p = getenv("HOME"); - FILE *infp; - - if (p) { - (void) sprintf(sigbuf, "%s/%s", p, ".signature"); - if (infp = fopen(sigbuf, "r")) { - fprintf(fd,"---\n"); - while ((c = getc(infp)) != EOF) - putc(c,fd); - (void) fclose(infp); - } - } - } - (void) fclose(fd); - - /* - * Force the path to only consider /bin and /usr/bin, since - * that's the version of mail we want (not /usr/ucb/mail) - */ - if (mailer[0] != '/') { - register int e; - extern char **environ; - for (e = 0; environ[e] != NULL; ++e) - if (strncmp(environ[e], "PATH=", 5) == 0) { - environ[e] = "PATH=/bin:/usr/bin"; - break; - } - } - mypath = getenv("PATH"); - if (mypath) - strcpy(mypath, "/bin:/usr/bin"); - - /* - * We send the copies out separately, because of a bug in - * USG's /bin/mail which will generate ANOTHER To: line, - * even though we already have one, if there are at least - * two recipients. - */ - for (i=0; i<nrecips; i++) { - /* - * mail recips[i] < tmpf - */ - pid = mailto(tmpf, errfd, recips[i]); - exstat = -1; - while ((wpid = wait(&exstat)) >= 0 && wpid != pid) - ; - if (exstat == 0) - goodcnt++; - else - badcnt++; - } - if (badcnt) { - mailback(errfd, tmpf, errf); - (void) unlink(tmpf); - (void) unlink(errf); - exit(1); - } else if (goodcnt == 0) { - fprintf(errfd, "recmail: no 'To:' line\n"); - mailback(errfd, tmpf, errf); - (void) unlink(tmpf); - (void) unlink(errf); - exit (1); - } - (void) unlink(tmpf); - (void) unlink(errf); - exit (0); -} - -#define isok(c) (isprint(c) && (c) != ' ' && c != ',') -addrecips(line) -char *line; -{ - char *front, *back, *tail; - char *malloc(); - - tail = line + strlen(line); - for (front=line; front < tail; ) { - while (!isok(*front) && front < tail) - front++; - if (front >= tail) - break; /* skip end of line garbage */ - for (back=front; isok(*back); back++) - ; - *back=0; - if (nrecips >= MAXRECIPS) { - printf("Too many destinations\n"); - exit(2); - } - if ((recips[nrecips] = malloc(strlen(front) + 1)) == NULL) { - printf("Out of space\n"); - exit(2); - } - (void) strcpy(recips[nrecips], front); - nrecips++; - front = back+1; - } -} - -int -mailto(tmpf, errfd, recip) -char *tmpf; -FILE *errfd; -char *recip; -{ - register int pid; - - /* - * mail recips < tmpf - */ - while ((pid = vfork()) == -1) { - fprintf(stderr, "fork failed, waiting...\r\n"); - sleep(60); - } - if (pid == 0) { - (void) close(0); - (void) open(tmpf, 0); - if (errfd != NULL) { - (void) close(1); - (void) dup(fileno(errfd)); - (void) fclose(errfd); - (void) close(2); - (void) dup(1); - } - execlp(mailer, mailer, recip, (char *)0); - perror(mailer); - exit(1); - } - return pid; -} - -mailback(errfd, tmpf, errf) -register FILE *errfd; -char *tmpf; -char *errf; -{ - register FILE *fd; - register int c; - int exstat; - register int pid, wpid; - char *logn; - char *getlogin(), *getenv(); - register struct passwd *pwd; - - if ((fd = fopen(tmpf, "r")) != NULL) { - fprintf(errfd, "\n ----- Unsent message follows -----\n"); - while ((c = getc(fd)) != EOF) - putc(c, errfd); - (void) fclose(fd); - } - (void) fclose(errfd); - if ((logn = getlogin()) == NULL && (logn = getenv("USER")) == NULL) { - if ((pwd = getpwent(getuid())) == NULL) - return; - logn = pwd->pw_name; - } - pid = mailto(errf, (FILE *)NULL, logn); - while ((wpid = wait(&exstat)) >= 0 && wpid != pid) - ; -} *-*-END-of-src/recmail.c-*-* echo x - src/ftime.c 1>&2 sed 's/.//' >src/ftime.c <<'*-*-END-of-src/ftime.c-*-*' -#ifdef SCCSID -static char *SccsId = "@(#)ftime.c 2.5 4/26/85"; -#endif /* SCSCID */ - -#include <sys/types.h> -struct timeb -{ - time_t time; - unsigned short millitm; - short timezone; - short dstflag; -}; - -extern long timezone; -extern int daylight; - -ftime(tp) -struct timeb *tp; -{ - long t; - - time(&t); - tp->time = t; - tp->millitm = 0; - tp->timezone = timezone/60; - tp->dstflag = daylight; -} *-*-END-of-src/ftime.c-*-* exit