source: trunk/third/transcript/src/psfax.c @ 9090

Revision 9090, 15.5 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9089, which included commits to RCS files with non-trunk default branches.
RevLine 
[9089]1#ifndef lint
2#define _NOTICE static char
3_NOTICE N1[] = "Copyright (c) 1992  Adobe Systems Incorporated";
4_NOTICE N2[] = "GOVERNMENT END USERS: See Notice file in TranScript library directory";
5_NOTICE N3[] = "-- probably /usr/lib/ps/Notice";
6_NOTICE RCSID[]="$Header: /afs/dev.mit.edu/source/repository/third/transcript/src/psfax.c,v 1.1.1.1 1996-10-07 20:25:51 ghudson Exp $";
7#endif
8/* psfax.c
9 *
10 * Copyright (C) 1992 Adobe Systems Incorporated. All
11 *  rights reserved.
12 * GOVERNMENT END USERS: See Notice file in TranScript library directory
13 * -- probably /usr/lib/ps/Notice
14 *
15 * $Log: not supported by cvs2svn $
16 * Revision 1.10  1993/11/22  21:28:44  snichols
17 * only process list of keys once, and keep the zero'th entry of
18 * faxopts for common keys on multicast; start multicast entries at 1.
19 *
20 * Revision 1.9  1993/05/18  21:37:48  snichols
21 * fixed memory-smasher on Sparcs.
22 *
23 * Revision 1.8  1992/10/15  22:12:32  snichols
24 * should be opening output file for writing, not reading.
25 *
26 * Revision 1.7  1992/08/21  16:26:32  snichols
27 * Release 4.0
28 *
29 * Revision 1.6  1992/07/14  22:00:50  snichols
30 * Added copyright
31 *
32 */
33#include <stdio.h>
34#ifdef XPG3
35#include <stdlib.h>
36#else
37#include "compat.h"
38#endif
39#include <string.h>
40#include <sys/wait.h>
41
42#include "transcript.h"
43#include "config.h"
44
45#define TRUE 1
46#define FALSE 0
47
48
49extern char *optarg;
50extern int optind;
51
52extern char *lp;
53
54char list[100][50];             /* holder for parsing keys in list */
55int numlist=0;
56
57FILE *db, *doc, *output;
58
59char *dbfile = NULL;
60char defdbfile[255];
61char *infile = NULL;
62char *outfile = NULL;
63char *printername = NULL;
64char *dialcallee;
65char *toname;
66
67int fdin, fdout;
68
69struct entry{
70    char option[128];
71    char value[256];
72    int filename;
73};
74
75struct listopts {
76    int numopts;                /* number of options for this entry */
77    int maxopts;                /* number allocated */
78    struct entry **opts;        /* list of options */
79} **faxopts;                    /* a list, for multicast */
80                                /* if not multicast, all options are in the
81                                   zero'th entry; if multicast, zero'th
82                                   entry contains the options in common
83                                   among all the recipients */
84
85int numfaxopts = 1;             /* number of faxopts entries */
86int maxfaxopts = 1;             /* number allocated */
87int multicast = FALSE;
88int sendps = FALSE;
89int usedb = TRUE;
90int treatasstrings=TRUE;
91
92char *comopts[20];              /* options from command line */
93int ncomopts = 0;
94
95typedef enum {string, integer, boolean, procedure, arrayint,
96                             arraydict} valueTypes;
97#define NUMOPTS 30
98
99struct _optionTypes {           /* table for outputting various options */
100    char *name;
101    valueTypes valueType;
102    char *begin;
103    char *end;
104} optionTypes[NUMOPTS] = {
105    { "nooptionstr", string, "(", ")" },
106    { "nooptionlit", integer, "", "" },
107    { "DialCallee", string, "(", ")" },
108    { "RecipientName", string, "(", ")" },
109    { "RecipientPhone", string, "(", ")" },
110    { "RecipientOrg", string, "(", ")" },
111    { "RecipientMailStop", string, "(", ")" },
112    { "RecipientID", string, "(", ")" },
113    { "SenderName", string, "(", ")" },
114    { "SenderPhone", string, "(", ")" },
115    { "SenderOrg", string, "(", ")" },
116    { "SenderMailStop", string, "(", ")" },
117    { "SenderID", string, "(", ")" },
118    { "CallerID", string, "(", ")" },
119    { "CalleePhone", string, "(", ")" },
120    { "CallerPhone", string, "(", ")" },
121    { "FaxType", integer, "", "" },
122    { "ErrorCorrect", boolean, "", "" },
123    { "TrimWhite", boolean, "", "" },
124    { "PageCaption", procedure, "{", "}" },
125    { "MaxRetries", integer, "", "" },
126    { "RetryInterval", integer, "", "" },
127    { "MailingTime", arrayint, "[", "]" },
128    { "CoverSheet", procedure, "{", "}" },
129    { "Confirmation", procedure, "{", "}" },
130    { "nPages", integer, "", "" },
131    { "CoverSheetOnly", boolean, "", "" },
132    { "RevertToRaster", boolean, "", "" },
133    { "PostScriptPassword", string, "(", ")" },
134    { "Copies", arraydict, "[", "]" }
135};
136
137/* forward dec'ls */
138
139static struct listopts *NewFaxOpt();
140static void AddOption();
141static int FindOption();
142static void HandleGroup();
143static int FindEntry();
144
145static char *myrealloc(ptr, size)
146    char *ptr;
147    int size;
148{
149    char *ret;
150
151    if (ptr == NULL) return malloc(size);
152    ret = (char *)realloc(ptr, (unsigned) size);
153    if (ret) return ret;
154    fprintf(stderr, "realloc failed\n");
155    exit(1);
156    return NULL;
157}
158
159static void HandleCommandLineOptions(opt)
160    char *opt;
161{
162    char *option, *value;
163   
164    option = opt;
165    value = strchr(option, '=');
166    if (value) {
167        *value = '\0';
168        value++;
169        AddOption(0, option, value, 0);
170    }
171    else {
172        value = strchr(option, ':');
173        if (value) {
174            *value = '\0';
175            value++;
176            AddOption(0, option, value, 1);
177        }
178    }
179}
180
181static int LookupOpt(opt)
182    char *opt;
183{
184    int i;
185
186    for (i = 0; i < NUMOPTS; i++) {
187        if (strcmp(opt, optionTypes[i].name) == 0)
188            return i;
189    }
190    if (treatasstrings)
191        return 0;
192    else
193        return 1;
194}
195
196static void DumpOpts(out)
197    FILE *out;
198{
199    int i,j;
200    FILE *fp;
201    char buf[1024];
202    int ndex;
203
204    for (j = 0; j < faxopts[0]->numopts; j++) {
205        ndex = LookupOpt(faxopts[0]->opts[j]->option);
206        if (faxopts[0]->opts[j]->filename) {
207            if ((fp = fopen(faxopts[0]->opts[j]->value, "r")) == NULL) {
208                fprintf(stderr, "Couldn't open file %s\n",
209                        faxopts[0]->opts[j]->value);
210                exit(1);
211            }
212            fprintf(out, "/%s ", faxopts[0]->opts[j]->option);
213            fprintf(out, "%s\n",optionTypes[ndex].begin);
214            while (fgets(buf, 1024, fp))
215                fputs(buf, out);
216            fprintf(out, "%s def\n", optionTypes[ndex].end);
217        }
218        else {
219            fprintf(out, "/%s %s%s%s def\n", faxopts[0]->opts[j]->option,
220                    optionTypes[ndex].begin, faxopts[0]->opts[j]->value,
221                    optionTypes[ndex].end);
222        }
223    }
224    if (multicast) {
225        /* build copies array */
226        fprintf(out, "/Copies [\n");
227        for (i = 1; i < numfaxopts; i++) {
228            if (i > 1) fprintf(out, "\n");
229            fprintf(out, "<<");
230            for (j = 0; j < faxopts[i]->numopts; j++) {
231                if (j > 0) fprintf(out, "\n");
232                ndex = LookupOpt(faxopts[i]->opts[j]->option);
233                if (faxopts[i]->opts[j]->filename) {
234                    if ((fp = fopen(faxopts[i]->opts[j]->value, "r")) ==
235                        NULL) { 
236                        fprintf(stderr, "Couldn't open file %s\n",
237                                faxopts[i]->opts[j]->value);
238                        exit(1);
239                    }
240                    fprintf(out, "/%s %s\n", faxopts[i]->opts[j]->option,
241                            optionTypes[ndex].begin); 
242                    while (fgets(buf, 1024, fp))
243                        fputs(buf, out);
244                    fprintf(out, "%s", optionTypes[ndex].end);
245                }
246                else {
247                    fprintf(out, "/%s %s%s%s",
248                            faxopts[i]->opts[j]->option,
249                            optionTypes[ndex].begin,
250                            faxopts[i]->opts[j]->value,
251                            optionTypes[ndex].end);
252                }
253            }
254            fprintf(out, ">>\n");
255        }
256        fprintf(out, "] def\n");
257    }
258}
259       
260static void DumpPS(out)
261    FILE *out;
262{
263
264    fprintf(out, "currentfile %d dict dup begin\n",
265            faxopts[0]->numopts+multicast+5);
266    DumpOpts(out);
267    fprintf(out, "end\n");
268    fprintf(out, "/FaxOps /ProcSet findresource /faxsendps get exec\n");
269}
270
271static void DumpFax(out)
272    FILE *out;
273{
274
275    fprintf(out, "2 dict dup begin /OutputDevice (Fax) def\n");
276    fprintf(out, "/FaxOptions %d dict dup begin\n",
277            faxopts[0]->numopts+multicast+5);
278    DumpOpts(out);
279    fprintf(out, "end def end setpagedevice\n");
280}
281
282static void HandleList(s)
283    char *s;
284{
285    char *p, *q;
286
287    p = s;
288    while (*p == ' ') p++;
289
290    q = p;
291    while ((p = strchr(q, ',')) != NULL) {
292        *p = '\0'; p++;
293        while (*p == ' ') p++;
294        strcpy(list[numlist++], q);
295        q = p;
296    }
297    /* get last one */
298    strcpy(list[numlist++], q);
299}
300     
301#define ARGS "P:k:d:f:s:p:n:tlc"
302
303main(argc, argv)
304    int argc;
305    char **argv;
306{
307    char *key;
308    char *p;
309    char c;
310    int i;
311    char buf[1024];
312    int cnt;
313    int dumped = FALSE;
314    int fdpipe[2];
315    int spid;
316    int status;
317    char *tmp;
318
319    while ((c = getopt(argc, argv, ARGS)) != EOF) {
320        switch (c) {
321        case 'k':
322            key = optarg;
323            if ((p = strchr(key, ',')) != NULL) {
324                /* list of keys */
325                HandleList(key);
326                key = NULL;
327            }
328            break;
329        case 'f':
330            dbfile = optarg;
331            break;
332        case 'd':
333            /* DialCallee string */
334            dialcallee = optarg;
335            break;
336        case 'S':
337            comopts[ncomopts++] = optarg;
338            break;
339        case 't':
340            sendps = TRUE;
341            break;
342        case 'c':
343            usedb = FALSE;
344            break;
345        case 'n':
346            toname = optarg;
347            break;
348        case 'l':
349            treatasstrings = FALSE;
350            break;
351        case 'P':
352            printername = optarg;
353            break;
354        case 'p':
355            outfile = optarg;
356            break;
357        }
358    }
359
360    if (argc > optind)
361        infile = argv[optind];
362    else infile = NULL;
363    faxopts = (struct listopts **)malloc(sizeof(struct listopts *));
364    faxopts[0] = (struct listopts *)NewFaxOpt();
365    if (usedb) {
366        if (dbfile == NULL) {
367            tmp = getenv("PSFAXDB");
368            if (tmp) {
369                dbfile = tmp;
370            }
371            else {
372                tmp = getenv("HOME");
373                if (tmp) {
374                    strcpy(defdbfile, tmp);
375                    strcat(defdbfile, "/.faxdb");
376                    dbfile = defdbfile;
377                }
378            }
379        }
380        if ((db = fopen(dbfile, "r")) == NULL) {
381            fprintf(stderr, "psfax: couldn't open fax database file %s.\n",
382                    dbfile);
383            exit(1);
384        }
385        FindEntry(0, "always");
386        if (key) {
387            if (!FindEntry(0, key)) {
388                fprintf(stderr, "psfax: couldn't find entry for %s.\n", key);
389                exit(1);
390            }
391        }
392    }
393    if (dialcallee)
394        AddOption(0, "DialCallee", dialcallee, 0);
395    if (toname)
396        AddOption(0, "RecipientName", toname, 0);
397
398    for (i = 0; i < ncomopts; i++)
399        HandleCommandLineOptions(comopts[i]);
400
401    if (numlist > 0)
402        HandleGroup();
403
404    if (FindOption(0, "DialCallee") == -1) {
405        if (!multicast)  {
406            fprintf(stderr, "psfax: Must specify DialCallee field!\n");
407            exit(1);
408        }
409        else {
410            for (i = 1; i < numfaxopts; i++) {
411                if (FindOption(i, "DialCallee") == -1) {
412                    fprintf(stderr, "psfax: Must specify DialCallee field!\n");
413                    exit(1);
414                }
415            }
416        }
417    }
418
419    if (sendps && FindOption(0, "PostScriptPassword") == -1) {
420        fprintf(stderr,
421                "psfax: password may be required when sending PostScript.\n");
422    }
423    else doc = stdin;
424    if (printername && !outfile) {
425        /* set up pipe to spooler */
426        if (pipe(fdpipe)) {
427            fprintf(stderr, "psfax: pipe to lpr failed.\n");
428            exit(1);
429        }
430        if ((spid = fork()) < 0) {
431            fprintf(stderr, "psfax: fork failed.\n");
432            exit(1);
433        }
434        if (spid == 0) {
435            /* child process */
436            if (close(0) || (dup(fdpipe[0]) != 0) || close(fdpipe[0]) ||
437                close(fdpipe[1])) {
438                fprintf(stderr, "psfax: child failed.\n");
439                exit(1);
440            }
441            sprintf(buf, "-P%s", printername);
442            execlp(lp, lp, buf, (char *) 0);
443            fprintf(stderr, "psfax: exec of %s failed\n", lp);
444            exit(1);
445        }
446        /* parent */
447        if (close(1) || (dup(fdpipe[1]) != 1) || close(fdpipe[0]) ||
448            close(fdpipe[1])) {
449            fprintf(stderr, "psfax: parent failed.\n");
450            exit(1);
451        }
452        if ((output = fdopen(1, "w")) == NULL) {
453            fprintf(stderr, "psfax: error opening pipe.\n");
454            exit(1);
455        }
456    }
457    else {
458        if (outfile) {
459            if ((output = fopen(outfile, "w")) == NULL) {
460                fprintf(stderr,
461                        "psfax: couldn't open output file %s.\n", outfile);
462                exit(1);
463            }
464        }
465        else output = stdout;
466    }
467    if (infile) {
468        if ((doc = fopen(infile, "r")) == NULL) {
469            fprintf(stderr, "psfax: couldn't open input file %s.\n", infile);
470            exit(1);
471        }
472    }
473    fgets(buf, 1024, doc);
474    if (strncmp(buf, "%!", 2) != 0) {
475        fprintf(stderr, "psfax: input is not PostScript file.\n");
476        exit(1);
477    }
478    fputs(buf, output);
479    if (sendps)
480        DumpPS(output);
481    else
482        DumpFax(output);
483    while (fgets(buf, 1024, doc))
484        fputs(buf, output);
485    fclose(output);
486    wait(&status);
487}
488               
489static struct entry *NewEntry()
490{
491    struct entry *a;
492    unsigned size;
493
494    size = sizeof(struct entry);
495    a = (struct entry *)malloc(size);
496    if (a) {
497        return a;
498    }
499    else {
500        fprintf(stderr, "Error in malloc!");
501        perror("");
502        exit(1);
503    }
504}
505
506static struct listopts *NewFaxOpt()
507{
508    struct listopts *ptr;
509
510    ptr = (struct listopts *)malloc(sizeof(struct listopts));
511    ptr->numopts = 0;
512    ptr->maxopts = 0;
513    ptr->opts = NULL;
514    return ptr;
515}
516
517
518static void AddOption(ndex, option, value, name)
519    int ndex;
520    char *option;
521    char *value;
522    int name;
523{
524    /* if option is already in list, replace with new value;
525       else, add to list. */
526    int i;
527
528    for (i = 0; i < faxopts[ndex]->numopts; i++) {
529        if (!strcmp(faxopts[ndex]->opts[i]->option, option)) {
530            strncpy(faxopts[ndex]->opts[i]->value, value, 256);
531            faxopts[ndex]->opts[i]->filename = name;
532            return;
533        }
534    }
535    if (faxopts[ndex]->numopts >= faxopts[ndex]->maxopts) {
536        /* need more space, get 20 more */
537        faxopts[ndex]->opts =
538            (struct entry **)myrealloc((char *) faxopts[ndex]->opts, 
539                                       (faxopts[ndex]->maxopts *
540                                        sizeof(struct entry *) +
541                                        20*sizeof(struct entry *)));
542        faxopts[ndex]->maxopts += 20;
543    }
544    faxopts[ndex]->opts[faxopts[ndex]->numopts] = NewEntry();
545    strncpy(faxopts[ndex]->opts[faxopts[ndex]->numopts]->option, option, 128);
546    strncpy(faxopts[ndex]->opts[faxopts[ndex]->numopts]->value, value, 256);
547    faxopts[ndex]->opts[faxopts[ndex]->numopts]->filename = name;
548    faxopts[ndex]->numopts++;
549}
550
551static int FindOption(ndex, str)
552    int ndex;
553    char *str;
554{
555    int i;
556
557    for (i = 0; i < faxopts[ndex]->numopts; i++) {
558        if (strcmp(str, faxopts[ndex]->opts[i]->option) == 0) {
559            return i;
560        }
561    }
562    return -1;;
563}
564           
565static void HandleOption(ndex, line)
566    int ndex;
567    char *line;
568{
569    char *p;
570    char *q;
571    int filename = FALSE;
572    char *ptr;
573
574    p = strchr(line, '=');
575    if (p == NULL) {
576        p = strchr(line, ':');
577        if (p == NULL) {
578            fprintf(stderr, "readfdb: ill-formed option line %s\n", line);
579            exit(1);
580        }
581        filename = TRUE;
582    }
583    *p = '\0';
584    p++;
585    while (*p == ' ') p++;
586    if (line[0] == '/') {
587        /* special keyword */
588        q = line;
589        q++;
590        if (strcmp(q, "list") == 0) {
591            /* list of users */
592        }
593        multicast = TRUE;
594        q = p;
595        while ((p = strchr(q, ',')) != NULL) {
596            *p = '\0'; p++;
597            while (*p == ' ') p++;
598            strcpy(list[numlist++], q);
599            q = p;
600        }
601        /* get last one */
602        strcpy(list[numlist++], q);
603    }   
604    else {
605        AddOption(ndex, line, p, filename);
606    }
607}
608
609static int MatchKey(line, key)
610    char *line, *key;
611{
612    char *p, *q;
613    int foundit = FALSE;
614
615    if (strcmp(line, key) == 0)
616        return TRUE;
617    q = line;
618    while ((p = strchr(q, '|')) != NULL) {
619        *p = '\0'; p++;
620        if (strcmp(q, key) == 0) {
621            return TRUE;
622        }
623        q = p;
624    }
625    if (strcmp(q, key) == 0)
626        return TRUE;
627    return FALSE;
628}
629
630static char *myfgets(buf, cnt, fp)
631    char *buf;
632    int cnt;
633    FILE *fp;
634{
635    char *ret;
636    char *p;
637
638    ret = fgets(buf, cnt, fp);
639
640    if (ret) {
641        p = strchr(buf, '\n');
642        if (p) *p = '\0';
643    }
644    return ret;
645}
646
647static void HandleGroup()
648{
649    int i;
650
651    rewind(db);
652    multicast = FALSE; /* for now, to avoid confusing FindEntry */
653    for (i = 0; i < numlist; i++) {
654        if (numfaxopts >= maxfaxopts) {
655            faxopts =
656                (struct listopts **) myrealloc((char *)faxopts,
657                                               (maxfaxopts *
658                                                sizeof(struct listopts *) +
659                                                5*sizeof(struct listopts
660                                                         *)));
661            maxfaxopts += 5;
662        }
663        faxopts[numfaxopts] = (struct listopts *) NewFaxOpt();
664        if (!FindEntry(numfaxopts, list[i])) {
665            fprintf(stderr, "Couldn't find entry for group member %s.\n",
666                    list[i]);
667            exit(1);
668        }
669        numfaxopts++;
670        rewind(db);
671    }
672    multicast = TRUE; /* to notify DumpOptions */
673}
674
675static int FindEntry(ndex, key)
676    int ndex;
677    char *key;
678{
679    char buf[1024];
680    int match = FALSE;
681    char *p, *q;
682
683    while (myfgets(buf, 1024, db)) {
684        if (buf[0] == '%')
685            continue;
686        p = strchr(buf, '\n');
687        if (p) *p = '\0';
688        if (MatchKey(buf, key)) {
689            while (myfgets(buf, 1024, db)) {
690                if (buf[0] == '%')
691                    continue;
692                if (buf[0] == '.') {
693                    return TRUE;
694                }
695                HandleOption(ndex, buf);
696            }
697        }
698        else {
699            while (myfgets(buf, 1024, db)) {
700                if (buf[0] == '.')
701                    break;
702            }
703        }
704    }
705    return FALSE;
706}
707
708       
Note: See TracBrowser for help on using the repository browser.