home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / faxpax / part01 next >
Text File  |  1991-03-12  |  55KB  |  2,053 lines

  1. Subject:  v24i039:  Email fax-sending package, Part01/05
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 0c8fe16e 6f072551 39bbea94 42baa701
  5.  
  6. Submitted-by: klaus u schallhorn <cnix!klaus>
  7. Posting-number: Volume 24, Issue 39
  8. Archive-name: faxpax/part01
  9.  
  10. This  is   faxpak   [Copyright   (C)   1991   klaus   schallhorn,
  11. klaus@cnix.uucp]
  12.  
  13. faxpak currently runs on Suns only - not because it uses any spe-
  14. cial  SunOs features, but because I don't have access to anything
  15. else. I developed faxpak mainly on a 4/60, then  moved  it  to  a
  16. 3/60 that does all our spooling.
  17.  
  18. Apart from [temporary] hardware and  typeface  restrictions  [see
  19. below]  faxpak is quite flexible. It allows faxes to be sent from
  20. any networked machine. It allows aliases and distribution  lists.
  21. Entries  in  such  lists needing a special "for the attention of"
  22. string are forked out as separate jobs.  If you have more than  1
  23. fax  modem,  faxpak  automatically  shares the load between these
  24. modems. This includes splitting of batches to distribution  lists
  25. into several queues.
  26.  
  27. faxpak enforces permissions. You can set faxpak up to send  local
  28. faxes  any  time, long distance ones and international ones to be
  29. sent at cheap rates only. You can enforce the sending of faxes to
  30. any  given  phone  number at fixed times. And you can permit some
  31. users to override these time restrictions.
  32.  
  33. faxpak was created when the post office  increased  our  contract
  34. postage rates to an almost insane level. We therefore decided [as
  35. a small publishing house] to  deliver  our  newsletter  by  other
  36. means.  We  now  deliver  by mail(1) to subscribers' mailboxes at
  37. various online and video text systems, we allow direct modem con-
  38. nection to mbox [our 3/60] and we fax our newsletter.
  39.  
  40. faxpak is used for oneoff faxes [and only if I can't email],  and
  41. has  been  used  three  times  [we  publish every other week] for
  42. batches of ~150 faxes @ five pages each to our  subscriber  list.
  43. Batches of this size take a good two nights to send out, although
  44. the pure transmission time is just under 12 hours  [the  rest  is
  45. engaged  phone lines, repeats because transmission errors, logins
  46. sneaking in on the faxmodems, etc].
  47.  
  48. faxpak currently supports touchbase's 2496 fax modem  and  others
  49. that  use  or emulate the sierra type fax chipset, such as zoom's
  50. mx 2400s. Early december I found someone willing  and  supposedly
  51. able  to ship a beta class2 modem. Unfortunately it seems to have
  52. been sent by bicycle.  It's supposed to be here "real soon now".
  53.  
  54. For this reason faxpak does [not yet] support other  modems,  nor
  55. does it allow incoming faxes.
  56.  
  57. #! /bin/sh
  58. # This is a shell archive.  Remove anything before this line, then feed it
  59. # into a shell via "sh file" or similar.  To overwrite existing files,
  60. # type "sh file -c".
  61. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  62. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  63. # Contents:  MANIFEST faxclient faxhost faxhost/faxcleanup.c
  64. #   faxhost/faxfonts faxhost/wiring.c
  65. # Wrapped by rsalz@litchi.bbn.com on Wed Mar 13 14:08:00 1991
  66. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  67. echo If this archive is complete, you will see the following message:
  68. echo '          "shar: End of archive 1 (of 5)."'
  69. if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  70.   echo shar: Will not clobber existing file \"'MANIFEST'\"
  71. else
  72.   echo shar: Extracting \"'MANIFEST'\" \(1250 characters\)
  73.   sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
  74. X   File Name        Archive #    Description
  75. X----------------------------------------------------------
  76. XMANIFEST                   1    This shipping list
  77. XFaxConfig                  2    chmod +x or sh FaxConfig
  78. XHowto.Install              5    basic install info
  79. XReadme                     4    describes faxpak
  80. Xfaxclient                  1    
  81. Xfaxclient/fax.c            3    user interface [wot - no vindohs?]
  82. Xfaxhost                    1    
  83. Xfaxhost/faxcleanup.c       1    leftover disposer
  84. Xfaxhost/faxfonts           1    kit to roll your own 8bit charset
  85. Xfaxhost/faxfonts/diy_codep861.def  5    
  86. Xfaxhost/faxfonts/diy_ibmpc.def  5    
  87. Xfaxhost/faxfonts/diy_iso.def  5    
  88. Xfaxhost/faxfonts/diykit.c  2    
  89. Xfaxhost/faxfonts/diykit.h  4    
  90. Xfaxhost/faxfonts/hires.uue  4    compressed font data    
  91. Xfaxhost/faxfonts/lores.uue  4    same
  92. Xfaxhost/faxlog.c           5    
  93. Xfaxhost/fntwrite.c         4    
  94. Xfaxhost/pbmtog3.c          4    REPLACE pbmplus/pbmtog3 WITH THIS ONE !
  95. Xfaxhost/sendfax.c          2    
  96. Xfaxhost/sierracmd.h        4    
  97. Xfaxhost/spool.fax.c        3    spooler
  98. Xfaxhost/texttopbm.c        5    uses the diy font kit
  99. Xfaxhost/wiring.c           1    
  100. Xsample.dot.faxrc           5    free samples
  101. Xsample.fax.aliases         3    
  102. Xsample.fax.list            4    
  103. Xwritefax.man               3    tech specs for sierra type modems
  104. END_OF_FILE
  105.   if test 1250 -ne `wc -c <'MANIFEST'`; then
  106.     echo shar: \"'MANIFEST'\" unpacked with wrong size!
  107.   fi
  108.   # end of 'MANIFEST'
  109. fi
  110. if test ! -d 'faxclient' ; then
  111.     echo shar: Creating directory \"'faxclient'\"
  112.     mkdir 'faxclient'
  113. fi
  114. if test ! -d 'faxhost' ; then
  115.     echo shar: Creating directory \"'faxhost'\"
  116.     mkdir 'faxhost'
  117. fi
  118. if test -f 'faxhost/faxcleanup.c' -a "${1}" != "-c" ; then 
  119.   echo shar: Will not clobber existing file \"'faxhost/faxcleanup.c'\"
  120. else
  121.   echo shar: Extracting \"'faxhost/faxcleanup.c'\" \(5045 characters\)
  122.   sed "s/^X//" >'faxhost/faxcleanup.c' <<'END_OF_FILE'
  123. X#include <stdio.h>
  124. X#include <sys/time.h>
  125. X#include <dirent.h>
  126. X
  127. X#include "../faxconfig.h"
  128. X
  129. Xstruct    FAX fax;
  130. Xchar    io[512], tmp[256];
  131. Xtime_t    now;
  132. Xint    maxage, maxtry, blah;
  133. X
  134. X/*
  135. X    faxcleanup
  136. X
  137. X    runs once a day to rm old garbage that might be left over.
  138. X    all the functions here are really shortened stubs picked
  139. X    mostly from sendfax.c [I plan to do a faxlib later].
  140. X
  141. X    first released version 0.99 [desperado version]
  142. X    cleaned up Jan 28nd '91,
  143. X    Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp
  144. X
  145. X    Permission to use, copy, modify, and distribute this software 
  146. X    and its documentation for any purpose and without fee is hereby 
  147. X    granted, provided that the above copyright notice appear in 
  148. X    all copies and that both that copyright notice and this permission 
  149. X    notice appear in supporting documentation. 
  150. X
  151. X    This software is provided "as is" without express or implied warranty.
  152. X*/
  153. X
  154. Xread_config()
  155. X{
  156. X    FILE *cfg;
  157. X    char a[256], b[80];
  158. X    int i;
  159. X
  160. X    maxage = maxtry = 0;
  161. X    sprintf(a, "%s/fax.config", FAXLIB);
  162. X    if ((cfg = fopen(a, "r")) == NULL)
  163. X    {
  164. X        fax_log(ERROR,"faxcleanup: can't open %s/fax.config\n",FAXLIB);
  165. X        return(ERROR);
  166. X    }
  167. X
  168. X    while (fgets(io, 254, cfg) != NULL)
  169. X    {
  170. X        if (io[0] == '#' || (sscanf(io, "%s %s",a,b) < 1))
  171. X            continue;
  172. X        if (!strcmp(a, "maxage"))
  173. X            maxage = atoi(b);
  174. X        else if (!strcmp(a, "maxtry"))
  175. X            maxtry = atoi(b);
  176. X        if (maxage && maxtry)
  177. X            break;
  178. X    }
  179. X    fclose(cfg);
  180. X    return(0);
  181. X}
  182. Xread_job(fp, xn)
  183. XFILE *fp;
  184. Xchar *xn;
  185. X{
  186. X    int i;
  187. X
  188. X    if (getint(fp,&fax.spooled))    /* spool timestamp */
  189. X        return(ERROR);
  190. X    if (getint(fp,&fax.tries)
  191. X        || getstring(fp,fax.user) || getint(fp,&fax.uid)
  192. X        || getint(fp,&fax.now) || getint(fp,&fax.mail)
  193. X        || getstring(fp,tmp)    /* type, don't need to know */
  194. X        || getint(fp,&fax.hires)/* hires, NEEDED FOR SENDFAX */
  195. X        || getstring(fp,tmp)    /* font, don't need to know  */
  196. X        || getstring(fp,tmp))    /* retfax, don't need to know  */
  197. X        return(ERROR);
  198. X    if ((fax.phone_nos = getphone(fp)) <= 0)
  199. X        return(ERROR);
  200. X    if (getstring(fp,fax.dname))
  201. X        return(ERROR);
  202. X    strcpy(fax.xname, xn);
  203. X    if (getint(fp,&fax.pages))
  204. X        return(ERROR);
  205. X#ifdef    JOBID
  206. X    if (getstring(fp,fax.jobid))
  207. X        return(ERROR);
  208. X#endif
  209. X    return(0);
  210. X}
  211. Xgetstring(fp,s)
  212. XFILE *fp;
  213. Xchar *s;
  214. X{
  215. X    char buf[80];
  216. X
  217. X    if (fgets(io, 80, fp) == NULL)
  218. X        return(ERROR);
  219. X    if (sscanf(io, "%s %s",buf,s) != 2)
  220. X        return(ERROR);
  221. X    return(0);
  222. X}
  223. Xgetint(fp,n)
  224. XFILE *fp;
  225. Xint *n;
  226. X{
  227. X    long l;
  228. X
  229. X    if (fgets(io, 80, fp) == NULL)
  230. X        return(ERROR);
  231. X    if (sscanf(io, "%s %ld",tmp,&l) != 2)
  232. X        return(ERROR);
  233. X    *n = l;
  234. X    return(0);
  235. X}
  236. Xgetphone(fp)
  237. XFILE *fp;
  238. X{
  239. X    char phone[80];
  240. X    long oldpos;
  241. X
  242. X    for (;;)
  243. X    {
  244. X        oldpos = ftell(fp);
  245. X        if (fgets(io, 80, fp) == NULL)
  246. X            return(ERROR);
  247. X        if (io[0] == '#')
  248. X            continue;
  249. X        if (!strncmp(io, "data", 4))
  250. X        {
  251. X            fseek(fp, oldpos, 0);
  252. X            break;
  253. X        }
  254. X        if (sscanf(io, "%s %s",tmp,phone) != 2)
  255. X            return(ERROR);
  256. X    }
  257. X    return(TRUE);
  258. X}
  259. Xmain()
  260. X{
  261. X    DIR *dirp;
  262. X    struct dirent *dp;
  263. X    FILE *fp, *pp;
  264. X    time_t days;
  265. X    char me[80];
  266. X
  267. X    blah = 0;
  268. X    if (chdir(FAXSPOOL))    /* quick one, job done */
  269. X    {
  270. X        fax_log(ERROR,"faxcleanup: can't cd to FAXSPOOL\n");
  271. X        exit(1);
  272. X    }
  273. X    if (read_config())
  274. X        exit(1);
  275. X
  276. X    days = (60L * 60L * 24L);    /* about an average unix working day */
  277. X    days *= (time_t)maxage;
  278. X    now = time((time_t *)NULL);
  279. X
  280. X    if (gethostname(me, 80))
  281. X        me[0] = '\0';
  282. X
  283. X    if ((dirp = opendir(FAXSPOOL)) == NULL)
  284. X    {
  285. X        fax_log(ERROR,"faxcleanup: can't open directory %s\n",FAXSPOOL);
  286. X        exit(1);
  287. X    }
  288. X
  289. X    while ((dp = readdir(dirp)) != NULL)
  290. X    {
  291. X        if (strncmp(dp->d_name, "x.f", 3))
  292. X            continue;
  293. X
  294. X        if ((fp = fopen(dp->d_name, "r")) == NULL)
  295. X        {
  296. X            fax_log(ERROR,"faxcleanup: can't open %s\n",dp->d_name);
  297. X            exit(1);
  298. X        }
  299. X        if (read_job(fp, dp->d_name))
  300. X        {
  301. X            fax_log(ERROR,"faxcleanup: can't read %s\n",dp->d_name);
  302. X            exit(1);
  303. X        }
  304. X        if ((fax.spooled + days < now) || fax.tries >= maxtry)
  305. X        {
  306. X            rewind(fp);
  307. X            sprintf(io, "mail %s",fax.user);
  308. X            if ((pp = popen(io, "w")) == NULL)
  309. X            {
  310. X                fax_log(ERROR,"faxcleanup: can't mail user %s about bad job %s\n",
  311. X                    fax.user,dp->d_name);
  312. X                exit(1);
  313. X            }
  314. X#ifdef    JOBID
  315. X            fprintf(pp,"your fax job %s, queued ",fax.jobid);
  316. X#else
  317. X            fprintf(pp,"your fax job %s, queued ",dp->d_name);
  318. X#endif
  319. X            timestamp(pp, (time_t)fax.spooled);
  320. X            fprintf(pp,"could not be sent\n\n");
  321. X            fprintf(pp,"no of attempts and unsent phone nos:\n");
  322. X
  323. X            while (fgets(io, 128, fp) != NULL)
  324. X            {
  325. X                if ((!strncmp(io, "phone", 5))
  326. X                    || (!strncmp(io, "tries", 4)))
  327. X                    fprintf(pp, "\t%s",io);
  328. X            }
  329. X            fprintf(pp,"\n");
  330. X
  331. X            fprintf(pp,"you can ask %s for the appropriate logs\n\n",FAXADMIN);
  332. X            fprintf(pp,"regrettably yours\n\n\tfaxcleanup%c%s\n\n",
  333. X                (me[0])?'@':' ',me);
  334. X            fprintf(pp,"PS: have you considered using email ?\n");
  335. X            fflush(pp);
  336. X            if (ferror(pp))
  337. X            {
  338. X                fax_log(ERROR,"faxcleanup: can't mail user %s about bad job %s\n",
  339. X                    fax.user,dp->d_name);
  340. X                exit(1);
  341. X            }
  342. X            pclose(pp);
  343. X            fclose(fp);
  344. X            rmjob(fax.xname, fax.dname, fax.pages);
  345. X        }
  346. X    }
  347. X    closedir(dirp);
  348. X    exit(0);
  349. X}
  350. Xrmjob(xname,dname,pages)
  351. Xchar *xname,*dname;
  352. Xint pages;
  353. X{
  354. X    char buf[256], *d;
  355. X    int i;
  356. X
  357. X    unlink(xname);
  358. X    for (i=0; i<pages; i++)
  359. X    {
  360. X        sprintf(buf,"%s.g3.%d",dname,i);
  361. X        unlink(buf);
  362. X    }
  363. X}
  364. END_OF_FILE
  365.   if test 5045 -ne `wc -c <'faxhost/faxcleanup.c'`; then
  366.     echo shar: \"'faxhost/faxcleanup.c'\" unpacked with wrong size!
  367.   fi
  368.   # end of 'faxhost/faxcleanup.c'
  369. fi
  370. if test ! -d 'faxhost/faxfonts' ; then
  371.     echo shar: Creating directory \"'faxhost/faxfonts'\"
  372.     mkdir 'faxhost/faxfonts'
  373. fi
  374. if test -f 'faxhost/wiring.c' -a "${1}" != "-c" ; then 
  375.   echo shar: Will not clobber existing file \"'faxhost/wiring.c'\"
  376. else
  377.   echo shar: Extracting \"'faxhost/wiring.c'\" \(41916 characters\)
  378.   sed "s/^X//" >'faxhost/wiring.c' <<'END_OF_FILE'
  379. X#include <stdio.h>
  380. X#include <ctype.h>
  381. X#include <termios.h>
  382. X#include <fcntl.h>
  383. X#include <errno.h>
  384. X#include <signal.h>
  385. X#include <sys/time.h>
  386. X
  387. X#include "../faxconfig.h"
  388. X
  389. X
  390. Xextern    int errno;
  391. X
  392. X/*
  393. X    wiring.c
  394. X
  395. X    first released version 0.99a [desperado version]
  396. X    cleaned up Feb 21st, '91,
  397. X    Copyright (C) 1991, klaus schallhorn, klaus@cnix.uucp
  398. X
  399. X    Permission to use, copy, modify, and distribute this software 
  400. X    and its documentation for any purpose and without fee is hereby 
  401. X    granted, provided that the above copyright notice appear in 
  402. X    all copies and that both that copyright notice and this permission 
  403. X    notice appear in supporting documentation. 
  404. X
  405. X    This software is provided "as is" without express or implied warranty.
  406. X
  407. X
  408. X    faxpak is late by about 6 weeks. It turned out that the way
  409. X    the faxmodem communicates with the host is extremely, well,
  410. X    artistic. It also turned out that g3 files, as specified
  411. X    in the ccitt specs need quite a bit of processing before
  412. X    they can be stashed down the serial port.
  413. X
  414. X    The faxmodem basically makes the assumption it's running
  415. X    on a medium to fast dos box. It assumes it has the undivided
  416. X    attention of the host, and it assumes it can fiddle with
  417. X    the actual wiring between the host and the modem at will
  418. X    [like the guy in the movie trying to start a stolen car].
  419. X
  420. X    If, for instance, you're using hardware flow ctl, the
  421. X    fax modem still sends tons of xon's/xoff's although you
  422. X    specified NOT to use xonoff.
  423. X
  424. X    pauses of more than one fifteenth of a second during the 
  425. X    tx [transmission] phase of a fax result in a quiet abort.
  426. X    The faxmodem regards this as "end of page" and squirts
  427. X    abuse to the fax machine at the other end.
  428. X
  429. X    Imagine news expiring a full feed, or processing an incoming
  430. X    batch, and the standard cron tab entry finding old garbage
  431. X    and removing it and you can see that a delay of something
  432. X    like 60 or 70 milliseconds is quite possible.
  433. X
  434. X    I therefore suggest not to schedule any faxes at or
  435. X    around the time disk intensive cron jobs are due if you cannot
  436. X    guarantee there won't be any major swapping.
  437. X
  438. X    A 3/60 handles concurrent "find", or "newsrun" and faxes ok.
  439. X    Copying a few Mb via nfs while your sending multiple faxes works
  440. X    as well.
  441. X
  442. X    On a 10 mhz 286 [dos] box printf statements while transmitting 
  443. X    can screw you up [actually not you, but the outgoing fax].
  444. X    They take too long. And I'm not kidding.
  445. X
  446. X    I assume "Flow control" is done partly in rs232 fashion, 
  447. X    more so according to what's possible and common on dos boxes. 
  448. X    In fact, the various modem manufacturers' specs specify which 
  449. X    bit in which register to twiddle, in the dos box hardware, 
  450. X    rather than how to connect to a serial port.
  451. X
  452. X    This proves to have no effect - unless the fax modem is 
  453. X    actually connected to a dos box.
  454. X
  455. X    In the course of getting this to work I have used three rolls
  456. X    of fax paper, resorted to beating the fax modem [makes you
  457. X    feel real good. Doesn't advance the issue though], and missed some
  458. X    of my favourite tv pgms.
  459. X
  460. X    After some persistant phone calls to the vendor I even
  461. X    discovered that my modem had beta release firmware [no hint of that
  462. X    in the sales blurb or the tech specs]. A "pre release" prom was 
  463. X    promised and arrived promptly after a week [I actually got two].
  464. X    Clearly labelled "BETA RELEASE" this time. I would
  465. X    not be surprised to find further discrepancies between specs
  466. X    and real life [incorporated into the wiring, 26.1.90].
  467. X
  468. X    Well, at least it works now, on Sun 3's and Sun 4's [I run 4.1],
  469. X    using hardware flow ctl - no chance with xon/xoff.
  470. X
  471. X    If you don't have a Sun, and cannot yet get your hands on one
  472. X    of these "available real soon now" class2 modems [I'm still waiting],
  473. X    I suggest you get a fax modem
  474. X
  475. X        ON LOAN, or
  476. X        =======
  477. X        ON APPROVAL,
  478. X        ===========
  479. X
  480. X    and have the supplier [remember, it's not a vendor yet] confirm
  481. X    that the modem's command set adheres strictly to the CCITT T.30
  482. X    specifications [dubbed sierra], as outlined in the enclosed
  483. X    document "writefax.man" which I picked up on the net.
  484. X
  485. X    There are faxmodems out and available now that currently
  486. X    support T.30 *and* some proprietary command set [often using
  487. X    a binary language when analysed with a serial port sniffer].
  488. X    Some faxmodems come with a non standard command set and need
  489. X    an upgrade in firmware to make them t.30 compatible [like the
  490. X    ones I used]. Others will be relaunched as t.30 compatible ones,
  491. X    again, "real soon now" [honestly, I'm running beta].
  492. X
  493. X    You have to make sure though that the modem recognises AT LEAST
  494. X    the sierra, or t.30, standard - class2 type modems of course
  495. X    would be far better, but as far as I know the standard is still
  496. X    in the making. The making of the modems thusly might take just
  497. X    that little bit extra.
  498. X
  499. X    I'm not trying to discourage you.
  500. X
  501. X    I just want to make sure you don't run out and buy yourself
  502. X    a fax modem you can only use with the vendors software on a dos
  503. X    box [why don't you use email anyway?].
  504. X
  505. X    Only after you've aquired a fax modem on the terms outlined
  506. X    here should you play with this module with:
  507. X
  508. X#define    TESTING
  509. X#define    TEST_DEVICE=\"/dev/whatever_device_is_handy_for_testing\"
  510. X
  511. X    to get it working. And only if you get it to work on your system,
  512. X    is faxpak a make, install 'n run package.
  513. X
  514. X    During development it's certainly helpful to turn incoming
  515. X    getty's OFF. Otherwise you might have to reboot because
  516. X    an aborted attempt might block the port from further use.
  517. X
  518. X    If the modem works to your satisfaction for several years
  519. X    you may pay the bill for the modem.
  520. X
  521. X    It is possible that I have to port this within the next six to
  522. X    eight weeks to a xenix 286 box - a system I know nothing of.
  523. X    But I won't know this for sure until early march.
  524. X
  525. X*/
  526. X
  527. X#ifdef    SIERRA
  528. X/*
  529. X    sierra modems cannot digest raw group 3 format fax files. They 
  530. X    need quite a bit of munging and processing. 
  531. X*/
  532. X#include "sierracmd.h"
  533. X#endif    SIERRA    /* ***************************************************** */
  534. X
  535. X
  536. X
  537. X#ifdef    CLASS2
  538. X    while (class2 modem != yet arrived)
  539. X        ;
  540. X#endif
  541. X
  542. X
  543. X
  544. X
  545. X
  546. X
  547. X/* *************** these apply to both types of modem types ************ */
  548. X#define    Class2        0
  549. X#define    Sierra        1
  550. X
  551. Xstruct    Modems
  552. X{
  553. X    char    *name;
  554. X    int    type;
  555. X} known_modems[]=
  556. X{
  557. X    "class2",    Class2,     /* your best bet */
  558. X    "sierra",    Sierra     /* see above, and sierracmd.h for info */
  559. X};
  560. X#define    MAX_MODEM    (sizeof(known_modems)/sizeof(struct Modems))
  561. X
  562. Xstruct    termios    virgin, wire;
  563. X
  564. Xint    ser_port, cannot, dev_no, curjob, curpage, sent, failed, 
  565. X    dial_tries;
  566. Xstatic    int foul;
  567. X
  568. Xchar    wbuf[1024], biff[1024], namebuf[256];
  569. Xchar    devnam[256], lcknam[256];
  570. Xunsigned char rxbuf[1024], txbuf[2048];
  571. XFILE    *logfp;
  572. X
  573. Xvoid    breakwrite();
  574. Xchar    *faxtime();
  575. X
  576. X
  577. X#ifndef    TESTING
  578. X#define    SPEAKER    0
  579. X#define    FUNCTION(funcname)    ""
  580. X    
  581. Xextern    char **Devices, **Devlocks, **Faxtypes, **Wakeup,
  582. X        *Dialtyp, *Topspeed;
  583. Xextern    struct FAX fax;
  584. Xextern    int blah;
  585. X
  586. X#else    /* ******************** TESTING ********************* */
  587. X
  588. X#include <varargs.h>
  589. X#ifndef    SPEAKER
  590. X#define    SPEAKER    2
  591. X#endif
  592. X#define    FUNCTION(funcname)    funcname
  593. X
  594. Xchar    tstphone[80], faxtype[80], wakeup[2], dev[80];
  595. Xchar    *Devices[2], *Devlocks[2], *Faxtypes[2], *Wakeup[2],
  596. X        Dialtyp[2], Topspeed[2];
  597. Xstruct    FAX fax;
  598. Xint    blah=9;
  599. X
  600. Xmain(ac,av)
  601. Xint ac;
  602. Xchar *av[];
  603. X{
  604. X    if (ac != 4)
  605. X    {
  606. X        fprintf(stderr,"need phoneno, no_of_pages, g3.basename\n");
  607. X        exit(1);
  608. X    }
  609. X    strcpy(fax.user,  "root"); /* you need the perms for port access anyway */
  610. X    strcpy(fax.dname, av[3]);
  611. X    strcpy(fax.xname, "nosuch");
  612. X    strcpy(tstphone,  av[1]);
  613. X    fax.phone = (char **)malloc(2*sizeof(char*));
  614. X    fax.phone[0] = tstphone;
  615. X    fax.phone[1] = NULL;
  616. X    fax.tries = fax.uid = 0;
  617. X    fax.now = TRUE;
  618. X    fax.mail = 0;
  619. X    fax.pages = atoi(av[2]);
  620. X    fax.phone_nos = 1;
  621. X#ifdef    SIERRA
  622. X    strcpy(faxtype, "sierra");
  623. X#else
  624. X    strcpy(faxtype, "class2");
  625. X#endif
  626. X    Faxtypes[0] = faxtype;
  627. X    Faxtypes[1] = NULL;
  628. X    wakeup[0] = '\0';
  629. X    Wakeup[0] = wakeup;
  630. X    Wakeup[1] = NULL;
  631. X    Dialtyp[0] = 'T';    /* 'P' for pulse dialling */
  632. X    Dialtyp[1] = '\0';
  633. X    strcpy(dev, TEST_DEVICE);
  634. X    Devices[0] = dev;
  635. X    Devices[1] = NULL;
  636. X    Devlocks[0] = wakeup;    /* empty */
  637. X    Devlocks[1] = NULL;
  638. X    Topspeed[0] = '7';    /* 9600 baud, see modem docs */
  639. X    Topspeed[1] = '\0';
  640. X#ifdef    BLAH
  641. X    blah = BLAH;
  642. X#endif
  643. X
  644. X    sendfax((FILE *)NULL,0,TRUE);
  645. X    exit(0);
  646. X}
  647. X#ifndef    lint
  648. Xfax_log(va_alist)
  649. Xva_dcl
  650. X{
  651. X    va_list args;
  652. X    char *fmt;
  653. X    int db_flag;
  654. X
  655. X    va_start(args);
  656. X    db_flag = va_arg(args, int);
  657. X    fmt = va_arg(args, char *);
  658. X
  659. X    if (db_flag == ERROR || (blah >= db_flag))
  660. X    {
  661. X        fprintf(stderr,"   ");
  662. X        vfprintf(stderr, fmt, args);
  663. X    }
  664. X    va_end(args);
  665. X    return(0);
  666. X}
  667. Xfax_tlog(va_alist)
  668. Xva_dcl
  669. X{
  670. X    va_list args;
  671. X    int db_flag;
  672. X    FILE *fp;
  673. X    char *fmt;
  674. X
  675. X    va_start(args);
  676. X
  677. X    db_flag = va_arg(args, int);
  678. X    fp = va_arg(args, FILE *);
  679. X    fmt = va_arg(args, char *);
  680. X
  681. X    if (fp && (db_flag == ERROR || (blah >= db_flag)))
  682. X    {
  683. X        if (db_flag == ERROR)
  684. X            fprintf(stderr,"%2d ",errno);
  685. X        else fprintf(stderr,"   ");
  686. X        vfprintf(stderr, fmt, args);
  687. X    }
  688. X    va_end(args);
  689. X    return(0);
  690. X}
  691. Xfflushlog(){return(0);}        /* don't bother with these while testing */
  692. Xnot_now(){return(0);}        /* notnow() and rmjob() are in sendfax.c */
  693. Xrmjob(){return(0);}        /* you don't want to link that in for tests */
  694. X
  695. X#endif    /* lint */
  696. X#endif    /* ******************* end of TESTING CODE ********************* */
  697. X
  698. X
  699. Xchar *faxtime(t) /* dont know how portable the ctime(3) variants are */
  700. Xtime_t t;     /* in any case, all I need is the time */
  701. X{
  702. X    static char permastore[40];
  703. X    struct tm *tml, *localtime();
  704. X
  705. X    tml = localtime(&t);
  706. X    sprintf(permastore,"%02d:%02d:%02d",
  707. X        tml->tm_hour,tml->tm_min,tml->tm_sec);
  708. X    return(permastore);
  709. X}
  710. Xvoid breakwrite()
  711. X{
  712. X    cannot = 1;
  713. X}
  714. Xportunlock(name)
  715. Xchar *name;
  716. X{
  717. X    if (name)
  718. X        unlink(name);
  719. X    return(ERROR);
  720. X}
  721. X
  722. Xplug(portname,portlock)
  723. Xchar *portname, *portlock;
  724. X{
  725. X    int i;
  726. X
  727. X    errno = 0;
  728. X        /* lock, allow possible incoming fax, or uucp, wait 5 mins */
  729. X        /* if no luck, simply go away */
  730. X#ifndef    TESTING
  731. X    if (portlock)
  732. X        if (mklock(portlock, 30, 300))
  733. X            return(ERROR);
  734. X#endif
  735. X    if ((ser_port = open(portname, (O_RDWR | O_NDELAY), 0600)) < 0)
  736. X    {
  737. X        if (errno == EBUSY)
  738. X            fax_tlog(0, logfp, "sendfax: port %s BUSY\n",portname);
  739. X        else fax_tlog(ERROR, logfp, "sendfax: can't plug into %s\n",portname);
  740. X        return(portunlock(portlock));
  741. X    }
  742. X    if (ioctl(ser_port,TCGETS,&virgin) < 0)
  743. X    {
  744. X        fax_tlog(ERROR, logfp, "sendfax: can't ioctl on %s\n",portname);
  745. X        return(portunlock(portlock));
  746. X    }
  747. X    wire = virgin;            /* working copy        */
  748. X
  749. X    wire.c_iflag &= ~BRKINT;    /* c_iflag is set to 0L, but looks */
  750. X    wire.c_iflag &= ~ICRNL;        /* cleaner when setting flags off */
  751. X    wire.c_iflag &= ~ISTRIP;
  752. X    wire.c_iflag &= ~IXON;    /* can't use proper xon/xoff, see set_ixon() */
  753. X
  754. X    wire.c_cflag &= ~CIBAUD;
  755. X    wire.c_cflag &= ~B9600;
  756. X    wire.c_cflag |= CSIZE;
  757. X    wire.c_cflag |= CS8;
  758. X    wire.c_cflag |= HUPCL;
  759. X    wire.c_cflag |= CREAD;
  760. X    wire.c_cflag |= B2400;
  761. X    wire.c_cflag |= CSTOPB;
  762. X    wire.c_cflag &= ~PARENB;
  763. X
  764. X    wire.c_lflag &= ~ISIG;
  765. X/*    wire.c_lflag &= ~ICANON; I now read this a line at a time */
  766. X    wire.c_lflag &= ~ECHO;
  767. X    wire.c_lflag &= ~IEXTEN;
  768. X
  769. X    wire.c_oflag &= ~OPOST;        /* no messing with output */
  770. X
  771. X    wire.c_cc[VMIN] = 1;
  772. X    wire.c_cc[VTIME] = 1;
  773. X    wire.c_cc[VEOL] = 0x0d;    /* need this to get the lines though */
  774. X                /* or I would have to switch to ascii asnwers */
  775. X                /* from the modem altogether - don't like it */
  776. X    if (ioctl(ser_port,TCSETSF,&wire) < 0)
  777. X    {
  778. X        fax_tlog(ERROR, logfp, "sendfax: can't set 2400 baud for %s\n",portname);
  779. X        return(portunlock(portlock));
  780. X    }
  781. X
  782. X    i = 1;            /* probably SUN SPECIFIC, raise carrier */
  783. X    if (ioctl(ser_port,TIOCSSOFTCAR, &i) < 0)
  784. X    {
  785. X        fax_tlog(ERROR, logfp, "sendfax: can't raise softcar on %s\n",portname);
  786. X        return(portunlock(portlock));
  787. X    }
  788. X    if (fcntl(ser_port, F_SETFL, O_RDWR) == ERROR)
  789. X    {
  790. X        fax_tlog(ERROR, logfp, "sendfax: can't set O_NDELAY off for %s\n",portname);
  791. X        return(portunlock(portlock));
  792. X    }
  793. X    fax_tlog(5, logfp, "sendfax: 2400 baud set for %s\n",portname);
  794. X    return(0);
  795. X}
  796. Xfaxmode(portname,portlock)
  797. Xchar *portname,*portlock;
  798. X{
  799. X    errno = 0;
  800. X            /* pump up the volume to 19k2 */
  801. X    wire.c_cflag &= ~B2400;
  802. X    wire.c_cflag |= B19200;
  803. X
  804. X    if (ioctl(ser_port,TCSETSW,&wire) < 0)
  805. X    {
  806. X        fax_tlog(ERROR, logfp, "sendfax: can't set 19200 baud for %s\n",portname);
  807. X        return(portunlock(portlock));
  808. X    }
  809. X    fax_tlog(5, logfp, "sendfax: 19200 baud set for %s\n",portname);
  810. X    return(0);
  811. X}
  812. Xset_ixon(on,portname,portlock)
  813. Xint on;
  814. Xchar *portname,*portlock;
  815. X{
  816. X/*
  817. X    toggle flow control
  818. X    there's no point trying to READ during transmit if
  819. X    we're using CRTSCTS [hardware flow ctl], we
  820. X    simply won't get anything even if the modem sends us some,
  821. X    which in fact it does, namely xons and xoffs, even if we tell
  822. X    the modem not to use xonoff flow ctl [tested on dos].
  823. X
  824. X    I don't know if this is standard behaviour or if this
  825. X    is a SunOs value added feature
  826. X
  827. X    if you want to try your luck with xon/xoff, you have to set
  828. X    flow ctl AFTER you've received your first XON [I know it's silly].
  829. X    One problem you're likely to find is that the modem expects
  830. X    the host to shut up instantly when sending an xoff. 
  831. X
  832. X    Testing on a dos box showed that by delaying the digesting of a 
  833. X    received xoff by two bytes screwed up the fax. It also showed 
  834. X    that the modem sends an xoff after fewer than 100
  835. X    bytes were sent. At 19200 [~2000 bytes/sec] xon/xoff is thus toggled
  836. X    more than 20 times a second. I guess this is just too much for unix
  837. X    device drivers that are not guaranteed to stop instantly. 
  838. X    I could not get it to work on a 3/60 using xon/xoff reliably.
  839. X    I'm too tired to even try it again on a 4/60. I use hardware
  840. X    flow ctl. basta.
  841. X
  842. X    feb 21st, '91: did not try xonoff again with icanon change
  843. X*/
  844. X    errno = 0;
  845. X
  846. X    if (on)
  847. X    {
  848. X#ifdef    USE_IXON
  849. X        wire.c_iflag |= IXON;
  850. X#else
  851. X        wire.c_cflag |= CRTSCTS;
  852. X#endif
  853. X    }
  854. X    else
  855. X    {
  856. X#ifdef    USE_IXON
  857. X        wire.c_iflag &= ~IXON;
  858. X#else
  859. X        wire.c_cflag &= ~CRTSCTS;
  860. X#endif
  861. X    }
  862. X
  863. X    if (ioctl(ser_port,TCSETSW,&wire) < 0)
  864. X    {
  865. X        fax_tlog(ERROR, logfp, "sendfax: can't %s flow ctl for %s\n",
  866. X            (on)?"set":"unset",portname);
  867. X        return(portunlock(portlock));
  868. X    }
  869. X    fax_tlog(9, logfp, "sendfax: flow_ctl %s for %s\n",
  870. X            (on)?"set":"unset",portname);
  871. X    return(0);
  872. X}
  873. Xunplug(portname,portlock)
  874. Xchar *portname,*portlock;
  875. X{
  876. X    int i;
  877. X
  878. X    wire.c_cflag = B0;
  879. X    errno = 0;
  880. X
  881. X    fax_tlog(5, logfp, "sendfax: hanging up on %s\n",portname);
  882. X    if (ioctl(ser_port,TCSETS,&wire) < 0)
  883. X    {
  884. X        fax_tlog(ERROR, logfp, "sendfax: can't hang up %s\n",portname);
  885. X        return(portunlock(portlock));
  886. X    }
  887. X
  888. X    i = 0;        /* software carrier OFF */
  889. X    if (ioctl(ser_port,TIOCSSOFTCAR, &i) < 0)
  890. X    {
  891. X        fax_tlog(ERROR, logfp, "sendfax: can't set softcar off for %s\n",portname);
  892. X        return(portunlock(portlock));
  893. X    }
  894. X    close(ser_port);
  895. X
  896. X    if (Wakeup[dev_no] && *(Wakeup[dev_no]))
  897. X        resuscitate(portname);
  898. X
  899. X    (void)portunlock(portlock);
  900. X    return(0);
  901. X}
  902. Xresuscitate(dv)        /* re enable auto answer */
  903. Xchar *dv;
  904. X{
  905. X    int i;
  906. X
  907. X    if (!plug(dv, NULL))
  908. X    {
  909. X        sprintf(txbuf,"%s\r\n",Wakeup[dev_no]);
  910. X        write(ser_port, txbuf, strlen(txbuf));
  911. X        sleep(1);
  912. X
  913. X        i = 0;
  914. X        if (ioctl(ser_port,TIOCSSOFTCAR, &i) < 0)
  915. X            fax_tlog(ERROR, logfp, "sendfax: can't set softcar off for %s\n",dv);
  916. X        close(ser_port);
  917. X    }
  918. X}
  919. X
  920. Xsendfax(wfp, slot, canexit)
  921. XFILE *wfp;
  922. Xint slot, canexit;
  923. X{
  924. X    int i;
  925. X    char buf[256];
  926. X
  927. X    dev_no = slot;
  928. X    sent = failed = 0;
  929. X
  930. X    sprintf(buf, "%s/FAX.LOG.%d", FAXLIB, getpid());
  931. X    if ((logfp = fopen(buf, "w")) == NULL)
  932. X    {
  933. X        chmod(buf, FAXFMODE);
  934. X        fax_log(ERROR, "sendfax: can't create temp log, I've had it\n");
  935. X        if (canexit)
  936. X            exit(1);
  937. X        return;
  938. X    }
  939. X    for (i=0; i<MAX_MODEM; i++)
  940. X        if (!strcmp(Faxtypes[slot], known_modems[i]))
  941. X            break;
  942. X    switch(i)
  943. X    {
  944. X#ifdef    CLASS2
  945. X    case    Class2:        classyfax();    break;
  946. X#endif
  947. X#ifdef    SIERRA
  948. X    case    Sierra:        sierrafax();    break;
  949. X#endif
  950. X    default:
  951. X        fax_log(ERROR, "sendfax: unknown faxtype %s\n",Faxtypes[slot]);
  952. X    }
  953. X    if (wfp)
  954. X    {
  955. X        if (sent || failed)
  956. X            xupdate(wfp);    /* update or unlink x.fax file */
  957. X        else fclose(wfp);    /* no action, simply close file */
  958. X    }
  959. X
  960. X    fclose(logfp);
  961. X    fflushlog(buf);
  962. X    unlink(buf);        /* get rid of tmp log */
  963. X    if (canexit)
  964. X        exit(0);    /* else return */
  965. X}
  966. Xxupdate(fp)
  967. XFILE *fp;
  968. X{
  969. X    int i;
  970. X    struct tm *tml, *localtime();
  971. X
  972. X    if (sent == fax.phone_nos)
  973. X    {
  974. X        fclose(fp);
  975. X#ifndef    JOBID
  976. X        fax_tlog(0, logfp, "sendfax: job %s, %d fax%s, completed\n",
  977. X            fax.xname,fax.phone_nos,
  978. X            (fax.phone_nos>1)?"es":"");
  979. X#else
  980. X        fax_tlog(0, logfp, "sendfax: %s, jobid %s, %d fax%s, completed\n",
  981. X            fax.xname,fax.jobid,fax.phone_nos,
  982. X            (fax.phone_nos>1)?"es":"");
  983. X#endif
  984. X        rmjob(fax.xname,fax.dname,fax.pages);
  985. X        if (fax.mail)
  986. X        {
  987. X            tml = localtime(&fax.spooled);
  988. X            ++tml->tm_mon;        /* jan is 0 */
  989. X#ifndef    JOBID
  990. X            sprintf(wbuf,"echo 'your fax job %s, spooled %02d.%02d.%2d, %02d:%02d,\nhas been completed SUCCESSFUL' | mail %s",
  991. X                fax.xname,
  992. X                tml->tm_mday,tml->tm_mon,tml->tm_year,
  993. X                tml->tm_hour,tml->tm_min,
  994. X                fax.user);
  995. X#else
  996. X            sprintf(wbuf,"echo 'your fax job %s, spooled %02d.%02d.%2d, %02d:%02d,\nhas been completed SUCCESSFUL' | mail %s",
  997. X                fax.jobid,
  998. X                tml->tm_mday,tml->tm_mon,tml->tm_year,
  999. X                tml->tm_hour,tml->tm_min,
  1000. X                fax.user);
  1001. X#endif
  1002. X            system(wbuf);
  1003. X        }
  1004. X        return;
  1005. X    }
  1006. X    else if (sent + foul == fax.phone_nos)
  1007. X    {        /* created new jobs, unlink old one */
  1008. X        rmjob(fax.xname,fax.dname,fax.pages);
  1009. X        return;
  1010. X    }
  1011. X
  1012. X    if (fseek(fp, fax.tpos, 0))    /* increment no of attempts */
  1013. X    {
  1014. X        fax_tlog(ERROR, logfp, "sendfax: can't update %s after sending %d fax%s\n",
  1015. X            fax.xname, sent, (sent>1)?"es":"");
  1016. X        return;
  1017. X    }
  1018. X    fprintf(fp, "tries %3d\n",1+fax.tries);
  1019. X    if (fseek(fp, fax.ppos, 0))    /* write out remaining phone nos */
  1020. X    {
  1021. X        fax_tlog(ERROR, logfp, "sendfax: can't update %s after sending %d fax%s\n",
  1022. X            fax.xname, sent, (sent>1)?"es":"");
  1023. X        return;
  1024. X    }
  1025. X    for (i=0; i<fax.phone_nos; i++)
  1026. X        if (fax.phone[i] != NULL)
  1027. X            fprintf(fp, "phone %s\n",fax.phone[i]);
  1028. X    fprintf(fp,"data %s\npages %d\n",fax.dname,fax.pages);
  1029. X#ifdef    JOBID
  1030. X    fprintf(fp,"jobid %s\n",fax.jobid);
  1031. X#endif
  1032. X    fflush(fp);
  1033. X    if (ferror(fp))
  1034. X        fax_tlog(ERROR, logfp, "sendfax: can't update %s after sending %d fax%s\n",
  1035. X            fax.xname, sent, (sent>1)?"es":"");
  1036. X    fclose(fp);
  1037. X}
  1038. Xfork_off()
  1039. X{
  1040. X    FILE *nj;
  1041. X    int i;
  1042. X    char dname[256];
  1043. X
  1044. X/*
  1045. X    remove foul jobs from batch on first attempt, so we don't
  1046. X    spoil a batch job because of one recipient whose fax gizzmo
  1047. X    is brain dead, switched off, run out of paper or so...
  1048. X*/
  1049. X
  1050. X    sprintf(wbuf, "%s/d.fb%05d%d",FAXSPOOL,getpid(),foul);
  1051. X    strcpy(dname, wbuf);
  1052. X
  1053. X    for (i=0; i<fax.pages; i++)
  1054. X    {
  1055. X        sprintf(namebuf, "%s.g3.%d", fax.dname, i);
  1056. X        sprintf(biff,    "%s.g3.%d", wbuf,      i);
  1057. X        if (link(namebuf, biff))
  1058. X        {
  1059. X            fax_tlog(ERROR, logfp, "sendfax: can't link %s to %s for %s, x.file %s\n",
  1060. X                namebuf, biff, fax.phone[curjob],fax.xname);
  1061. X            return(ERROR);
  1062. X        }
  1063. X    }
  1064. X    sprintf(wbuf, "%s/x.fb%05d%d",FAXSPOOL,getpid(),foul);
  1065. X
  1066. X    if ((nj = fopen(wbuf, "w")) == NULL)
  1067. X    {
  1068. X        fax_tlog(ERROR, logfp, "sendfax: can't create new x.file for %s, x.file %s\n",
  1069. X            fax.phone[curjob],fax.xname);
  1070. X        return(ERROR);
  1071. X    }
  1072. X    fprintf(nj,"spooled %ld\n",fax.spooled);
  1073. X    fprintf(nj,"tries %3d\n",1);
  1074. X    fprintf(nj,"user %s\n",fax.user);
  1075. X    fprintf(nj,"uid %d\n",fax.uid);
  1076. X    fprintf(nj,"now %d\n",fax.now);
  1077. X    fprintf(nj,"mail %d\n",fax.mail);
  1078. X    fprintf(nj,"type %d\n",fax.type);
  1079. X    fprintf(nj,"hires %d\n",fax.hires);
  1080. X    fprintf(nj,"font unknown\n");    /* that's done already */
  1081. X    fprintf(nj,"retfax unknown\n");    /* that's done as well */
  1082. X    fprintf(nj,"phone %s\n",fax.phone[curjob]);
  1083. X    fprintf(nj,"data %s\n",dname);
  1084. X    fprintf(nj,"pages %d\n",fax.pages);
  1085. X#ifdef    JOBID
  1086. X    fprintf(nj,"jobid %s\n",fax.jobid);
  1087. X#endif
  1088. X    fflush(nj);
  1089. X    if (ferror(nj))
  1090. X    {
  1091. X        fax_tlog(ERROR, logfp, "sendfax: can't write to new x.file for %s, x.file %s\n",
  1092. X            fax.phone[curjob],fax.xname);
  1093. X        return(ERROR);
  1094. X    }
  1095. X    fclose(nj);
  1096. X    ++foul;
  1097. X    return(0);
  1098. X}
  1099. X
  1100. X#ifdef    SIERRA
  1101. X
  1102. Xlastframe(s, n)
  1103. Xunsigned char *s;
  1104. Xint n;
  1105. X{
  1106. X    int i;
  1107. X
  1108. X    if ((n -= 5) < 0)
  1109. X        return(ERROR);
  1110. X    for (i=0; i<n; i++)
  1111. X        if (*s++ == MARKER && (*s == 0xff) && (*(s+1) == 0xc8))
  1112. X            return(i);
  1113. X    return(ERROR);
  1114. X}
  1115. Xstrnpos(s, c, f, n)    /* similar to strchr, but works on binary'\0'strings */
  1116. Xunsigned char *s, c;    /* ignores first 'f' bytes, len is in 'n' */
  1117. Xint f, n;        /* strings are likely to contain zero bytes */
  1118. X{
  1119. X    int i;
  1120. X
  1121. X    s += f;
  1122. X    for (i=f; i<n; i++)
  1123. X        if (*s++ == c)
  1124. X            return(i);
  1125. X    return(ERROR);
  1126. X}
  1127. Xstrnrpos(s, c, f, n)    /* find last occurence of c in binary string of len n */
  1128. Xunsigned char *s, c;
  1129. Xint f, n;
  1130. X{
  1131. X    int i, last;
  1132. X
  1133. X    last = ERROR;
  1134. X    s += f;
  1135. X    for (i=f; i<n; i++)    /* I don't like counting backwards */
  1136. X        if (*s++ == c)
  1137. X            last = i;
  1138. X    return(last);
  1139. X}
  1140. Xsierrafax()
  1141. X{
  1142. X    int c, i, confirms, len, joberr, porterr, resend_cnt, tot_resends, alive;
  1143. X    FILE *fp;
  1144. X    time_t time_connect, time_hangup, *time_pstart, *time_pend;
  1145. X
  1146. X    curjob = porterr = 0;
  1147. X
  1148. X    sprintf(devnam,"%s",Devices[dev_no]);
  1149. X    sprintf(lcknam,"%s/%s",UUCPLOCKS,Devlocks[dev_no]);
  1150. X
  1151. X    signal(SIGALRM, breakwrite);
  1152. X    siginterrupt(SIGALRM, 1); /* not sure if this is avail in Sys V */
  1153. X    signal(SIGHUP, breakwrite);
  1154. X    siginterrupt(SIGHUP, 1);
  1155. X
  1156. X    while ((!porterr) && fax.phone[curjob] != NULL)
  1157. X    {
  1158. X        if (!fax.pages)        /* just in case something breaks */
  1159. X            continue;    /* cleanup will take care of it */
  1160. X
  1161. X        if (not_now(fax.uid, fax.now, fax.phone[curjob]))
  1162. X        {
  1163. X            fax_tlog(5, logfp, "sendfax: bad time for %s\n",
  1164. X                fax.phone[curjob]);
  1165. X            ++curjob;
  1166. X            continue;
  1167. X        }
  1168. X
  1169. X#ifdef    TESTING
  1170. X        fprintf(stderr, "\nsendfax: STARTUP\n");
  1171. X#endif
  1172. X        i = line_minlen = have_cfr = have_connect =
  1173. X            have_dis = cannot = dial_tries = joberr = confirms =
  1174. X            tot_resends = resend_cnt = 0;
  1175. X        alive = TRUE;
  1176. X
  1177. X        if (((time_pstart = (time_t *)calloc(fax.pages, sizeof(time_t))) == NULL)
  1178. X            || ((time_pend = (time_t *)calloc(fax.pages, sizeof(time_t))) == NULL))
  1179. X            return(fax_tlog(ERROR, logfp, "sendfax: can't allocate memory\n"));
  1180. X
  1181. X        if (plug(devnam,lcknam))
  1182. X            return;        /* errs logged already */
  1183. X
  1184. X                /* force sync with modem */
  1185. X                /* sometimes it talks gibberish */
  1186. X        strcpy(wbuf, "ATE0V0\r\n");
  1187. X        do
  1188. X        {
  1189. X            if (to_modem(wbuf))
  1190. X                break;
  1191. X            if ((c = modem_c_ans(OK,8)) == 0 && i)
  1192. X                break;
  1193. X        } while (i++ < 5);
  1194. X        if (c || cannot)
  1195. X        {
  1196. X            fax_tlog(ERROR, logfp, "sendfax: can't sync with modem\n");
  1197. X            return(unplug(devnam, lcknam));
  1198. X        }
  1199. X
  1200. X        sprintf(wbuf, "ATX4M%d#A0#B%c#E1#P%d#R%d#K%d#F1\r\n",
  1201. X            SPEAKER, Topspeed[dev_no], fax.pages, fax.hires, FLOW_CTL);
  1202. X
  1203. X        if (to_modem(wbuf) || modem_c_ans(OK,8))
  1204. X        {
  1205. X            fax_tlog(ERROR, logfp, "sendfax: %s missing after #F1\n",
  1206. X                sierra_cmds[OK].txtstring);
  1207. X            return(unplug(devnam, lcknam));
  1208. X        }
  1209. X
  1210. X        if (faxmode(devnam,lcknam))    /* errlogging done already */
  1211. X            return(unplug(devnam, lcknam));
  1212. X        sleep(2);
  1213. X
  1214. X        sprintf(wbuf, "ATD%c%s\r\n",Dialtyp[dev_no], fax.phone[curjob]);
  1215. X        if (to_modem(wbuf))
  1216. X        {
  1217. X            fax_tlog(ERROR, logfp, "sendfax: can't dial\n");
  1218. X            return(unplug(devnam, lcknam));
  1219. X        }
  1220. X/*
  1221. X    I don't know if 3*strlen(phone_no) is enough of a delay. Although tone 
  1222. X    dialling the us is often instant [like nyc], some places in the uk 
  1223. X    don't benefit from tone dial speed [yet]. When dialling germany I can 
  1224. X    make some coffee, and get a news paper before I hear ok [or busy]
  1225. X
  1226. X    Also note that "BUSY" is not recognised as such outside the US
  1227. X*/
  1228. X        if ((c = modem_c_ans(ANSWER_TONE, 15+(3*strlen(fax.phone[curjob])) ))
  1229. X                == sierra_cmds[OK].retcode)
  1230. X        {
  1231. X            c = modem_c_ans(ANSWER_TONE,15+(3*strlen(fax.phone[curjob])));
  1232. X            /* it's possible the modem sends OK after receiving phone no */
  1233. X        }
  1234. X
  1235. X        if (c == sierra_cmds[BUSY].retcode)
  1236. X        {
  1237. X            fax_tlog(5, logfp, "sendfax: %s BUSY\n",fax.phone[curjob]);
  1238. X            unplug(devnam,lcknam);
  1239. X            fflush(logfp);
  1240. X            sleep(5);
  1241. X            ++curjob;
  1242. X            continue;
  1243. X        }
  1244. X        else if (c)
  1245. X        {
  1246. X            /* could be non USA BUSY */
  1247. X            /* NEED TO WATCH THIS */
  1248. X
  1249. X            for (i=0; i<LAST_SIERRA_ANS; i++)
  1250. X                if (c == sierra_cmds[i].retcode)
  1251. X                    break;
  1252. X            fax_tlog(3, logfp, "sendfax: can't connect, have %s instead of ANSWER TONE for %s\n",
  1253. X                sierra_cmds[i].txtstring,fax.phone[curjob]);
  1254. X            unplug(devnam,lcknam);
  1255. X            fflush(logfp);
  1256. X            sleep(5);
  1257. X            ++curjob;
  1258. X            ++failed;
  1259. X            continue;
  1260. X        }
  1261. X        time_connect = time((time_t *)NULL);
  1262. X
  1263. X        if (get_frame())        /* read hldc frame */
  1264. X        {
  1265. X            fax_tlog(ERROR, logfp, "sendfax: not a legal hldc frame on %s\n",
  1266. X                fax.phone[curjob]);
  1267. X            unplug(devnam,lcknam);
  1268. X            fflush(logfp);
  1269. X
  1270. X            if ((!fax.tries) && (fax.phone_nos > 1))
  1271. X            {
  1272. X                if (!fork_off())
  1273. X                {
  1274. X                    free(fax.phone[curjob]);
  1275. X                    fax.phone[curjob] = NULL;
  1276. X                }
  1277. X                else break;     /* something's seriously wrong */
  1278. X            }            /* give up to avoid desaster */
  1279. X            sleep(5);
  1280. X            ++curjob;
  1281. X            ++failed;
  1282. X            continue;
  1283. X        }
  1284. X
  1285. X        if (get_remote_cap())    /* read remote capabilities */
  1286. X        {            /* might include identification [ignored] */
  1287. X            fax_tlog(ERROR, logfp, "sendfax: can't get remote capabilities on %s\n",
  1288. X                fax.phone[curjob]);
  1289. X            unplug(devnam,lcknam);
  1290. X            fflush(logfp);
  1291. X
  1292. X            if ((!fax.tries) && (fax.phone_nos > 1))
  1293. X            {
  1294. X                if (!fork_off())
  1295. X                {
  1296. X                    free(fax.phone[curjob]);
  1297. X                    fax.phone[curjob] = NULL;
  1298. X                }
  1299. X                else break;     /* something's seriously wrong */
  1300. X            }            /* give up to avoid desaster */
  1301. X            sleep(5);
  1302. X            ++curjob;
  1303. X            ++failed;
  1304. X            continue;
  1305. X        }
  1306. X
  1307. X        if (get_connect())
  1308. X        {
  1309. X            fax_tlog(ERROR, logfp, "sendfax: can't get CONNECT on %s\n",
  1310. X                fax.phone[curjob]);
  1311. X            unplug(devnam,lcknam);
  1312. X            sleep(5);
  1313. X            ++curjob;
  1314. X            ++failed;
  1315. X            continue;
  1316. X        }
  1317. X        set_minlen(have_connect);
  1318. X
  1319. X        for (curpage=0; curpage<fax.pages;curpage++)
  1320. X        {
  1321. X            time_pstart[curpage] = time((time_t *)NULL);
  1322. X            sprintf(biff,"%s.g3.%d",fax.dname,curpage);
  1323. X            if ((fp = fopen(biff, "r")) == NULL)
  1324. X            {
  1325. X                unplug(devnam, lcknam);
  1326. X                fax_tlog(ERROR, logfp, "sendfax: can't open %s for %s\n",
  1327. X                    biff, fax.phone[curjob]);
  1328. X                return;    /* we're buggered somehow */
  1329. X            }
  1330. X
  1331. X#ifndef    USE_IXON;    /* else when using ixon/xoff, read XON before setting flow ctl */
  1332. X            if (set_ixon(TRUE,devnam,lcknam))
  1333. X            {
  1334. X                porterr = joberr = ERROR;
  1335. X                break;
  1336. X            }
  1337. X#endif
  1338. X
  1339. X        /* max tx time per full a4 page at 9k6 is < 60 secs */
  1340. X        /* alarm settings are based on 60 secs * 1.5, seems ok */
  1341. X            if (have_connect == CONNECT_24)
  1342. X                alarm(360);
  1343. X            else if (have_connect == CONNECT_48)
  1344. X                alarm(180);
  1345. X            else if (have_connect == CONNECT_72)
  1346. X                alarm(135);
  1347. X            else alarm(90);
  1348. X
  1349. X#ifdef    USE_IXON    /* you're out of luck on a sun, don't know about others */
  1350. X            fax_tlog(9, logfp, "sendfax: waiting for initial XON\n");
  1351. X            rxbuf[0] = '\0';
  1352. X            for (;;)
  1353. X            {
  1354. X                if (read(ser_port, rxbuf, 1) == 1)
  1355. X                    if (rxbuf[0] == XON_CHAR)
  1356. X                        break;
  1357. X            }
  1358. X            fax_tlog(9, logfp, "sendfax: GOT THAT\n");
  1359. X                /* have ixon, use flow ctl now */
  1360. X            if (set_ixon(TRUE,devnam,lcknam))
  1361. X            {
  1362. X                porterr = ERROR;
  1363. X                break;
  1364. X            }
  1365. X
  1366. X            for (i=0; i<MAX_FAX_LINES; i++)
  1367. X            {
  1368. X                if ((len = getline(fp,txbuf,line_minlen)) == EOF)
  1369. X                    break;
  1370. X                for (c=0; c<len; c++)
  1371. X                    if (write(ser_port, &txbuf[c], 1) != 1)
  1372. X                    {
  1373. X                        porterr = joberr = ERROR;
  1374. X                        fax_tlog(ERROR, logfp, "sendfax: can't write %d bytes to %s in page %d\n",
  1375. X                            len,devnam,curpage);
  1376. X                        break;
  1377. X                    }
  1378. X                if (porterr)
  1379. X                    break;
  1380. X            }
  1381. X#else    /* !USE_IXON, far less wear 'n tear, use it if you can */
  1382. X            for (i=0; i<MAX_FAX_LINES; i++)
  1383. X            {
  1384. X                if ((len = getline(fp,txbuf,line_minlen)) == EOF)
  1385. X                    break;
  1386. X                if (write(ser_port, txbuf, len) != len)
  1387. X                {
  1388. X                    sleep(2);    /* force modem to time out, 1/10 sec is enough */
  1389. X                    porterr = joberr = ERROR;
  1390. X                    fax_tlog(ERROR, logfp, "sendfax: can't write %d bytes to %s in page %d\n",
  1391. X                        len,devnam,curpage);
  1392. X                    break;
  1393. X                }
  1394. X            }
  1395. X#endif    /* use_ixon */
  1396. X            alarm(0);
  1397. X            fclose(fp);
  1398. X            fax_tlog(9, logfp, "sendfax: %d scanlines sent\n",i);
  1399. X
  1400. X            if (set_ixon(FALSE,devnam,lcknam))
  1401. X            {
  1402. X                porterr = ERROR; /*errs logged already */
  1403. X                break;
  1404. X            }
  1405. X
  1406. X            if (!porterr)
  1407. X                c = modem_str_ans(MSG_CONFMD, 20, TRUE);
  1408. X            else c = porterr;
  1409. X
  1410. X            time_pend[curpage] = time((time_t *)NULL);
  1411. X            if (c == sierra_cmds[RETRAIN].retcode)
  1412. X            {
  1413. X                --curpage;
  1414. X                ++tot_resends;
  1415. X                if (++resend_cnt == MAX_RESEND)
  1416. X                {
  1417. X                    joberr = TRUE;
  1418. X                    fax_tlog(ERROR, logfp, "sendfax: TOO MANY RESENDS, I've had it\n");
  1419. X                    break;
  1420. X                }
  1421. X            }
  1422. X            else if (c == sierra_cmds[NO_CARRIER].retcode)
  1423. X            {
  1424. X                fax_tlog(ERROR, logfp, "sendfax: NO CARRIER after page %d of %d\n",
  1425. X                    1+curpage, fax.pages);
  1426. X                joberr = TRUE;
  1427. X                alive = FALSE;
  1428. X                break;
  1429. X            }
  1430. X            else if (c != sierra_cmds[MSG_CONFMD].retcode
  1431. X                && c != sierra_cmds[RTRN_OK].retcode)
  1432. X            {
  1433. X                for (i=0; i<LAST_SIERRA_ANS; i++)
  1434. X                    if (c == sierra_cmds[i].retcode)
  1435. X                        break;
  1436. X                fax_tlog(ERROR, logfp, "sendfax: unexpected response %s after page %d of %d\n",
  1437. X                    sierra_cmds[i].txtstring,curpage+1,fax.pages);
  1438. X                joberr = TRUE;
  1439. X                alive = FALSE;
  1440. X                break;
  1441. X            }
  1442. X            else
  1443. X            {
  1444. X                fax_tlog(5, logfp, "sendfax: page %d of %d confirmed\n",
  1445. X                    curpage+1,fax.pages);
  1446. X                confirms++;
  1447. X                resend_cnt = 0;
  1448. X            }
  1449. X        }
  1450. X
  1451. X/*
  1452. X    if we're still online, allow faxmodem to diconnect gracefully
  1453. X    at the other end, otherwise some fax machines remain in an
  1454. X    error condition barring further use. You're not gaining
  1455. X    popularity by jamming other people's fax toys
  1456. X*/
  1457. X        if (alive)
  1458. X            (void)modem_str_ans(NO_CARRIER, 20, TRUE);
  1459. X        time_hangup = time((time_t *)NULL);
  1460. X
  1461. X        unplug(devnam,lcknam);
  1462. X
  1463. X        fax_tlog(0, logfp, 
  1464. X        "sendfax: fax to %s, connect at %s\n",
  1465. X            fax.phone[curjob],faxtime(time_connect));
  1466. X        for (i=0; i<fax.pages; i++)
  1467. X        {
  1468. X            if ((!time_pstart[i]) || (!time_pend[i]))
  1469. X                break;
  1470. X                /* *faxtime() is static, stash away first use */
  1471. X            sprintf(biff,"%s, %ld secs\n",
  1472. X                faxtime(time_pend[i]),
  1473. X                (time_pend[i]-time_pstart[i]));
  1474. X            fax_tlog(0, logfp, 
  1475. X                "sendfax: fax to %s, page %d, %s to %s",
  1476. X                fax.phone[curjob], i+1,
  1477. X                faxtime(time_pstart[i]),biff);
  1478. X        }
  1479. X        if (!tot_resends)
  1480. X            fax_tlog(0, logfp, 
  1481. X                "sendfax: %s%s, connect time %ld secs\n",
  1482. X                (confirms==fax.pages)?"SUCCESSFUL: ":"",
  1483. X                fax.phone[curjob],
  1484. X                (time_hangup-time_connect));
  1485. X        else fax_tlog(0, logfp, 
  1486. X            "sendfax: %s%s, %d RESENDS, connect time %ld secs\n",
  1487. X            (confirms==fax.pages)?"SUCCESSFUL: ":"",
  1488. X            fax.phone[curjob],
  1489. X            tot_resends,
  1490. X            (time_hangup-time_connect));
  1491. X
  1492. X        if (joberr)
  1493. X        {
  1494. X            ++failed;
  1495. X            if ((!fax.tries) && (fax.phone_nos > 1))
  1496. X            {
  1497. X                if (!fork_off())
  1498. X                {
  1499. X                    free(fax.phone[curjob]);
  1500. X                    fax.phone[curjob] = NULL;
  1501. X                }
  1502. X                else break;
  1503. X            }
  1504. X        }
  1505. X        else
  1506. X        {
  1507. X            ++sent;
  1508. X            free(fax.phone[curjob]);
  1509. X            fax.phone[curjob] = NULL;
  1510. X        }
  1511. X
  1512. X        free(time_pstart);
  1513. X        free(time_pend);
  1514. X        ++curjob;
  1515. X        fflush(logfp);
  1516. X        sleep(5);    /* let the dust settle */
  1517. X    }
  1518. X}
  1519. Xmodem_c_ans(want,secs)
  1520. Xint want, secs;
  1521. X{
  1522. X    int nread, rlen;
  1523. X    static int fst;
  1524. X    char fred[4];
  1525. X
  1526. X    fax_tlog(9, logfp, "sendfax: %swant %s, secs %d, attempt %d\n",
  1527. X        FUNCTION("modem_c_ans, "),sierra_cmds[want].txtstring,secs,fst);
  1528. X
  1529. X    rxbuf[0] = '\0';
  1530. X    errno = nread = rlen = 0;
  1531. X    alarm(secs);
  1532. X    nread = read(ser_port, rxbuf, 6);
  1533. X    alarm(0);
  1534. X
  1535. X    nread = max(nread,0);    /* don't set rxbuf[-1] to '\0' on error */
  1536. X    rxbuf[nread] = '\0';
  1537. X    if (asclen(rxbuf) == 0 && (fst++ < 3))
  1538. X        return(modem_c_ans(want,secs));
  1539. X    fst = 0;
  1540. X
  1541. X    /* since this is ascii directly from the modem it's quite safe */
  1542. X    if (strchr(rxbuf, sierra_cmds[want].retcode) == NULL)
  1543. X    {
  1544. X        if (blah == 9)
  1545. X        {
  1546. X            sprintf(biff, "sendfax: NOPE {%d bytes} ",nread);
  1547. X            for (rlen=0; rlen<nread; rlen++)
  1548. X            {
  1549. X                sprintf(fred,"%02x",rxbuf[rlen]);
  1550. X                strcat(biff, fred);
  1551. X            }
  1552. X            strcat(biff, "\n");
  1553. X            fax_tlog(9, logfp, biff);
  1554. X        }
  1555. X        return((rxbuf[0]) ? rxbuf[0] : ERROR);
  1556. X    }
  1557. X    fax_tlog(9, logfp, "sendfax: GOT THAT\n",errno);
  1558. X    return(0);
  1559. X}
  1560. Xmodem_str_ans(want,secs,newlot)
  1561. Xint want, secs, newlot;
  1562. X{
  1563. X    int nread, i, have, redo, left_marker, rite_marker;
  1564. X    static int fst;
  1565. X    char fred[4];
  1566. X
  1567. X    errno = nread = 0;
  1568. X    if (newlot)
  1569. X        fst = 0;
  1570. X    for (i=0; i<128; i++)
  1571. X        rxbuf[i] = '\0';
  1572. X
  1573. X    fax_tlog(9, logfp, "sendfax: %swant %s, secs %d, attempt %d\n",
  1574. X        FUNCTION("modem_str_ans, "),sierra_cmds[want].txtstring,secs,fst);
  1575. X    alarm(secs);
  1576. X    nread = read(ser_port, rxbuf, 128);
  1577. X    alarm(0);
  1578. X
  1579. X    nread = max(nread,0);
  1580. X    rxbuf[nread] = '\0';
  1581. X
  1582. X    have = left_marker = rite_marker = ERROR;
  1583. X    if (nread)
  1584. X    {            /* do we have in rxbuf what we want ? */
  1585. X        if (rxbuf[0] == sierra_cmds[want].retcode)
  1586. X            have = TRUE;
  1587. X                            /* check it's outside frame data markers */
  1588. X        left_marker = strnpos(rxbuf, MARKER, 0, nread);
  1589. X        rite_marker = strnrpos(rxbuf, MARKER, max(0,left_marker), nread);
  1590. X    }
  1591. X
  1592. X    if (blah == 9)
  1593. X    {
  1594. X        sprintf(biff, "sendfax: read {%d bytes} ",nread);
  1595. X        for (i=0; i<nread; i++)
  1596. X        {
  1597. X            if (i == left_marker)
  1598. X                strcat(biff, "{");
  1599. X            sprintf(fred,"%02x",rxbuf[i]);
  1600. X            strcat(biff, fred);
  1601. X            if (i == rite_marker)
  1602. X                strcat(biff, "}");
  1603. X            if (i && (!(i % 32)))
  1604. X                strcat(biff, "\n");
  1605. X        }
  1606. X        strcat(biff, "\n");
  1607. X        fax_tlog(9, logfp, biff);
  1608. X    }
  1609. X                /* not found, or within frame data */
  1610. X    if (have == ERROR)
  1611. X    {
  1612. X        if (nread)
  1613. X        {
  1614. X            if (rxbuf[0] == sierra_cmds[NO_CARRIER].retcode)
  1615. X                return(sierra_cmds[NO_CARRIER].retcode);
  1616. X
  1617. X            redo = FALSE;
  1618. X            if (rxbuf[0] == sierra_cmds[RETRAIN].retcode)
  1619. X            {
  1620. X                redo = sierra_cmds[RETRAIN].retcode;
  1621. X                fax_tlog(5, logfp, "sendfax: REQUEST to RESEND page %d of %d\n",
  1622. X                    1+curpage, fax.pages);
  1623. X            }
  1624. X            else if (rxbuf[0] == sierra_cmds[RTRN_OK].retcode)
  1625. X            {
  1626. X                fax_tlog(5, logfp, "sendfax: retrained successful after page %d of %d\n",
  1627. X                    1+curpage, fax.pages);
  1628. X
  1629. X                if (1+curpage == fax.pages)
  1630. X                    return(sierra_cmds[want].retcode);
  1631. X                redo = sierra_cmds[RTRN_OK].retcode;
  1632. X            }
  1633. X
  1634. X            if (redo)
  1635. X            {
  1636. X                dial_tries = 0;
  1637. X                have_cfr = have_connect = 0;
  1638. X                if ((i = get_connect()) == 0)
  1639. X                    return(redo);
  1640. X                return(i);
  1641. X            }
  1642. X        }
  1643. X        if (++fst >= 8)
  1644. X            return(ERROR);
  1645. X        return(modem_str_ans(want,secs,0));
  1646. X    }
  1647. X    fax_tlog(9, logfp, "sendfax: GOT THAT\n",errno);
  1648. X    fst = 0;
  1649. X    return(sierra_cmds[want].retcode);
  1650. X}
  1651. Xget_frame()
  1652. X{
  1653. X    int i, nread, Nread, framestart, left_marker, rite_marker;
  1654. X    unsigned char timebyte;
  1655. X    char fred[4];
  1656. X
  1657. X    /*
  1658. X    here's some typical "hdlc frames" as received from two
  1659. X    fax machines, including the training and retraining session
  1660. X
  1661. X    nread = 121
  1662. X    0d0a7effc004000088005182080404040404040404040404040404040400e800
  1663. X    00748d7effc800721d0071247effffff7e0d0a620d0d0a7effc82157be7effff
  1664. X    fc7e0d0a670d7a0d0d0a7effc83275ec7efffffe7e0d0a680d0d0a7effc83275
  1665. X    ec7efffffe7e0d0a680d0d0a7effc82157be7efffffc7e0d0a
  1666. X
  1667. X    nread = 166
  1668. X    0d0a7effc00400008c00731d00e9b0bb0000bbbb0000bbbbbbbbbb8980600068
  1669. X    6224b7c6b7a5b07effc0020404040404040404040404040404040404040404a4
  1670. X    f37effc80100731d0046147e7e7fff7e0d0a6b0d202020202020202020202020
  1671. X    20202020202020200d0a620d0d0a7effc82157be7e7e787e0d0a670d7a0d0d0a
  1672. X    7effc831458f7e7e7c7e0d0a6d0d0d0a7effc831458f7e7e7c7e0d0a6d0d330d
  1673. X    8d0acf4b8d0a
  1674. X
  1675. X    Frames vary in length. What we're looking for is the first substring
  1676. X    containing 7e ff c8. if we're not answering quick enough,
  1677. X    the two gizzmos seem to exchange/repeat some garbage
  1678. X    that we don't need to concern ourselves with. These frames are
  1679. X    rather large because I sat in a loop making the connection time
  1680. X    out on purpose. Expect to see 50 to 120 bytes in real life, though.
  1681. X
  1682. X    I know of one make/model fax machine that does NOT send
  1683. X    "legal" hldc frames. I haven't found a way round this yet.
  1684. X    Ignoring it and assuming worts case seems not to help since
  1685. X    you don't get CFR and CONNECT [in a format that looks ok] either.
  1686. X
  1687. X    This is such a bad frame:
  1688. X    0d0a7e7effc00400008a00000981572e4d617965722042617520476d6248ffff
  1689. X    ffffffffffffffffffffffffff8260ffff0000ea727effc00200000000000000
  1690. X    00000000000000000000000000000000000000000000000000008bef77ef7e0d
  1691. X    0a6b0d0d0a7e7effc00400008a00000981572e4d617965722042617520476d62
  1692. X    48ffffffffffffffffffffffffffffffff8260ffff0000ea727effc002000000
  1693. X    00000000000000000000000000000000000000000000000000008bfeefde8bef
  1694. X    77ef7e0d
  1695. X
  1696. X    */
  1697. X
  1698. X    for (i=0; i<256; i++)    /* I've seen frames THAT long */
  1699. X        rxbuf[i] = '\0';   /* I know there's bcopy, memset etc */
  1700. X                   /* can't be bothered now to ifdef portable */
  1701. X    Nread = errno = 0;
  1702. X    fax_tlog(9, logfp, "sendfax: want frame\n");
  1703. X
  1704. X    alarm(45);    /* just in case */
  1705. X    for (framestart=ERROR; Nread < 512;)    /* and again */
  1706. X    {
  1707. X        if ((nread = read(ser_port, &rxbuf[Nread], 256)) > 0)
  1708. X        {
  1709. X            Nread += nread;
  1710. X            if ((framestart = lastframe(rxbuf, Nread)) >= 0
  1711. X                && framestart <= (Nread-6))
  1712. X                break;
  1713. X        }
  1714. X        if (cannot)    /* alarm went off */
  1715. X            break;
  1716. X    }
  1717. X    alarm(0);
  1718. X
  1719. X    left_marker = strnpos(rxbuf, MARKER, 0, Nread);
  1720. X    rite_marker = strnrpos(rxbuf, MARKER, left_marker, Nread);
  1721. X
  1722. X    if (blah == 9)
  1723. X    {
  1724. X        fax_tlog(9, logfp, "sendfax: framelen %d, start of last frame %d\n",
  1725. X            Nread,framestart);
  1726. X        strcpy(biff,"sendfax: frame data\n");
  1727. X        for (i=0; i<Nread; i++)
  1728. X        {
  1729. X            if (i == left_marker && framestart > -1)
  1730. X                strcat(biff, "{");
  1731. X            else if (i == (framestart + 6) && framestart > -1)
  1732. X                strcat(biff, "->");
  1733. X            sprintf(fred, "%02x",rxbuf[i]);
  1734. X            strcat(biff, fred);
  1735. X            if (i == rite_marker && framestart > -1)
  1736. X                strcat(biff, "}");
  1737. X            if (i && (!(i % 32)))
  1738. X                strcat(biff, "\n");
  1739. X        }
  1740. X        strcat(biff, "\n");
  1741. X        fax_tlog(9, logfp, biff);
  1742. X    }
  1743. X    if (framestart == ERROR || cannot)    /* cannot triggered by alarm */
  1744. X        return(ERROR);        /* framestart == ERROR if no MARKER */
  1745. X
  1746. X    timebyte = rxbuf[framestart+6];
  1747. X    timebyte = (timebyte >> 1) & 0x07; /* only want leftmost 3 bits in rite nibble */
  1748. X    line_minlen = not_so_fast[timebyte];
  1749. X
  1750. X    fax_tlog(9, logfp, "sendfax: min usecs per line %d\n",line_minlen);
  1751. X    return(0);
  1752. X}
  1753. Xget_remote_cap()
  1754. X{
  1755. X    int i, nread;
  1756. X    char fred[8];
  1757. X
  1758. X    for (i=0; i<48; i++)
  1759. X        rxbuf[i] = '\0';
  1760. X
  1761. X    nread = errno = 0;
  1762. X    fax_tlog(9, logfp, "sendfax: want REMOTE CAPABILITIES\n");
  1763. X
  1764. X    alarm(30);    /* just in case */
  1765. X
  1766. X    for (;;)
  1767. X    {
  1768. X        if ((nread = read(ser_port, rxbuf, 48)) <= 0)
  1769. X            return(ERROR);
  1770. X
  1771. X        if (blah == 9)
  1772. X        {
  1773. X            sprintf(biff, "sendfax: read {%d bytes} ",nread);
  1774. X            for (i=0; i<nread; i++)
  1775. X            {
  1776. X                sprintf(fred, "%02x",rxbuf[i]);
  1777. X                strcat(biff, fred);
  1778. X            }
  1779. X            strcat(biff, "\n");
  1780. X            fax_tlog(9, logfp, biff);
  1781. X        }
  1782. X
  1783. X        if (nread >= 1 && rxbuf[0] == sierra_cmds[NO_CARRIER].retcode)
  1784. X            return(sierra_cmds[NO_CARRIER].retcode);
  1785. X        else if (nread == 2 
  1786. X            && rxbuf[0] == sierra_cmds[WHAT_I_CAN].retcode)
  1787. X        {
  1788. X                have_dis = TRUE;
  1789. X                break;
  1790. X        }
  1791. X    }
  1792. X    if (cannot)
  1793. X        return(ERROR);
  1794. X    alarm(0);
  1795. X    fax_tlog(9, logfp, "sendfax: have REMOTE CAPABILITIES\n");
  1796. X    return(0);
  1797. X}
  1798. Xget_connect()
  1799. X{
  1800. X    int nread, i, left_marker, rite_marker;
  1801. X    char fred[4];
  1802. X
  1803. X    errno = 0;
  1804. X    rxbuf[0] = '\0';
  1805. X    if (blah == 9)
  1806. X    {
  1807. X        if (!have_cfr)
  1808. X            sprintf(biff,"sendfax: %swant %s, CONNECT, attempt %d\n",
  1809. X                FUNCTION("get_connect, "),sierra_cmds[CONFIRM_TO_RX].txtstring, dial_tries);
  1810. X        else sprintf(biff,"sendfax: %swant CONNECT, attempt %d\n",
  1811. X            FUNCTION("get_connect, "),dial_tries);
  1812. X        fax_tlog(9, logfp, biff);
  1813. X    }
  1814. X
  1815. X    ++dial_tries;
  1816. X    alarm(25);
  1817. X    nread = read(ser_port, rxbuf, 256);
  1818. X    alarm(0);
  1819. X
  1820. X    left_marker = strnpos(rxbuf, MARKER, 0, nread);
  1821. X    rite_marker = strnrpos(rxbuf, MARKER, max(0,left_marker), nread);
  1822. X
  1823. X    if (blah == 9)
  1824. X    {
  1825. X        sprintf(biff, "sendfax: read {%d bytes} ",nread);
  1826. X        for (i=0; i<nread; i++)
  1827. X        {
  1828. X            if (i == left_marker)
  1829. X                strcat(biff, "{");
  1830. X            sprintf(fred,"%02x",rxbuf[i]);
  1831. X            strcat(biff, fred);
  1832. X            if (i == rite_marker)
  1833. X                strcat(biff, "}");
  1834. X            if (i && (!(i % 32)))
  1835. X                strcat(biff, "\n");
  1836. X        }
  1837. X        strcat(biff, "\n");
  1838. X        fax_tlog(9, logfp, biff);
  1839. X    }
  1840. X
  1841. X    if (nread <= 0)
  1842. X        return(ERROR);
  1843. X    rxbuf[nread] = '\0';
  1844. X
  1845. X    if ((!have_cfr) && rxbuf[0] == sierra_cmds[CONFIRM_TO_RX].retcode)
  1846. X    {
  1847. X        have_cfr = TRUE;
  1848. X        fax_tlog(9, logfp, "sendfax: have %s\n",sierra_cmds[CONFIRM_TO_RX].txtstring);
  1849. X        return(get_connect());
  1850. X    }
  1851. X    else if (rxbuf[0] == sierra_cmds[CRC_IN_FRAME].retcode)
  1852. X    {
  1853. X        fax_tlog(9, logfp, "sendfax: have %s\n",sierra_cmds[CRC_IN_FRAME].txtstring);
  1854. X        return(sierra_cmds[CRC_IN_FRAME].retcode);
  1855. X    }
  1856. X    else if (rxbuf[0] == sierra_cmds[NO_CARRIER].retcode)
  1857. X    {
  1858. X        fax_tlog(9, logfp, "sendfax: have %s\n",sierra_cmds[NO_CARRIER].txtstring);
  1859. X        return(sierra_cmds[NO_CARRIER].retcode);
  1860. X    }
  1861. X    else for (i=CONNECT_MIN; i<CONNECT_MAX; i++)
  1862. X    {
  1863. X        if (rxbuf[0] == sierra_cmds[i].retcode && have_cfr)
  1864. X        {
  1865. X            have_connect = sierra_cmds[i].retcode;
  1866. X            fax_tlog(9, logfp, "sendfax: have %s\n",sierra_cmds[i].txtstring);
  1867. X            return(0);
  1868. X        }
  1869. X    }
  1870. X
  1871. X    if (dial_tries < 10)    /* none found */
  1872. X    {
  1873. X        if (rxbuf[0] == sierra_cmds[RETRAIN].retcode)
  1874. X            --dial_tries;
  1875. X        return(get_connect());
  1876. X    }
  1877. X    return(ERROR);        /* pointless, give up */
  1878. X}
  1879. Xset_minlen(c)
  1880. Xint c;
  1881. X{
  1882. X    double bits;
  1883. X    int i, j;
  1884. X
  1885. X    /* line_minlen contains minimum microsecs per line */
  1886. X    /* assume worst case, 2400 baud, we're sending 2.4 bits/usec */
  1887. X    bits = 2.4;
  1888. X
  1889. X    /* at higher speed we're sending more: */
  1890. X    for (i=CONNECT_MIN, j=1; i<CONNECT_MAX; i++, j++)
  1891. X        if (c == sierra_cmds[i].retcode)
  1892. X        {
  1893. X            bits *= (double)j;
  1894. X            break;
  1895. X        }
  1896. X
  1897. X#ifdef    TESTING
  1898. X    if (i == CONNECT_MAX)
  1899. X    {
  1900. X        /* not really necessary, never seen anything strange */
  1901. X        fax_tlog(ERROR, logfp, "sendfax: Ooops - funny connect type %d\n",c);
  1902. X        line_minlen = 80;    /* use a rubber */
  1903. X    }
  1904. X    else
  1905. X#endif
  1906. X    {
  1907. X        bits *= (double)line_minlen;
  1908. X        line_minlen = (int)(bits/8.0) + (((int)(bits)%8)!=0);
  1909. X        /* line_minlen NOW contains min bytes per line */
  1910. X    }
  1911. X    fax_tlog(5, logfp, "sendfax: min bytes per line %d\n",line_minlen);
  1912. X}
  1913. Xgetline(fp,faxbuf,minlen)
  1914. XFILE *fp;
  1915. Xunsigned char *faxbuf;
  1916. Xint minlen;
  1917. X{
  1918. X    int i, c, idx, eol;
  1919. X    static int fst;
  1920. X
  1921. X    if (eof) 
  1922. X    {
  1923. X        eof = fst = FALSE;
  1924. X        return (EOF);
  1925. X    }
  1926. X    if (!fst++)
  1927. X        last1 = cur = 0xff;
  1928. X
  1929. X    for (eol=idx=0; !eol;)
  1930. X    {
  1931. X        if ((c = getc(fp)) == EOF)    /* add eop by hand */
  1932. X        {
  1933. X            eof = TRUE;
  1934. X            return(add_eop(faxbuf, minlen, idx));
  1935. X        }
  1936. X        last1 = cur;
  1937. X        cur = c;
  1938. X
  1939. X        if ((!last1) && cur == 0x01)
  1940. X            eol = TRUE;
  1941. X        else if (eols)
  1942. X        {
  1943. X            if (((!last1) && cur == 0x10) || (last1 == 0x10 && cur == 0x01))
  1944. X                eol = TRUE;
  1945. X        }
  1946. X
  1947. X        if (eol)
  1948. X        {
  1949. X            if (++eols == 6)
  1950. X                eof = TRUE;
  1951. X            else if (eols == 1)
  1952. X            {
  1953. X                faxbuf[idx++] = '\0';
  1954. X                faxbuf[idx++] = '\0';
  1955. X                faxbuf[idx++] = '\0';
  1956. X                if ((i = (minlen - idx)) > 0)
  1957. X                {
  1958. X                    memcpy(&faxbuf[idx], zeros, i);
  1959. X                    idx += i;
  1960. X                }
  1961. X            }
  1962. X        }
  1963. X        else if (cur)
  1964. X            eols = 0;
  1965. X
  1966. X        faxbuf[idx++] = faxbyte[cur];
  1967. X        if (idx >= 1900)
  1968. X        {
  1969. X            fax_tlog(ERROR, logfp, "sendfax: don't think this is a fax file, scanline > %d pels\n",idx);
  1970. X            return(EOF);
  1971. X        }
  1972. X    }
  1973. X    return(idx);
  1974. X}
  1975. Xadd_eop(faxbuf, minlen, idx)
  1976. Xunsigned char *faxbuf;
  1977. Xint minlen, idx;
  1978. X{
  1979. X    int x;
  1980. X
  1981. X    fax_tlog(ERROR, logfp, "sendfax: strange fax file without EOP\n");
  1982. X
  1983. X    faxbuf[idx++] = '\0';
  1984. X    faxbuf[idx++] = '\0';
  1985. X    faxbuf[idx++] = '\0';
  1986. X    if ((x = (minlen - idx)) > 0)
  1987. X    {
  1988. X        memcpy(&faxbuf[idx], zeros, x);
  1989. X        idx += x;
  1990. X    }
  1991. X    memcpy(&faxbuf[idx], eol_pat, sizeof(eol_pat));
  1992. X    return(idx+sizeof(eol_pat));
  1993. X}
  1994. X#endif
  1995. X
  1996. Xto_modem(s)
  1997. Xchar *s;
  1998. X{
  1999. X    int len, written;
  2000. X
  2001. X    fax_tlog(9, logfp, "sendfax: sending %s",s); /* string contains \r\n */
  2002. X    len = strlen(s);
  2003. X    alarm(4);
  2004. X    written = write(ser_port, s, len);
  2005. X    alarm(0);
  2006. X    if (cannot || len != written)
  2007. X        return(ERROR);
  2008. X    sleep(1);
  2009. X    return(0);
  2010. X}
  2011. Xasclen(s)
  2012. Xunsigned char *s;
  2013. X{
  2014. X    unsigned char *d;
  2015. X    int i=0;
  2016. X
  2017. X    d = s;
  2018. X    while (*s)
  2019. X    {
  2020. X        if (*s > ' ')
  2021. X        {
  2022. X            ++i;
  2023. X            *d++ = *s;
  2024. X        }
  2025. X        ++s;
  2026. X    }
  2027. X    *d = '\0';
  2028. X    return(i);
  2029. X}
  2030. END_OF_FILE
  2031.   if test 41916 -ne `wc -c <'faxhost/wiring.c'`; then
  2032.     echo shar: \"'faxhost/wiring.c'\" unpacked with wrong size!
  2033.   fi
  2034.   # end of 'faxhost/wiring.c'
  2035. fi
  2036. echo shar: End of archive 1 \(of 5\).
  2037. cp /dev/null ark1isdone
  2038. MISSING=""
  2039. for I in 1 2 3 4 5 ; do
  2040.     if test ! -f ark${I}isdone ; then
  2041.     MISSING="${MISSING} ${I}"
  2042.     fi
  2043. done
  2044. if test "${MISSING}" = "" ; then
  2045.     echo You have unpacked all 5 archives.
  2046.     rm -f ark[1-9]isdone
  2047. else
  2048.     echo You still must unpack the following archives:
  2049.     echo "        " ${MISSING}
  2050. fi
  2051. exit 0
  2052. exit 0 # Just in case...
  2053.