#include #include #include /* T. Jennings 15 May 87 Perform a telex type function by printing all unread messages to the printer or diskfile. Because of the funky scheduler in Fido, where this might get invoked a number of times, dont creat the output file unless there really are message to be printed. This is a hack, and no apologies are made for the ugly code contained herein. So there. */ int outfile; /* output file handle */ struct _msg msg; /* message header structure */ struct _fido fido; /* big system file */ struct _area msgarea; struct _xfbuf xfbuf; /* file search first/next struct */ struct _nmap nmap; struct _ndat ndat; struct _ntc ntc; int nodefile; /* node file handles */ int ntcfile; int ndatfile; int idxfile; int ndxfile; int zdxfile; int nodetotal; /* satisfy link */ int connect_tries,dial_tries; /* satisfy link */ char nodepath[80] = ""; /* current directory */ struct _node id,altid; /* Crude telex type function; prints out messages from the mail directory. It prints only messages that have not been read yet; it then increments the 'times' counter in the message. */ unsigned _stack = 20000; /* be overly generous (paranoid) */ main(argc,argv) int argc; char **argv; { char msgname[SS],outname[SS],buff[SS],*p; int i,f,v,n; struct _xfbuf xfbuf; int doff,doall; printf("TWIX (16 Jun 91) FidoNet Message Printer for "); copr(); strcpy(outname,"PRN"); /* default output device */ allmem(); fastfile(8); /* enable buffered I/O */ n= open("fido.sys",0); /* load system stuff */ if (n == -1) { clprintf("The Fido system file \"FIDO.SYS\" is missing!\r\n"); exit(1); } read(n,&fido,sizeof(fido)); close(n); if (fido.fido_version != FIDOVER) { clprintf("Wrong Fido/FidoNet or TWIX version!\r\n"); exit(1); } id.zone= fido.zone; /* node ID */ id.net= fido.net; id.number= fido.number; id.point= fido.point; altid.zone= fido.altzone; /* alternate ID */ altid.net= fido.altnet; altid.number= fido.altnumber; altid.point= fido.altpoint; open_node(); /* open the node files */ open_nmap(fido.event); /* specific nodemap */ if (node_files()) { printf("Missing or wrong version nodelist -- run \"MAKELIST.EXE\"\r\n"); exit(1); } doff= 1; /* do formfeeds */ doall= 0; /* not all, only new ones */ while (--argc) { ++argv; cpyarg(buff,*argv); /* a copy of any filename */ if (*buff) strcpy(outname,buff);/* output name, if any */ strip_switch(msgname,*argv); /* a copy of the switches, */ switch (*msgname) { case 'A': doall= 1; break; case 'V': doff= 0; break; } } printf("- Sending output to %s\r\n",outname); outfile= -1; /* mark not open yet */ v= open("fido.sys",0); /* load system stuff */ if (v == 0) { printf("The Fido system file FIDO.SYS is missing!\r\n"); exit(1); } read(v,&fido,sizeof(fido)); close(v); if (fido.fido_version != FIDOVER) { cprintf("Wrong Fido version!\r\n"); exit(1); } id.zone= fido.zone; id.net= fido.net; id.number= fido.number; id.point= fido.point; altid.zone= fido.altzone; altid.net= fido.altnet; altid.number= fido.altnumber; altid.point= fido.altpoint; getarea(fido.netmarea,&msgarea); /* select the msg area */ /* Now find all messages that have not been read, and print them. */ makemname(msgname,"*.msg"); xfbuf.s_attrib= 0; i= 0; while (_find(msgname,i++,&xfbuf)) { makemname(buff,xfbuf.name); /* build file name */ f= open(buff,2); /* open the message, */ if (f == -1) continue; n= read(f,&msg,sizeof(struct _msg)); /* read the header, */ if ((n == sizeof(struct _msg)) && /* if a good msg file, */ ((msg.times == 0) || doall)) { /* or one we want */ n= atoi(xfbuf.name); /* make the msg number */ if (outfile == -1) { /* if not open yet */ outfile= creat(outname,1); if (outfile == -1) { /* open output file */ printf("Cant create output file %s\r\n",outname); exit(2); } } listhdr(&msg,n); /* print header, */ dumptext(f); /* print the text, */ if (doff) lputs("\014"); /* do FFs */ ++msg.times; /* mark it read */ lseek(f,0L,0); /* seek over header, */ write(f,&msg,sizeof(struct _msg)); /* write it out, */ } close(f); /* close the message */ } if (outfile != -1) close(outfile); close_node(); exit(0); } /* Get message area #n; return 0 if not set, illegal number or other error. */ getarea(n,a) unsigned n; /* area number */ struct _area *a; /* struct to load */ { int off,f,i; if (n < 0) return(0); /* no such area */ off= sizeof(struct _fido); /* offset to beg msg areas */ if (n >= fido.marea_max) return(0); /* msg area max */ f= open("fido.sys",0); if (f == -1) return(0); /* no system file! */ off += n * sizeof(struct _area); /* offset plus area # */ lseek(f,(0L + off),0); /* seek there, */ i= read(f,a,sizeof(struct _area)); /* read some, */ close(f); /* immediately close it */ if (i != sizeof(struct _area)) return(0); /* check read error */ a-> number= n; /* set the path number */ return(*a-> path != NUL); /* invalid if no path set */ } /* Assemble a full msg filename */ makemname(d,p) char *d,*p; { strcpy(d,msgarea.path); /* put in the path, */ strcat(d,p); /* add the filename */ } /* Display the contents of a text file on the screen, do word wrap and all the other good stuff. The handle of an open file is passed. This does not output lines beginning with ^A. */ dumptext(f) int f; /* open file to dump to screen */ { int screen; /* current screen column */ int width; /* callers maximum screen width */ char *cp; char word[SS]; /* word we build before output */ int count; int i; /* index (length) of word */ char c,lastc; /* current and previous character */ FLAG crsoh; /* 1 == found embedded ^A line */ if (f == -1) return; /* be serious */ width= 76; screen= 0; /* nothing on screen yet */ crsoh= 0; /* start CR/SOH machine */ c= CR; /* in case first is SOH */ while (1) { i= 0; /* local word index */ word[i]= NUL; /* word is empty */ while (i < sizeof(word)) { /* word at a time */ lastc= c; /* remember last character */ while (1) { c= NUL; count= read(f,&c,1); /* get a character, */ if (! count) break; /* check EOF */ /* Do some processing to eliminate crap generated by other programs and older Fidos. */ switch (c) { case CR + 128: if (lastc == ' ') c= NUL; else c= ' '; break; case LF: c= NUL; break; } if (c) break; /* got a real one */ } if (count == 0) break; /* end of file, word too */ /* The CR/SOH machine detects "IFNA Kludge" route lines and other nonsense embedded in messages; this detects lines beginning with ^A and does not output them, except to sysops. */ if (crsoh) { /* if machine is on, */ if (c == CR) crsoh= 0; /* CR turns it off, */ continue; /* eat characters */ } crsoh= (c == SOH) && (lastc == CR); if (crsoh) continue; /* check for new start */ if (c == CR) break; /* end of (the) wor(l)d */ word[i++]= c; /* build the word */ word[i]= NUL; /* for output */ if ((c == TAB) || (c == ' ')) break; } if (i + screen > width) { /* if combined width */ lputs("\r\n"); /* too long, wrap */ screen= 0; /* before typing word */ } lputs(word); /* output the word */ screen += i; /* size on screen */ if (c == CR) { /* if a hard CR, */ lputs("\r\n"); /* do a CR LF */ screen= 0; } if (count == 0) break; /* check EOF */ } lputs("\r\n"); } /* List the header of the message. */ listhdr(m,n) struct _msg *m; int n; { struct _node msg_orig,msg_dest; msg_orig.number= m-> orig_node; /* set the node struct */ msg_orig.net= m-> orig_net; /* for internal compatibility */ msg_orig.zone= id.zone; msg_dest.number= m-> dest_node; msg_dest.net= m-> dest_net; msg_dest.zone= id.zone; /**/ msg_orig.zone= id.zone; /**/ msg_dest.zone= id.zone; lprintf("#%-3u %s [%u] ",n,m-> date,m-> times); if (m-> attr & MSGPRIVATE) lprintf("(PRIVATE) "); if (m-> attr & MSGSENT) lprintf("(SENT) "); if (m-> attr & MSGREAD) lprintf("(RECV'D) "); if (m-> attr & MSGFILE) lprintf("(FILE ATTACHED) "); if (!is_us(&msg_orig) && !is_us(&msg_dest)) lprintf("(IN TRANSIT) "); if (m-> attr & MSGORPHAN) lprintf("(ORPHAN) "); if (m-> attr & MSGKILL) lprintf("(KILL/SENT) "); lputs(bucks_str(m-> cost)); lputs("\r\n"); lprintf("From: %s",m-> from); lprintf(", %s",str_node(&msg_orig)); if (! is_us(&msg_orig)) { if (find_ndat(&msg_orig) != -1) lprintf(", %s, %s",ndat.name,ndat.city); } lputs("\r\n"); lprintf("To: %s",m-> to); lprintf(", %s",str_node(&msg_dest)); if (! is_us(&msg_dest)) { if (find_ndat(&msg_dest) != -1) lprintf(", %s, %s",ndat.name,ndat.city); } lputs("\r\n"); if (m-> reply) lprintf("Reply To #%u ",m-> reply); if (m-> up) lprintf("See Also #%u",m-> up); if (m-> reply || m-> up) lputs("\r\n"); if (m-> attr & MSGFILE) lprintf("File(s): %s\r\n",m-> subj); else lprintf("Subj: %s\r\n",m-> subj); } /* Put stuff in the output file. */ lprintf(f) char *f; { char buf[500]; _spr(buf,&f); lputs(buf); } /* Output a string. */ lputs(s) char *s; { while (*s) lputc(*s++); } /* Output a character. */ lputc(c) char c; { write(outfile,&c,1); /* ignore errors */ } /* Display money. Since this returns a string, we use a static string array and can make no more than 4 at a time. */ bucks_str(b) unsigned b; { static char s[4][8],i; /* string "$327.67", 4 each, plus index, */ if (++i > 3) i= 0; /* next string ... */ sprintf(s[i],"%c%d%c%02d", fido.bucks, /* dollar char, */ b / 100, /* dollars, */ fido.dec_char, /* the separator, */ b % 100); /* cents, */ return(s[i]); } /* Report an error */ error(s) char *s; { puts(s); puts("\r\n"); } clprintf(s) {} /* Return true if the FBIT is set. */ fbit(bit) int bit; { return(fido.fbits[bit / sizeof(char)] & (1 << bit % sizeof(char))); }