v24i041: Email fax-sending package, Part03/05
Rich Salz
rsalz at uunet.uu.net
Thu Mar 14 05:14:19 AEST 1991
Submitted-by: klaus u schallhorn <cnix!klaus>
Posting-number: Volume 24, Issue 41
Archive-name: faxpax/part03
#! /bin/sh
# This is a shell archive. Remove anything before this line, then feed it
# into a shell via "sh file" or similar. To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents: faxclient/fax.c faxhost/spool.fax.c sample.fax.aliases
# writefax.man
# Wrapped by rsalz at litchi.bbn.com on Wed Mar 13 14:08:02 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo ' "shar: End of archive 3 (of 5)."'
if test -f 'faxclient/fax.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'faxclient/fax.c'\"
else
echo shar: Extracting \"'faxclient/fax.c'\" \(14931 characters\)
sed "s/^X//" >'faxclient/fax.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <malloc.h>
X#include <unistd.h>
X#include <pwd.h>
X#include <string.h>
X#include <signal.h>
X#include <sys/time.h>
X#include <sys/stat.h>
X
X#include "../faxconfig.h"
X
X#ifdef NETWIDE_FAX
X#include <sys/types.h>
X#include <sys/socket.h>
X#include <netinet/in.h>
X#include <netdb.h>
X#endif
X
X
X/*
X fax.c
X
X accept fax from user.
X
X src is either a file or stdin, dest is spooler somewhere on the net.
X do some parsing && error checking before we invoke the spooler.
X allow aliases and lists for destination fax.
X argv[1] must be either a phone no [no alpha, just digits && ispunct()],
X an alias [as found in $HOME/fax.aliases], or name of a fax list file.
X
X format of alias file:
X =====================
X alias phone no ftao, starts with a colon optional comment
X ---------------------------------------------------------------------
X fred 12345678 :for the attention of fred bloggs # comment
X bill 98765
X joe 7654323 :The Lady in Pnik
X
X format of fax list
X ==================
X phone no ftao, starts with a colon opt. comment
X ------------------------------------------------------------
X 12345678 :for the attention of fred bloggs # comment
X 9274356 # no ftao
X 87340875 :z. Hd. Herrn Meier # needs it on time
X
X first released version 0.99 [desperado version]
X cleaned up Jan 21st '91,
X Copyright (C) 1991, klaus schallhorn, klaus at cnix.uucp
X
X Permission to use, copy, modify, and distribute this software
X and its documentation for any purpose and without fee is hereby
X granted, provided that the above copyright notice appear in
X all copies and that both that copyright notice and this permission
X notice appear in supporting documentation.
X
X This software is provided "as is" without express or implied warranty.
X*/
X
Xextern int errno;
X
Xchar me[80], tmpname[256], io[256], *hpfont, **phone, **ftao, *fname,
X *retfax, *home;
Xchar *get_aka(), *get_list(), *getenv();
X
Xstruct passwd *pwentry, *getpwuid();
Xint now, mail, hires, entries, alloced, save, broken;
XFILE *collect_msg();
Xvoid breakread();
X
X
Xnoalpha(s) /* allow digits and ispunct() in phone nos */
Xchar *s;
X{
X while (*s)
X {
X if (isalpha(*s))
X return(FALSE);
X ++s;
X }
X return(TRUE);
X}
Xfstbyte(s,skip)
Xchar *s;
Xint skip;
X{
X s += skip;
X while (*s && isspace(*s))
X {
X ++skip;
X ++s;
X }
X return(skip);
X}
Xvoid get_rc() /* read user defaults stashed in $HOME/.faxrc */
X{
X FILE *rc;
X char *ptr, *save_str();
X
X if (*home == '/' && *(home+1) == '\0')
X strcpy(io,"/.faxrc");
X else sprintf(io,"%s/.faxrc",home);
X
X if ((rc = fopen(io, "r")) == NULL)
X return;
X
X while (fgets(io, 248, rc) != NULL)
X {
X if (io[0] == '#')
X continue;
X
X if ((ptr = strchr(io, '\n')) != NULL)
X *ptr = '\0';
X ptr = io;
X if (!strncmp(io, "font", 4))
X {
X ptr += fstbyte(io, 4);
X hpfont = save_str(ptr);
X }
X else if (!strncmp(io, "resolution", 10))
X {
X ptr += fstbyte(io, 10);
X hires = get_bool(ptr, "high");
X }
X else if (!strncmp(io, "mail", 4)) /* mail success msg */
X {
X ptr += fstbyte(io, 4);
X mail = get_bool(ptr, "true");
X }
X else if (!strncmp(io, "now", 3)) /* send now */
X {
X ptr += fstbyte(io, 3);
X now = get_bool(ptr, "true");
X }
X else if (!strncmp(io, "save", 4)) /* save in $HOME/FaxSent */
X {
X ptr += fstbyte(io, 4);
X save = get_bool(ptr, "true");
X }
X else if (!strncmp(io, "retfax", 6)) /* return faxno */
X {
X ptr += fstbyte(io, 6);
X retfax = save_str(ptr);
X }
X }
X}
Xchar *save_str(s)
Xchar *s;
X{
X char *p;
X
X if ((p = malloc(1+strlen(s))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X exit(1);
X }
X strcpy(p, s);
X return(p);
X}
Xget_bool(from,true)
Xchar *from, *true;
X{
X if (!strncmp(from, true, strlen(true)))
X return(TRUE);
X return(FALSE);
X}
X
Xchar *get_aka(s) /* allocate and return a phone number for an alias */
Xchar *s;
X{
X char tmp[256], phoneno[80], alias[80], *ptr, *eptr;
X FILE *fp;
X int len, found;
X
X errno = 0;
X if (*home == '/' && *(home+1) == '\0')
X strcpy(tmp,"/fax.aliases");
X else sprintf(tmp,"%s/fax.aliases",home);
X
X len = strlen(s);
X found = 0;
X if ((fp = fopen(tmp, "r")) != NULL)
X {
X while (fgets(tmp, 248, fp) != NULL)
X {
X if (sscanf(tmp, "%s %s",alias,phoneno) < 2)
X continue;
X if (!strcmp(s, alias, len))
X {
X found = TRUE;
X break;
X }
X }
X fclose(fp);
X }
X if (!found) /* check if there's a file by that name */
X {
X if ((phone[0] = get_list(s)) == NULL)
X {
X fprintf(stderr,"no alias for %s, no faxlist %s\n",s,s);
X return(NULL);
X }
X return(phone[0]);
X }
X
X if ((phone[0] = malloc(1+strlen(phoneno))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X strcpy(phone[0], phoneno);
X if ((ptr = strchr(tmp, ':')) != NULL)
X {
X if ((eptr = strrchr(tmp, '#')) != NULL)
X *eptr = '\0';
X if ((ftao[0] = malloc(1+strlen(++ptr))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X strcpy(ftao[0], ptr);
X }
X ++entries;
X return(phone[0]);
X}
Xchar *get_list(name) /* read and allocate a list of phone nos */
Xchar *name;
X{
X static char tmp[256], phoneno[80], *fname0, *fname1, *ptr, *eptr;
X FILE *fp;
X int i;
X
X /* check listnames:
X if name[0] == '/', use absolute path
X else check ".", then $HOME
X */
X errno = 0;
X if (*name == '/')
X {
X fname0 = name;
X fname1 = NULL;
X }
X else
X {
X if (*home == '/' && *(home+1) == '\0')
X sprintf(tmp,"/%s",name);
X else sprintf(tmp,"%s/%s",home,name);
X fname0 = name;
X fname1 = tmp;
X }
X
X if ((fp = fopen(fname0, "r")) == NULL)
X if ((fp = fopen(fname1, "r")) == NULL)
X return(NULL);
X
X while (fgets(tmp, 248, fp) != NULL)
X {
X if (sscanf(tmp, "%s",phoneno) < 1 || tmp[0] == '#')
X continue;
X
X if ((phone[entries] = malloc(1+strlen(phoneno))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X strcpy(phone[entries], phoneno);
X
X if ((ptr = strchr(tmp, ':')) != NULL)
X {
X if ((eptr = strrchr(tmp, '#')) != NULL)
X *eptr = '\0';
X if ((ftao[entries] = malloc(1+strlen(++ptr))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X strcpy(ftao[entries], ptr);
X }
X else ftao[entries] = NULL;
X
X if (++entries == alloced) /* reshuffle base ptrs */
X {
X if ((phone = (char **)realloc(phone,
X ((alloced + 8) * sizeof(char *)))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X /* increment alloced now */
X if ((ftao = (char **)realloc(ftao,
X ((alloced += 8) * sizeof(char *)))) == NULL)
X {
X fprintf(stderr,"can't allocate memory\n");
X return(NULL);
X }
X }
X }
X fclose(fp);
X for (i=entries; i<alloced; i++)
X phone[i] = ftao[i] = NULL;
X return(phone[0]);
X}
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X#ifdef NETWIDE_FAX
X struct hostent *hent;
X struct sockaddr_in sin;
X struct servent *sent;
X int s;
X#endif
X int i, ac, piped, type;
X FILE *ofp, *faxfp;
X
X if (argc == 1)
X {
X fprintf(stderr,"fax phone [file], -opt for options\n");
X exit(1);
X }
X
X if ((home = getenv("HOME")) == NULL)
X {
X fprintf(stderr,"you're homeless\n");
X exit(1);
X }
X if (argc == 2 && (!strncmp(argv[1], "-opt", 4))) /* usage */
X usage();
X
X if ((pwentry = getpwuid(getuid())) == NULL)
X {
X fprintf(stderr,"you don't exist {%d}\n",errno);
X exit(1);
X }
X setuid(getuid());
X setgid(getgid());
X
X piped = 0;
X now = mail = hires = save = 0;
X type = ASCII;
X hpfont = retfax = fname = (char *)NULL;
X ofp = faxfp = (FILE *)NULL;
X me[0] = tmpname[0] = '\0';
X
X if ((phone = (char **)malloc(8*sizeof(char *))) == NULL)
X fprintf(stderr,"can't allocate memory");
X if ((ftao = (char **)malloc(8*sizeof(char *))) == NULL)
X fprintf(stderr,"can't allocate memory");
X for (i=0; i<8; i++)
X phone[i] = ftao[i] = NULL;
X alloced = 8;
X entries = 0;
X
X get_rc();
X
X for (ac=1; ac<argc; ac++)
X {
X if (phone[0] == NULL) /* first av[] is phone no, alias or list */
X {
X if (noalpha(argv[ac]))
X {
X phone[0] = argv[ac];
X entries = 1;
X }
X else if ((phone[0] = get_aka(argv[ac])) == NULL)
X exit(1);
X }
X else if (!strncmp(argv[ac], "-a", 2)) /* attn: fred bloggs */
X {
X ftao[0] = &argv[ac][2];
X entries = 1;
X }
X else if (!strncmp(argv[ac], "-f", 2)) /* use hp compat font */
X hpfont = &argv[ac][2];
X else if (!strncmp(argv[ac], "-h", 2)) /* high res, expensive */
X hires = TRUE;
X else if (!strncmp(argv[ac], "-l", 2)) /* low res */
X hires = FALSE;
X else if (!strncmp(argv[ac], "-m", 2)) /* mail success msg */
X mail = TRUE;
X else if (!strncmp(argv[ac], "-n", 2)) /* send now */
X now = TRUE;
X else if (!strncmp(argv[ac], "-r", 2)) /* return faxno */
X retfax = &argv[ac][2];
X else if (!strncmp(argv[ac], "-s", 2)) /* save in $HOME/FaxSent */
X save = TRUE;
X else fname = argv[ac];
X }
X
X if (phone[0] == NULL)
X {
X fprintf(stderr,"no recipient\n");
X exit(1);
X }
X if (fname == NULL)
X {
X if (isatty(fileno(stdin)))
X fprintf(stderr,"reading stdin:\n");
X if ((faxfp = collect_msg()) == NULL)
X exit(1);
X }
X else if ((faxfp = fopen(fname, "r")) == NULL)
X {
X fprintf(stderr,"can't open %s for input\n",fname);
X exit(1);
X }
X
X#ifdef NETWIDE_FAX
X /* that's me, with a little bit of luck */
X if (gethostname(me, 80))
X {
X fprintf(stderr,"I don't exist {%d}\n",errno);
X exit(1);
X }
X
X if ((hent = gethostbyname(FAXHOST)) == NULL)
X {
X fprintf(stderr,"%s not known {%d}\n",FAXHOST,errno);
X exit(1);
X }
X
X if (strcmp(me, hent->h_name)) /* FAXHOST != me */
X {
X if ((sent = getservbyname(FAXSERVER, "tcp")) == NULL)
X {
X fprintf(stderr,"%s service not known {%d}\n",FAXSERVER,errno);
X exit(1);
X }
X
X /* grab a socket */
X if ((s = socket(AF_INET, SOCK_STREAM, 0)) < 0)
X {
X fprintf(stderr," can't grab a socket {%d}\n",errno);
X exit(1);
X }
X sin.sin_family = AF_INET;
X sin.sin_port = htons(sent->s_port);
X bcopy(hent->h_addr, &sin.sin_addr, hent->h_length);
X
X /* now try to connect */
X if (connect(s, &sin, sizeof(sin)) < 0)
X {
X fprintf(stderr,"can't connect {%d}\n",errno);
X exit(1);
X }
X if ((ofp = fdopen(s, "w")) == NULL)
X {
X fprintf(stderr,"can't open socket for buffered write {%d}\n",errno);
X exit(1);
X }
X }
X else
X#endif
X {
X char ppath[128];
X
X me[0] = '\0'; /* running on faxhost */
X sprintf(ppath,"%s/%s",FAXLIB,FAXSERVER);
X if ((ofp = popen(ppath, "w")) == NULL)
X {
X fprintf(stderr,"can't pipe to %s {%d}\n",ppath,errno);
X exit(1);
X }
X piped = TRUE;
X }
X
X/* do something useful */
X
X ac = spoolfax(me, pwentry->pw_name, ofp, faxfp, type);
X
X if (piped)
X pclose(ofp);
X#ifdef NETWIDE_FAX
X else close(s);
X#endif
X if (save)
X savefax((fname==NULL)?tmpname:fname);
X
X if (tmpname[0])
X unlink(tmpname);
X exit(ac);
X}
X
Xspoolfax(host, user, outfp, infp, ftype)
Xchar *host, *user;
XFILE *outfp, *infp;
Xint ftype;
X{
X char tmp[256];
X int nread, i;
X
X if (*host)
X sprintf(tmp,"%s@%s",user,host);
X else strcpy(tmp,user);
X
X#define write_err() fprintf(stderr,"can't spool fax {%d}\n",errno)
X
X errno = 0;
X if (fprintf(outfp,"user %s\n",tmp) == EOF)
X return(write_err());
X if (fprintf(outfp,"uid %d\n",getuid()) == EOF)
X return(write_err());
X
X if (fprintf(outfp,"now %d\n",now) == EOF)
X return(write_err());
X if (fprintf(outfp,"mail %d\n",mail) == EOF)
X return(write_err());
X if (fprintf(outfp,"type %d\n",ftype) == EOF)
X return(write_err());
X if (fprintf(outfp,"hires %d\n",hires) == EOF)
X return(write_err());
X
X if (fprintf(outfp,"font %s\n",(hpfont)?hpfont:"none") == EOF)
X return(write_err());
X
X if (fprintf(outfp,"retfax %s\n",(retfax)?retfax:"none") == EOF)
X return(write_err());
X
X fprintf(outfp,"#\n"); /* marker for spoolfax */
X
X for (i=0; i<entries; i++)
X {
X if (fprintf(outfp,"phone %s",phone[i]) == EOF)
X return(write_err());
X if (ftao[i])
X {
X if (fprintf(outfp," :%s",ftao[i]) == EOF)
X return(write_err());
X }
X fprintf(outfp,"\n");
X }
X if (fprintf(outfp,"data\n") == EOF)
X return(write_err());
X
X while ((nread = fread(tmp, 1, 256, infp)) > 0)
X if (fwrite(tmp, 1, nread, outfp) != nread)
X return(write_err());
X fflush(outfp);
X return(0);
X}
Xvoid breakread()
X{
X broken = TRUE;
X}
X
XFILE *collect_msg()
X{
X static FILE *fp;
X int written, tty;
X
X broken = written = 0;
X signal(SIGINT, breakread);
X siginterrupt(SIGINT, 1); /* interrupt sys calls */
X
X tty = isatty(fileno(stdin));
X if (*home == '/' && *(home+1) == '\0')
X strcpy(tmpname,"/.infax.XXXXXX");
X else sprintf(tmpname,"%s/.infax.XXXXXX",home);
X mktemp(tmpname);
X if ((fp = fopen(tmpname, "w+")) == NULL)
X {
X fprintf(stderr,"can't create tmp file\n");
X return(NULL);
X }
X while (fgets(io, 248, stdin) != NULL)
X {
X if (broken)
X {
X written = 0;
X break;
X }
X if (io[0] == '.' && tty)
X break;
X else if (io[0] == '~' && io[1] == 'v' && tty)
X {
X fclose(fp);
X edit(tmpname);
X if ((fp = fopen(tmpname, "a+")) == NULL)
X {
X fprintf(stderr,"no tmp file ?\n");
X return(NULL);
X }
X written = (int)ftell(fp);
X fprintf(stderr,"(continue)\n");
X continue;
X }
X else if (io[0] == '~' && io[1] == 'p' && tty)
X {
X rewind(fp);
X fprintf(stderr,"-------\nMessage contains:\n");
X while (fgets(io, 248, fp) != NULL)
X fputs(io, stderr);
X fprintf(stderr,"(continue)\n");
X fseek(fp, 0L, 2);
X continue;
X }
X written += strlen(io);
X fputs(io, fp);
X }
X fclose(fp);
X if (broken || !written)
X {
X unlink(tmpname);
X fprintf(stderr,"null message, not sent\n");
X return(NULL);
X }
X if ((fp = fopen(tmpname, "r")) == NULL)
X {
X fprintf(stderr,"can't re-read your tmp file\n");
X return(NULL);
X }
X return(fp);
X}
Xsavefax(infile)
Xchar *infile;
X{
X time_t ca;
X struct tm *tml, *localtime();
X struct stat fred;
X char FaxSent[256];
X FILE *in, *sfp;
X
X time(&ca);
X tml = localtime(&ca);
X ++tml->tm_mon; /* jan is often 0 */
X
X if (*home == '/' && *(home+1) == '\0')
X {
X strcpy(FaxSent, "/FaxSent");
X sprintf(io,"/FaxSent/%s.%02d%02d%02d",
X phone[0],tml->tm_year,tml->tm_mon,tml->tm_mday);
X }
X else
X {
X sprintf(FaxSent,"%s/FaxSent",home);
X sprintf(io,"%s/FaxSent/%s.%02d%02d%02d",home,
X phone[0],tml->tm_year,tml->tm_mon,tml->tm_mday);
X }
X
X if (stat(FaxSent, &fred) && mkdir(FaxSent, 0700))
X {
X fprintf(stderr,"no directory %s\n",FaxSent);
X exit(1);
X }
X if (((sfp = fopen(io, "a")) == NULL)
X || ((in = fopen(infile, "r")) == NULL))
X {
X fprintf(stderr,"can't save your fax to %s in %s\n",
X phone[0],io);
X exit(1);
X }
X fprintf(sfp,"\n\nSPOOLED %02d.%02d.%2d %02d:%02d:%02d\n",
X tml->tm_mday,tml->tm_mon,tml->tm_year,
X tml->tm_hour,tml->tm_min,tml->tm_sec);
X
X while (fgets(io, 250, in) != NULL)
X fputs(io, sfp);
X fclose(in);
X fclose(sfp);
X}
Xedit(what)
Xchar *what;
X{
X char *ed;
X
X if ((ed = getenv("EDITOR")) == NULL)
X ed = "/usr/ucb/vi";
X
X sprintf(io, "%s %s\n",ed,what);
X system(io);
X}
Xusage()
X{
X char tmp[40];
X
X puts("fax options:");
X puts("-a\"for the attention of fred bloggs\"");
X puts("-h use high resolution");
X puts("-f use an hp ljet compatible font");
X puts("-n send it now");
X puts("-m confirm result by mail when sent");
X puts("-r specify return fax no");
X if (*home == '/' && *(home+1) == '\0')
X strcpy(tmp, "/FaxSent");
X else sprintf(tmp,"%s/FaxSent",home);
X printf("-s save message in %s/phoneno.date\n",tmp);
X puts("if called without a file name, fax reads stdin");
X exit(1);
X}
END_OF_FILE
if test 14931 -ne `wc -c <'faxclient/fax.c'`; then
echo shar: \"'faxclient/fax.c'\" unpacked with wrong size!
fi
# end of 'faxclient/fax.c'
fi
if test -f 'faxhost/spool.fax.c' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'faxhost/spool.fax.c'\"
else
echo shar: Extracting \"'faxhost/spool.fax.c'\" \(14959 characters\)
sed "s/^X//" >'faxhost/spool.fax.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <string.h>
X#include <time.h>
X#include <ctype.h>
X#include <unistd.h>
X
X#include "../faxconfig.h"
X
X/*
X spool.fax
X
X spool faxes,
X read incoming jobs,
X split into straight through jobs and jobs where that
X need special handling due to "f.t.a.o. fred bloggs"
X convert input -> pbm -> g3
X if straight through jobs > 1 && phone_nos > 1,
X split into batches of size (phone_nos/faxmodems)
X
X this looks [and is] rather messy due to the last minute addition
X of special treatment of those guys that doen't have their own
X fax machine but want their fax addressed [marked] "for the
X attention of whatever". The quick fix I made works, but
X the resulting mess is barely understandable [to me, that is].
X
X I'm gonna rework him as soon as there's some time - I probably
X have to anyway when I add prettier file types. Currently
X the only thing that works as advertised is files pushed through
X texttopbm. spooling faxes with pbm files should work, but I haven't
X had the time to test these [hey, I'm doing this in my spare time].
X
X first released version 0.99 [desperado version]
X cleaned up Jan 22nd '91,
X Copyright (C) 1991, klaus schallhorn, klaus at cnix.uucp
X
X Permission to use, copy, modify, and distribute this software
X and its documentation for any purpose and without fee is hereby
X granted, provided that the above copyright notice appear in
X all copies and that both that copyright notice and this permission
X notice appear in supporting documentation.
X
X This software is provided "as is" without express or implied warranty.
X*/
X
X
Xlong xpos;
Xint type, hires, pages, blah, mail;
Xchar tmp_nam[256], user[80], retfax[80], font[256], Ftao[256];
Xchar io[1024], Xfile[256], Dfile[256];
Xchar oldname[256], newname[256], linkbase[256], linkto[256], dataname[256];
X#ifdef JOBID
X jobid[80];
Xstruct tm *tml, *localtime();
X#endif
X
Xextern int errno;
X
Xchk_config()
X{
X FILE *cfg;
X char buf[256];
X int i;
X
X sprintf(buf, "%s/fax.config", FAXLIB);
X errno = 0;
X if ((cfg = fopen(buf, "r")) == NULL)
X {
X unlink(Xfile);
X unlink(Dfile);
X fax_log(ERROR, "spool.fax: can't read %s\n",buf);
X mailexit(user);
X }
X i = 0;
X while (fgets(buf, 254, cfg) != NULL)
X {
X if (buf[0] == '#')
X continue;
X if (!strncmp(buf, "device", 6))
X ++i;
X }
X fclose(cfg);
X return(i);
X}
X
Xmain()
X{
X FILE *fp;
X int nread, phones, tread, count, ftaofs;
X time_t now;
X char *ptr;
X
X phones = count = ftaofs = tread = errno = 0;
X user[0] = retfax[0] = font[0] = Ftao[0] = '\0';
X
X if (chdir(FAXSPOOL)) /* quick one, job done */
X {
X fax_log(ERROR,"spool.fax: can't cd to %s\n",FAXSPOOL);
X mailexit(FAXADMIN);
X }
X
X (void)time(&now);
X
X#ifdef JOBID
X tml = localtime(&now);
X ++tml->tm_mon; /* jan is 0 */
X
X sprintf(jobid, "%02d%02d-%d",tml->tm_mon,tml->tm_mday,getpid());
X#endif
X sprintf(tmp_nam,"%s/X.faxXXXXXX",FAXSPOOL);
X mktemp(tmp_nam);
X strcpy(Xfile, tmp_nam);
X
X if ((fp = fopen(tmp_nam, "w")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't create X.file\n");
X mailexit(FAXADMIN);
X }
X
X chmod(tmp_nam, FAXFMODE);
X
X fprintf(fp,"spooled %ld\n",(long)now);
X fprintf(fp,"tries %3d\n",0);
X
X while (fgets(io, 254, stdin) != NULL)
X {
X if (!count)
X {
X if (io[0] == 'f') /* font */
X {
X ptr = io;
X while (*ptr && (!isspace(*ptr)))
X ++ptr;
X ++ptr;
X if (strncmp(ptr, "none", 4))
X strcpy(font, ptr); /* else use default */
X }
X else if (io[0] == 'h') /* hires */
X {
X ptr = io;
X while (*ptr && (!isdigit(*ptr)))
X ++ptr;
X hires = atoi(ptr);
X }
X else if (io[0] == 'm') /* hires */
X {
X ptr = io;
X while (*ptr && (!isdigit(*ptr)))
X ++ptr;
X mail = atoi(ptr);
X }
X else if (io[0] == 'r') /* return faxno */
X {
X ptr = io;
X while (*ptr && (!isspace(*ptr)))
X ++ptr;
X strcpy(retfax, ++ptr);
X }
X else if (io[0] == 't') /* type */
X {
X ptr = io;
X while (*ptr && (!isdigit(*ptr)))
X ++ptr;
X type = atoi(ptr);
X }
X else if (io[0] == 'u' && (!user[0])) /* user */
X {
X ptr = io;
X while (*ptr && (!isspace(*ptr)))
X ++ptr;
X strcpy(user, ++ptr);
X }
X else if (io[0] == '#')
X {
X xpos = ftell(fp);
X count = TRUE;
X }
X }
X else
X {
X if (io[0] == 'd') /* data follows */
X break;
X else if (io[0] == 'p') /* last minute fix */
X { /* forgot ftao for 1off faxes */
X ++phones; /* added to faxconvert */
X if ((ptr = strchr(io, ':')) != NULL)
X {
X ftaofs++;
X strcpy(Ftao, (ptr+1));
X }
X }
X }
X fputs(io, fp);
X }
X sprintf(tmp_nam,"%s/D.faxXXXXXX",FAXSPOOL);
X mktemp(tmp_nam);
X strcpy(Dfile, tmp_nam);
X
X /* make a note of D.file name in X.file */
X fprintf(fp,"data %s\n",tmp_nam);
X fflush(fp);
X if (ferror(fp))
X {
X unlink(Xfile);
X fax_log(ERROR,"spool.fax: can't write X.file\n");
X mailexit(FAXADMIN);
X }
X fclose(fp);
X
X if ((!user[0]) || (!phones))
X {
X unlink(Xfile);
X fax_log(ERROR,"spool.fax: doesn't look like a fax job to me\n");
X mailexit(FAXADMIN);
X }
X
X if ((fp = fopen(tmp_nam, "w")) == NULL)
X {
X unlink(Xfile);
X fax_log(ERROR,"spool.fax: can't create D.file\n");
X mailexit(user);
X }
X chmod(tmp_nam, FAXFMODE);
X
X while ((nread = fread(io, 1, 256, stdin)) > 0)
X {
X tread += nread;
X if (fwrite(io, 1, nread, fp) != nread)
X {
X unlink(Xfile);
X fax_log(ERROR,"spool.fax: can't write D.file\n");
X mailexit(user);
X }
X }
X fflush(fp);
X if ((!tread) || ferror(fp)) /* empty file ? */
X {
X unlink(Xfile);
X unlink(Dfile);
X fax_log(ERROR,"spool.fax: can't write D.file, rcvd bytes %d\n",tread);
X mailexit(user);
X }
X fclose(fp);
X
X if ((nread = fork()) < 0)
X {
X unlink(Xfile);
X unlink(Dfile);
X fax_log(ERROR,"spool.fax: can't fork to convert files\n");
X mailexit(user);
X }
X else if (!nread) /* child */
X {
X if (setpgrp(0,0))
X {
X fax_log(ERROR, "spool.fax: can't create new prgp\n");
X mailexit(FAXADMIN);
X }
X if (setuid(geteuid()))
X {
X fax_log(ERROR, "spool.fax: can't setuid(geteuid())\n");
X mailexit(FAXADMIN);
X }
X if (setgid(getegid()))
X {
X fax_log(ERROR, "spool.fax: can't setgid(getegid())\n");
X mailexit(FAXADMIN);
X }
X
X if (!share_fax(Xfile,Dfile,phones,ftaofs))
X#ifndef JOBID
X fax_log(0, "spool.fax: user %s, %d pages, %d reciepient%c\n",
X user, pages, phones, (phones > 1)?'s':' ');
X#else
X fax_log(0, "spool.fax: jobid %s, user %s, %d pages, %d reciepient%c\n",
X jobid, user, pages, phones, (phones > 1)?'s':' ');
X
X if (mail)
X {
X sprintf(io,"echo \"the job id of your spooled fax is %s \" | mail %s",
X jobid,user);
X system(io);
X }
X#endif
X
X }
X exit(0);
X}
Xshare_fax(xnam,dnam,phones,oneoffs)
Xchar *xnam,*dnam;
Xint phones, oneoffs;
X{
X FILE *X, *x;
X char name[256], io[1024], *head;
X int i, split, batches, done, per_batch, devices;
X
X /* split a job into packets
X check for jobs with special headers [ftao], do separately,
X split the balance into packets so that load is distributed
X evenly between faxmodems
X */
X
X devices = chk_config(); /* or dead */
X
X if (phones == 1) /* doesn't need much splitting */
X return(faxconvert(xnam,dnam,0));
X else Ftao[0] = '\0'; /* last minute fix, spoolfax is due for a rewrite */
X
X if (oneoffs) /* special handling */
X phones -= xoneoffs(xnam,dnam);
X
X /* integer divide of 7 faxes / 10 modems == 0 */
X per_batch = max(1,(phones/devices));
X errno = 0;
X if ((X = fopen(xnam, "r")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't open X.file %s\n",xnam);
X mailexit(user);
X }
X if ((head = malloc((int)xpos)) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't allocate memory\n");
X mailexit(user);
X }
X if (fread(head, 1, (int)xpos, X) != (int)xpos)
X {
X fax_log(ERROR,"spool.fax: can't read X.file %s\n",xnam);
X mailexit(user);
X }
X
X for (done=batches=split=0;;)
X {
X if (done || (split == phones))
X break;
X
X sprintf(name, "%s%d",xnam,batches);
X if ((x = fopen(name, "w")) == NULL) /* buggered */
X { /* rm all batches */
Xbuggered:
X for (i=0; i<batches; i++) /* but leave main job */
X { /* for manual cleanup */
X sprintf(name, "%s%d",xnam,i);
X unlink(name);
X }
X unlink(xnam);
X unlink(dnam);
X fax_log(ERROR,"spool.fax: serious problems during split %s\n",xnam);
X mailexit(user);
X }
X
X chmod(name, FAXFMODE);
X if (fwrite(head, 1, (int)xpos, x) != (int)xpos)
X goto buggered;
X
X for (i=0; i<per_batch; )
X {
X if (fgets(io, 256, X) == NULL)
X goto buggered;
X if (io[0] == '#' || (strchr(io, ':') != NULL))
X continue;
X if (!strncmp(io, "data", 4)) /* no more phone nos */
X {
X if (!i)
X unlink(name);
X done = 1;
X break;
X }
X fputs(io, x);
X ++split;
X ++i;
X }
X fprintf(x,"data %s\n",dnam);
X fflush(x);
X if (ferror(x))
X goto buggered;
X fclose(x);
X batches += (i > 0);
X }
X fclose(X);
X unlink(xnam); /* passed on simply as a "basename" */
X return(faxconvert(xnam,dnam,batches));
X}
Xxoneoffs(xnam,dnam)
Xchar *xnam,*dnam;
X{
X FILE *X, *D, *x, *d;
X char ftao[128], newxnam[256], newdnam[256], txnam[256], tdnam[256],
X *head, *ptr;
X int split, nread;
X
X errno = 0;
X if ((D = fopen(dnam, "r")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't open D.file %s for ftao\n",dnam);
X mailexit(user);
X }
X if ((X = fopen(xnam, "r")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't open X.file %s for ftao\n",xnam);
X mailexit(user);
X }
X /* read header of X file */
X if ((head = malloc((int)xpos)) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't allocate memory\n");
X mailexit(user);
X }
X if (fread(head, 1, (int)xpos, X) != (int)xpos)
X {
X fax_log(ERROR,"spool.fax: can't read X.file %s for ftao\n",xnam);
X mailexit(user);
X }
X
X split = 0; /* find jobs with phone 1234 :f.t.a.o fred */
X sprintf(txnam,"%s/X.fxXXXXXX",FAXSPOOL);
X mktemp(txnam);
X sprintf(tdnam,"%s/D.fxXXXXXX",FAXSPOOL);
X mktemp(tdnam);
X
X while (fgets(io, 256, X) != NULL)
X {
X if (io[0] == '#' || ((ptr = strchr(io, ':')) == NULL))
X continue;
X
X sprintf(newxnam, "%s%d", txnam,split);
X errno = 0;
Xbuggered:
X if ((x = fopen(newxnam, "w")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't create %s for load sharing\n",newxnam);
X mailexit(user);
X }
X chmod(newxnam, FAXFMODE);
X
X if (fwrite(head, 1, (int)xpos, x) != (int)xpos)
X goto buggered;
X
X strcpy(ftao, (ptr+1)); /* save whats after ptr */
X *ptr = '\0'; /* zero out at ':' */
X
X /* io now contains just the phone number */
X /* ftao contains now "f.t.a.o. fred" */
X
X /* make new data name */
X sprintf(newdnam,"%s%d", tdnam,split);
X
X fprintf(x,"%s\ndata %s\n",io,newdnam);
X fflush(x);
X if (ferror(x))
X goto buggered;
X fclose(x);
X
X errno = 0;
X if ((d = fopen(newdnam, "w")) == NULL)
X goto buggered;
X chmod(newdnam, FAXFMODE);
X
X fprintf(d,"%s\n",ftao); /* make this part of the fax file */
X
X /* add the balance */
X while ((nread = fread(io, 1, 1024, D)) > 0)
X fwrite(io, 1, nread, d);
X fflush(d);
X if (ferror(d))
X goto buggered;
X fclose(d);
X faxconvert(newxnam, newdnam, 0); /* or die */
X ++split;
X rewind(D);
X }
X fclose(X);
X fclose(D);
X free(head);
X return(split);
X}
Xfaxconvert(xn, dn, batches)
Xchar *xn, *dn;
Xint batches;
X{
X int j, batch;
X char scratchbuf[256], tmp[256], *ptr;
X FILE *p, *fp;
X
X /* do D.files [data] first, if they're ok, do Xfiles */
X /* sendfax scans directory for x.files only */
X /* in case of multiple batches convert data once, then make links */
X
X batch = 0;
X do /* at least once */
X {
X if (!batch) /* first time around */
X {
X strcpy(oldname, dn);
X strcpy(newname, dn);
X ptr = strrchr(newname, '/');
X *(ptr+1) = 'd';
X strcpy(linkto, newname);
X strcat(newname, "0");
X strcpy(linkbase, newname);
X
X /* strip newlines */
X if ((ptr = strchr(font, '\n')) != NULL)
X *ptr = '\0';
X if ((ptr = strchr(user, '\n')) != NULL)
X *ptr = '\0';
X if ((ptr = strchr(retfax, '\n')) != NULL)
X *ptr = '\0';
X
X switch(type)
X {
X case ASCII:
X errno = 0;
X if ((fp = fopen(oldname, "r")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't read textfile %s for conversion\n",oldname);
X mailexit(user);
X }
X sprintf(scratchbuf,"%s/texttopbm %s %s%s -o%s.pbm",
X LOCALBIN,
X (hires)?"-h":"",
X (font[0])?"-f":"",
X (font[0])?font:"",
X newname);
X
X if ((p = popen(scratchbuf, "w")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't pipe to texttopbm with %s\n",scratchbuf);
X mailexit(user);
X }
X
X if (Ftao[0]) /* make this part of the fax file */
X fprintf(p,"%s\n",Ftao);
X fprintf(p,"fax from %s",user);
X if (strncmp(retfax, "none", 4))
X fprintf(p,", fax # %s - ",retfax);
X else fputc(' ',p);
X timestamp(p,(time_t)0L);
X
X fprintf(p,"\n\n");
X
X while (fgets(scratchbuf, 254, fp) != NULL)
X fputs(scratchbuf, p);
X
X fflush(p);
X if (ferror(p))
X {
X fax_log(ERROR,"spool.fax: can't unplump from texttopbm with %s\n",scratchbuf);
X mailexit(user);
X }
X pclose(p);
X fclose(fp);
X unlink(oldname); /* rm text input file */
X
X /* have one or more pbm files now */
X for (pages=0;;pages++)
X {
X sprintf(tmp, "%s.pbm.%d",newname,pages);
X if (access(tmp, R_OK))
X break;
X sprintf(scratchbuf,"%s/pbmtog3 -s <%s >%s.g3.%d",LOCALBIN,tmp,newname,pages);
X if (system(scratchbuf))
X {
X fax_log(ERROR,"spool.fax: can't execute pbmtog3 with %s\n",scratchbuf);
X mailexit(user);
X }
X unlink(tmp); /* get rid of pbm file */
X sprintf(tmp, "%s.g3.%d",newname,pages);
X chmod(tmp, FAXFMODE);
X }
X strcpy(dataname, linkbase);
X break;
X
X case PBM:
X sprintf(scratchbuf,"pbmtog3 -s <%s >%s.g3.0",oldname,newname);
X errno = 0;
X if (system(scratchbuf))
X {
X fax_log(ERROR,"spool.fax: can't execute pbmtog3 with %s\n",scratchbuf);
X mailexit(user);
X }
X unlink(oldname); /* again: get rid of pbm file */
X sprintf(tmp,"%s.g3.0",newname);
X chmod(tmp, FAXFMODE);
X pages = 1;
X strcpy(dataname, newname);
X break;
X }
X }
X else
X {
X for (j=0; j<pages; j++)
X {
X sprintf(dataname, "%s%d.g3.%d",linkto,batch,j);
X sprintf(scratchbuf, "%s.g3.%d",linkbase,j);
X if (link(scratchbuf, dataname))
X {
X fax_log(ERROR,"spool.fax: can't link %s to %s\n",linkbase,tmp);
X mailexit(user);
X }
X }
X sprintf(dataname, "%s%d",linkto,batch);
X }
X
X
X /* now do the X.file */
X if (batches) /* xn is basename only in case of batches */
X sprintf(oldname, "%s%d", xn, batch);
X else strcpy(oldname, xn);
X
X strcpy(newname, oldname);
X ptr = strrchr(newname, '/');
X *(ptr+1) = 'x';
X if ((p = fopen(oldname, "r")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't open %s after splitting D.files\n",oldname);
X mailexit(user);
X }
X if ((fp = fopen(newname, "w")) == NULL)
X {
X fax_log(ERROR,"spool.fax: can't create new %s\n",newname);
X mailexit(user);
X }
X chmod(newname, FAXFMODE);
X
X while (fgets(scratchbuf, 126, p) != NULL)
X {
X if (!strncmp(scratchbuf, "data", 4))
X fprintf(fp,"data %s\n",dataname);
X else fputs(scratchbuf, fp);
X }
X fprintf(fp,"pages %d\n",pages);
X#ifdef JOBID
X fprintf(fp,"jobid %s\n",jobid);
X#endif
X fflush(fp);
X if (ferror(fp))
X {
X fax_log(ERROR,"spool.fax: can't write new %s\n",newname);
X mailexit(user);
X }
X fclose(fp);
X unlink(oldname);
X } while (++batch < batches);
X
X unlink(dn);
X return(0);
X}
END_OF_FILE
if test 14959 -ne `wc -c <'faxhost/spool.fax.c'`; then
echo shar: \"'faxhost/spool.fax.c'\" unpacked with wrong size!
fi
# end of 'faxhost/spool.fax.c'
fi
if test -f 'sample.fax.aliases' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'sample.fax.aliases'\"
else
echo shar: Extracting \"'sample.fax.aliases'\" \(290 characters\)
sed "s/^X//" >'sample.fax.aliases' <<'END_OF_FILE'
X# sample fax.aliases file
X# alias phone no ftao, starts with a colon optional comment
X#---------------------------------------------------------------------
Xfred 12345678 :for the attention of fred bloggs # comment
Xbill 98765
Xjoe 7654323 :The Lady in Pink # should see her
END_OF_FILE
if test 290 -ne `wc -c <'sample.fax.aliases'`; then
echo shar: \"'sample.fax.aliases'\" unpacked with wrong size!
fi
# end of 'sample.fax.aliases'
fi
if test -f 'writefax.man' -a "${1}" != "-c" ; then
echo shar: Will not clobber existing file \"'writefax.man'\"
else
echo shar: Extracting \"'writefax.man'\" \(20046 characters\)
sed "s/^X//" >'writefax.man' <<'END_OF_FILE'
X>From cat!fulcrum!ukc.ac.uk!mcsun.eu.net!mcsun.uucp!aimed!nick Thu Dec 13 15:41:13 1990
XReturn-Path: <cat!fulcrum!ukc.ac.uk!mcsun.eu.net!mcsun.uucp!aimed!nick>
XSubject: Re: writefax.man
XTo: klaus u schallhorn <klaus at cnix.uucp>
XDate: Wed, 12 Dec 90 16:49:33 EST
X>From: Nick Pemberton <aimed!nick>
XX-Mailer: ELM [version 2.3 PL6]
XSender: uucp.mcsun!aimed!nick at mcsun.eu.net
X
X> I've just studied the document you posted to various newsgroups
X> and compared it to a document I received from a faxmodem
X> manufacturer, that asked me to sign a non disclosure agreement
X> in order to get what you posted. ************************
X
XThat sounds reasonably scary....
X
X>
X> Can you let me know the source of the document and if it's
X> "secret" as well or whether I've been done. I'd really like to know.
X
XI downloaded it from the Zoom Technologies BBS, at 1-617-451-5284. Zoom
Xare the folks who manufacture the modem - the chipset must be Sierra's.
X
XAs you can see from the document, there are no restrictive covenants
Xon it, and zoom never mentioned such restrictions. I'd question having to
Xsign such an agreement.
X
XNick.
X
X--
XNick Pemberton uucp: !{lsuc, uunet!mnetor}!aimed!nick
XAIM, Inc bus: (416) 429-1085
XToronto, Ontario, Canada Home: (416) 690-0647
X
X
X>From cat.fulcrum.bt.co.uk!uzi-9mm.fulcrum.bt.co.uk!axion!ukc!mcsun!sunic!uupsi!rpi!zaphod.mps.ohio-state.edu!wuarchive!cs.utexas.edu!utgpu!utzoo!mnetor!geac!aimed!nick Wed Dec 12 10:38:53 GMT 1990
XArticle: 112 of comp.dcom.modems
XXref: cnix alt.fax:79 comp.dcom.modems:112 comp.periphs:92
XPath: cnix!cat.fulcrum.bt.co.uk!uzi-9mm.fulcrum.bt.co.uk!axion!ukc!mcsun!sunic!uupsi!rpi!zaphod.mps.ohio-state.edu!wuarchive!cs.utexas.edu!utgpu!utzoo!mnetor!geac!aimed!nick
X>From: nick at aimed.UUCP (Nick Pemberton)
XNewsgroups: alt.fax,comp.dcom.modems,comp.periphs
XSubject: Here is WRITEFAX.MAN, details on ZOOM modem programming
XMessage-ID: <8658 at aimed.UUCP>
XDate: 8 Dec 90 00:30:56 GMT
XOrganization: AIM, Inc, Toronto, Ontario
XLines: 496
X
XWell, after much waiting, dialing, etc, I finally have a copy of
XWRITEFAX.MAN, which is a guide to programming the ZOOM MX 2400S modem,
Xamongst others. I have had a number of requests for this file, so I
Xthought I'd post it (its not that large anyway....)
X
X------------snip----------snip--------snip---------
X
X SendFax Application Software Interface Specification Rev 2
X
X
X
XContents
X
X1.0 Introduction
X
X2.0 Physical interface
X
X3.0 Command set
X
X4.0 Data format
X
X5.0 Example sessions
X
X
X
X
X.pa
X.he SendFax Application Software Interface Specification
X
X
X
X1.0 Introduction
X
XThis document defines the specifications for the application
Xsoftware interface to a PC Fax/Modem board incorporating Sierra's
XSC11046, 2400 bps modem with Send only Fax at 4800 bps (SendFax)
Xchip.
X
XThe device is intended to be used in internal cards for the IBM
XPC or compatible computers or for use in standalone modems
Xinterfacing to any computer using a standard RS232 port.
X
XFunctions and commands are defined to allow an extension to Fax
Xreceive mode in the future.
X
XThe Fax/Modem board is designed such that it appears to the PC as
Xa serial port. The address of the board is user selectable to be
Xone of four ports, COM1, COM2, COM3 or COM4. The DCE hardware
Xmakes and terminates calls, manages the communications session
Xand transmits image data in accordance with the procedures
Xdefined in the CCITT recommendation T.30. The image data is in
Xmodified Huffman compressed format as described in the CCITT
Xrecommendation T.4.
X
XThe application software running in the DTE will provide the
Xfunctions of user interface, conversion of user data files in
Xvarious formats to fax format per CCITT T.4 specification and
Xtransfer of data to the DCE for modulation according to the
Xprotocol defined in this document.
X
X
X.pa
X
X
X
X2.0 Physical Interface
X
X2.1 Internal PC version
X
XThe hardware appears to the PC as a serial port at an address
Xthat is user selectable to be one of four ports. Table 1 lists
Xthe addresses and interrupt levels for various port selections.
X
XTo the application software, the hardware appears as an
X8250/16450 type UART. The application software writes or reads
Xdata to and from registers in the UART. Table 2 shows the
Xvarious registers and their addresses. DTR and OUT2 bits in MCR
Xmust be set before communicating with the hardware. The software
Xsends commands and data to the hardware by writing to the
Xtransmitter holding register (THR) in the UART. Data can be
Xwritten to THR when THRE and/or TSRE bits in LSR are set. It
Xreceives responses or data from the hardware by reading the
Xreceive buffer register (RBR). Software should first check the
XLSR to see if DR bit is set indicating data is available in RBR.
XInterrupts can also be used to inform the software that
Xtransmitter is empty or data is available in the receiver. Refer
Xto the 8250/16450 data sheet or the IBM technical reference
Xmanual for more information on programming, reading and writing
Xto the UART.
X
X2.2 RS232 Standalone version
X
XThe UART in the SC11011 controller can be configured by changing
Xone bit (Bit3) in the code to present its serial port to the
Xoutside world. To enable the DTR control function, the AT&D2
Xcommand must be issued befoer entering the fax mode.
X
XThe standard 2400 bps modem command set is extended for the Fax
Xapplication using a format of AT#F... These commands were developed
Xin accordance with the original set proposed in the TIA T30 committee
Xin spring of 1989. Sierra is continuing to work with the T29.2 committee
Xto define teh ultimate standard command set for fax and data modems.
X
XIn the idle state the hardware is in the normal 2400 bps modem
Xmode. The UART is programmed at speeds from 300 to 2400 bps to
Xcommunicate with the hardware. In the fax mode, the DTE is set to 19.2Kbps.
XFour states are defined to allow a clear understanding of the
Xhardware control process:
X
X 1. Modem command mode: AT commands accepted
X 2400 bps max
X modem data mode entered online
X
X 2. Modem data mode: +++ escapes to modem command mode
X 2400 bps max
X
X 3. Fax command mode: entered from modem command mode
X with #F1
X 19.2 kbps only
X
X 4. Fax data mode: commands and data at 19.2kbps only
X return to fax command by:
X sending command #F
X end of call/ call disconnect
X dropping DTR
X
XAfter power-up the hardware is in the normal 2400 bps modem
Xcommand mode.
X
XA special command puts the hardware in the Fax mode. Once in
Xthe Fax mode, the UART must be programmed for 19,200 bps data
Xrate, 8 bits and no parity. This is because the image data must
Xbe sent to the hardware at a rate that is faster than line
Xtransmission rate. For 4800 bps synchronous transmission line
Xrate, the UART rate must be at least 9600 bps. To allow for the
Xfuture accomodation of 9600 bps line transmission rate, the UART
Xspeed in Fax mode is fixed at 19,200 bps. The UART speed is
Xprogrammed by setting the DLAB bit in the modem control register
X(MCR) and by writing appropriate values to the divisor latches
XDLL and DLM. Table 3 provides the DLL, DLM speed selection
Xvalues. Flow control (XON/XOFF or RTS/CTS) is required to
Xsynchronize the flow of information between the DTE and the DCE
Xduring image data transmission and HDLC frame reception. In the
Xdata transmission mode, software must not send data when CTS bit
Xis off or when <XOFF> is received. Data can be sent after
Xreceiving <XON> or when CTS bit is set.
X
X.pa
X
X
X
XTable 1. COM port addresses
X
XCOM1 3F8 - 3FF IRQ4
XCOM2 2F8 - 2FF IRQ3
XCOM3 3E8 - 3EF IRQ4
XCOM4 2E8 - 2EF IRQ3
X
XTable 2.1 UART registers
X
XI/O decode (Hex)
XCOM1 COM2 COM3 COM4 R/W DLAB Register
X----------------------------------------------------------------
X3F8 2F8 3E8 2E8 W 0 THR
X3F8 2F8 3E8 2E8 R 0 RBR
X3F8 2F8 3E8 2E8 R/W 1 DLL
X3F9 2F9 3E9 2E9 R/W 1 DLM
X3F9 2F9 3E9 2E9 R/W 0 IER
X3FA 2FA 3EA 2EA R 0 IIR
X3FB 2FB 3EB 2EB R/W 0 LCR
X3FC 2FC 3EC 2EC R/W 0 MCR
X3FD 2FD 3ED 2ED R/W 0 LSR
X3FE 2FE 3EE 2EE R/W 0 MSR
X
XTable 2.2 Register bit defintions
X
XRegister 7 6 5 4 3 2 1 0
X---------------------------------------------------------------
XTHR -------- TRANSMIT DATA (DLAB = 0) ---------
XRBR -------- RECEIVE DATA (DLAB = 0) ---------
XDLL ---- DIVISOR LATCH LS BYTE (DLAB = 1) -----
XDLM ---- DIVISOR LATCH MS BYTE (DLAB = 1) -----
XIER 0 0 0 0 MSI LSI THRE DA
XIIR 0 0 0 0 0 ID1 ID0 IP/
XLCR DLAB SB SP EPS PEN STB WLS1 WLS0
XMCR 0 0 0 LOOP OUT2 OUT1 RTS DTR
XLSR 0 TSRE THRE BI FE PE OR DR
XMSR RLSD RI DSR CTS DRLS TERI DDSR DCTS
X---------------------------------------------------------------
X
XTable 3. Speed selection table
X
XSPEED (BPS) DLM (HEX) DLL (HEX)
X----------------------------------------
X300 01 80
X1200 00 60
X2400 00 30
X4800 00 18
X9600 00 0C
X19200 00 06
X----------------------------------------
X
X
X
X3.0 Command Set
X
XExtensions to the Hayes AT command set for Fax mode operation are
Xdefined in this section.
X
XGeneral
X
X1) All extended commands start with the # prefix. This represents
Xa major change from previous versions which utilized the +
Xprefix. The change was made to provide upward compatibility with
Xfuture TIA command sets which are expected to use the + symbol.
XFor the immediate future, the firmware will accept either prefix.
X
X2) All extended commands have only one alpha character followed
Xby a numeric value in the range of decimal 0 to 255. Value 0 may
Xbe omitted.
X
X3) Fax mode assumes XON/XOFF or CTS flow control in data mode.
X&D2 command must be issued for DTR controlled abort.
X
X4) Once the hardware enters the Fax mode, it will remain in Fax
Xmode ( and accept commands at 19.2 kbps ) until one of following
Xoccurs :
X
X a) software issues a #F request to return to command mode
X b) a call disconnect frame is received
X c) application software issues an abort by dropping DTR
X
XCOMMANDS
X
X
X#Bn Speed control
X
X#B/B0 Reserved
X#B1 Reserved
X#B2 Reserved for V.23
X#B3 Reserved for V.23
X#B4 Fax transmission speed of 2400 bps
X#B5 Fax transmission speed of 4800 bps
X#B6 Fax transmission speed of 7200 bps
X#B7 Fax transmission speed of 9600 bps
X
XThis command is used to specify the initial speed at which the
Xhardware will attempt to connect to the remote Fax machine. For
Xthe SC11046 based hardware this will normally be 4800 bps, so B5
Xcommand will be used. However, the user at his option can
Xspecify a lower initial speed of 2400 bps by issuing B4. If the
Xhigher initial speed is specified, the hardware will attempt to
Xestablish connection at the higher speed and will fallback to the
Xlower speed if unsuccessful.
X
X
X
X
X
X
XEn Received frame display format selection
X
XE/E0 Disable display of received HDLC frames
XE1 Display frame in binary format
XE2 Display frame in 2 digit ASCII Hex format
X
X
X
XFn Mode control
X
XF/F0 Return to normal modem mode (300 to 2400 bps data rate)
XF1 Enter Fax mode (19,200 bps data rate)
X
X
XKn DTE flow control
X
XK/K0 Disable flow control
XK3 Enable CTS flow control
XK4 Enable XON/XOFF flow control
X
XMn Speaker Control
XM0 Speaker Always Off
XM1 Speaker Off after Connect Message
XM2 Speaker Always On
XM3 Speaker Off during Dial
X
XPn Number of pages to be transmitted (n = 1 to 255)
X
X
XRn Resolution control
X
XR/R0 Send document with normal resolution
XR1 Send document with fine resolution
X
X
XTn Test modes
X
XT/T0 End test mode
XT1 Enter test mode 1. This mode is used to dial a remote
X Fax machine and automatically send a message stored
X in EPROM.
X.pa
X
X
XFAX result codes
X
XDuring the Fax session the hardware will report the status of the
Xcall with result codes. An action by the software may or may not
Xbe necessary depending on the response.
X
XAll the normal Hayes result codes will also be reported.
X
XVerbose Digit Usage
X
X
XCED a Ansertone detected
X
XCFR g Remote machine confirmation to receive
X
XCONNECT 2400/FAX w Connection speed 2400 bps
X
XCONNECT 4800/FAX x Connection speed 4800 bps
X
XCONNECT 7200/FAX y Connection speed 7200 bps
X
XCONNECT 9600/FAX z Connection speed 9600 bps
X
XCRC ERROR e Error in received frame
X
XCRP c Repeat request
X
XCSI - Remote machine Identification
X
XDCN d Disconnect
X
XDIS b Remote machine capabilities frame
X
XFTT f Failure to train
X
XINVALID FRAME i Received frame is invalid
X
X MCF m Message received OK
X
XRTN h Message not received OK
X
XRTP j Retrain positive
X.pa
X
X
X4.0 Data format
X
XThe Transmit Subscriber Identification data encoded in the T.30
Xnegotiation will be taken from the nvram location Z3.
X
X
XImage data will be in compressed format with one dimensional
Xcoding rules in accordance with the CCITT specification T.4.
XData will be coded assuming the receiving Fax machine is capable
Xof a scan time of 0 milliseconds per line. Each line of data
Xmust terminate with a minimum of 3 bytes of zeroes before the
XEOL sequence. The zeroes must be byte aligned. The software
Xwill detect the zero bytes at the end of each line and fill
Xin the required number of zeroes based on the speed of
Xconnection and the minimum scan time per line specified by the
Xreceiving Fax machine. Data must be coded with MSB the first
Xbit to be transmitted from DTE to modem.The modem sends the
Xdata LSB first to the phone line.. Transmission of data
Xwill be synchronized using flow control (XON/XOFF or CTS). After
Xsending the last byte of page data, software will wait for a
Xresponse from the hardware before issuing a command or sending
Xdata for the next page.
X
X5.0 Example sessions
X
XIn the following example sessions, the response is enclosed
Xwithin <> brackets. The defaults are B3 (4800 bps), P1 (single
Xpage), R0 (normal resolution) and T0 (no test mode).
X
XEach command line terminates with a CRLF, a response begins and
Xterminates with a CRLF.
X
Xi) Send 1 page of document with normal resolution
X
XCommand Response
X
XATX4&D2#B3#P1#R0#T0#F1 <OK> ; Enter Fax mode
X <XOFF> CTS -> 0
X
XATDT4082639337 <OK> ; Dial a Fax machine
X ; any AT response valid
X <CED>
X ; Answertone detected
X
X <CSI = 408 263 1234>
X ; Called machine
X ; identification
X <DIS>
X ; Capabilities
X ; frame received
X
X <CFR>
X ; OK to send page data
X
X <CONNECT 4800/FAX>
X ; Connection speed
X
X <XON> CTS -> 1
X ; Page 1 data is sent
X ; using flow control
X---DATA--SENT---
X <XOFF> CTS -> 0
X---DATA STOPPED---
X <XON> CTS -> 1
X---DATA--SENT---
X ; No more data for page 1
X ; tx underflow
X
X <XOFF> CTS -> 0
X <MCF>
X ; Page 1 transmission OK
X
X <NO CARRIER>
X ; Call terminated, return to
X ; command mode
X
Xno new commands
Xuntil here
Xii) Send 2 pages of document with normal resolution
X
XCommand Response
X
XATX4&D2#B3#P2#R0#T0#F1 ; Enter Fax mode
X <XOFF> CTS -> 0
X <OK>
X
XATDT4082639337 <OK> ; Dial a Fax machine
X ; any AT response valid
X <CED>
X ; Answertone detected
X
X <INVALID FRAME>
X ; Received frame invalid
X
X <CSI = 408 263 1234>
X ; Called machine
X ; identification
X
X <DIS>
X ; Capabilities
X ; frame received
X
X
X <CFR>
X ; OK to send page data
X
X <CONNECT 4800/FAX>
X ; Connection speed
X
X <XON> CTS -> 1
X ; Page 1 data is sent
X ; using flow control
X---DATA--SENT---
X <XOFF> CTS -> 0
X---DATA STOPPED---
X <XON> CTS -> 1
X---DATA--SENT---
X ; No more data for page 1
X ; tx underrun
X <XOFF> CTS -> 0
X <MCF>
X ; Page 1 transmission OK
X
X <XON> CTS -> 1
X ; Page 2 Data is sent
X ; using flow control
X---DATA--SENT---
X <XOFF> CTS -> 0
X---DATA STOPPED---
X <XON> CTS -> 1
X---DATA--SENT---
X ; No more data for page 2
X ; tx underrun
X
X <XOFF> CTS -> 0
X <MCF>
X ; Page 2 transmission OK
X <NO CARRIER>
X ; Call terminated, return to
X ; command mode
Xno new commands
Xuntil here
X
X--
XNick Pemberton uucp: !{lsuc, uunet!mnetor}!aimed!nick
XAIM, Inc bus: (416) 429-1085
XToronto, Ontario, Canada Home: (416) 690-0647
X
X
END_OF_FILE
if test 20046 -ne `wc -c <'writefax.man'`; then
echo shar: \"'writefax.man'\" unpacked with wrong size!
fi
# end of 'writefax.man'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
if test ! -f ark${I}isdone ; then
MISSING="${MISSING} ${I}"
fi
done
if test "${MISSING}" = "" ; then
echo You have unpacked all 5 archives.
rm -f ark[1-9]isdone
else
echo You still must unpack the following archives:
echo " " ${MISSING}
fi
exit 0
exit 0 # Just in case...
--
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.
More information about the Comp.sources.unix
mailing list