1 /*	$Id$ */
2 /*
3  * Copyright (c) 1990-1996 Sam Leffler
4  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and
7  * its documentation for any purpose is hereby granted without fee, provided
8  * that (i) the above copyright notices and this permission notice appear in
9  * all copies of the software and related documentation, and (ii) the names of
10  * Sam Leffler and Silicon Graphics may not be used in any advertising or
11  * publicity relating to the software without the specific, prior written
12  * permission of Sam Leffler and Silicon Graphics.
13  *
14  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
16  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
17  *
18  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
19  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
20  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
21  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
22  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
23  * OF THIS SOFTWARE.
24  */
25 #include <stdio.h>
26 #include <string.h>
27 #include <syslog.h>
28 #include <stdarg.h>
29 #include <errno.h>
30 #include <fcntl.h>
31 #include <stdlib.h>
32 #include <unistd.h>
33 
34 #include "config.h"
35 #include "port.h"
36 
37 static void
fatal(char * fmt,...)38 fatal(char* fmt, ...)
39 {
40     va_list ap;
41     va_start(ap, fmt);
42     if (isatty(fileno(stderr))) {
43         vfprintf(stderr, fmt, ap);
44         putc('\n', stderr);
45     } else {
46         vsyslog(LOG_ERR, fmt, ap);
47     }
48     va_end(ap);
49     exit(-1);
50 }
51 
52 extern	int cvtFacility(const char*, int*);
53 
54 static const char*
modemstate(const char * arg)55 modemstate(const char* arg)
56 {
57     static struct {
58 	const char* tag;
59 	const char* state;
60     } modemstates[] = {
61 	{ "busy",  "B" },
62 	{ "ready", "R" }, { "up",      "R" },
63 	{ "down",  "D" }, { "disable", "D" },
64 	{ NULL }
65     };
66     int i;
67 
68     for (i = 0; modemstates[i].tag != NULL; i++)
69 	if (strcmp(modemstates[i].tag, arg) == 0)
70 	    return (modemstates[i].state);
71     fatal("Bad modem ready state `%s'; use one of busy, ready, and down", arg);
72     /*NOTREACHED*/
73     return (NULL);
74 }
75 
76 int
main(int argc,char ** argv)77 main(int argc, char** argv)
78 {
79     extern int optind;
80     extern char* optarg;
81     int fifo, c;
82     char* spooldir = FAX_SPOOLDIR;
83     const char* arg = modemstate("ready");
84     char fifoname[256];
85     char devid[256];
86     int cmdlen;
87     char cmd[80];
88     char* appname;
89     char* usage = "[-s state] [-q queue-dir] [-n]";
90     char* cp;
91     int facility = LOG_DAEMON;
92     int nofaxgetty = 0;
93 
94     (void) cvtFacility(LOG_FAX, &facility);
95     openlog(argv[0], LOG_PID|LOG_ODELAY, facility);
96     appname = strrchr(argv[0], '/');
97     if (appname)
98 	appname++;
99     else
100 	appname = argv[0];
101     while ((c = getopt(argc, argv, "s:q:n")) != -1)
102 	switch (c) {
103 	case 'n':
104 	    nofaxgetty = 1;
105 	    break;
106 	case 's':
107 	    arg = modemstate(optarg);
108 	    break;
109 	case 'q':
110 	    spooldir = optarg;
111 	    break;
112 	case '?':
113 	    fatal("usage: %s %s devid", argv[0], usage);
114 	    /*NOTREACHED*/
115 	}
116     if (optind != argc-1) {
117         fatal("usage: %s %s modem", argv[0], usage);
118     }
119     if (strlen(argv[optind]) < sizeof(devid)) {
120         strcpy(devid, argv[optind]);
121     } else {
122         fatal("Argument is too large: %s", argv[optind]);
123     }
124     for (cp = devid; (cp = strchr(cp, '/')); *cp++ = '_')
125 	;
126     if (chdir(spooldir) < 0)
127 	fatal("%s: chdir: %s", spooldir, strerror(errno));
128     if (nofaxgetty) {
129 	/*
130 	 * No faxgetty process, contact faxq directly and emulate
131 	 * what faxgetty would send.
132 	 */
133 	fifo = open(FAX_FIFO, O_WRONLY|O_NDELAY);
134         if (fifo < 0) {
135             fatal("%s: open: %s", FAX_FIFO, strerror(errno));
136         }
137         cmdlen = snprintf(cmd, sizeof(cmd), "+%s:%s", devid, arg);
138         if (cmdlen < 0 || cmdlen >= sizeof(cmd) || write(fifo, cmd, cmdlen) != cmdlen) {
139             fatal("FIFO write failed for command (%s)", strerror(errno));
140         }
141     } else {
142         snprintf(fifoname, sizeof(fifoname), "%s.%.*s", FAX_FIFO,
143             sizeof (fifoname) - sizeof (FAX_FIFO), devid);
144         fifo = open(fifoname, O_WRONLY|O_NDELAY);
145         if (fifo < 0) {
146             fatal("%s: open: %s", fifoname, strerror(errno));
147         }
148         cmdlen = snprintf(cmd, sizeof(cmd), "S%s", arg);
149         if (cmdlen < 0 || cmdlen >= sizeof(cmd) || write(fifo, cmd, cmdlen) != cmdlen) {
150             fatal("FIFO write failed for command (%s)", strerror(errno));
151         }
152     }
153     (void) close(fifo);
154     return 0;
155 }
156