1 /*	$Id$ */
2 /*
3  * Copyright (c) 1990-1996 Sam Leffler
4  * Copyright (c) 1991-1996 Silicon Graphics, Inc.
5  * HylaFAX is a trademark of Silicon Graphics
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 #include "FaxClient.h"
27 #include "StrArray.h"
28 #include "Sys.h"
29 #include "NLS.h"
30 #include "config.h"
31 
32 #include <errno.h>
33 
34 class faxStatApp : public FaxClient {
35 private:
36     fxStr	header;
37 
38     bool listWithHeader(const fxStr& dir, fxStr& emsg);
39 public:
40     faxStatApp();
41     ~faxStatApp();
42 
43     void run(int argc, char** argv);
44 };
faxStatApp()45 faxStatApp::faxStatApp() {}
~faxStatApp()46 faxStatApp::~faxStatApp() {}
47 
48 static bool
writeStdout(int,const char * buf,int cc,fxStr &)49 writeStdout(int, const char* buf, int cc, fxStr&)
50 {
51     (void) Sys::write(STDOUT_FILENO, buf, cc);
52     return (true);
53 }
54 
55 void
run(int argc,char ** argv)56 faxStatApp::run(int argc, char** argv)
57 {
58     resetConfig();
59     readConfig(FAX_SYSCONF);
60     readConfig(FAX_USERCONF);
61 
62     fxStrArray dirs;
63     dirs.append(FAX_STATUSDIR);		// server status
64     bool checkInfo = false;
65     int c;
66     while ((c = Sys::getopt(argc, argv, "h:adgfilrsv")) != -1)
67 	switch (c) {
68 	case 'a':			// display archived jobs
69 	    dirs.append(FAX_ARCHDIR);
70 	    break;
71 	case 'd':			// display jobs in done queue
72 	    dirs.append(FAX_DONEDIR);
73 	    break;
74 	case 'f':			// display queued documents
75 	    dirs.append(FAX_DOCDIR);
76 	    break;
77 	case 'g':			// use GMT for dates & times
78 	    setTimeZone(TZ_GMT);
79 	    break;
80 	case 'h':			// server's host
81 	    setHost(optarg);
82 	    break;
83 	case 'i':			// display any.info file
84 	    checkInfo = true;
85 	    break;
86 	case 'l':			// use local timezone for dates & times
87 	    setTimeZone(TZ_LOCAL);
88 	    break;
89 	case 'r':			// display receive queue
90 	    dirs.append(FAX_RECVDIR);
91 	    break;
92 	case 's':			// display jobs in send queue
93 	    dirs.append(FAX_SENDDIR);
94 	    break;
95 	case 'v':			// enable protocol tracing
96 	    setVerbose(true);
97 	    break;
98 	case '?':
99 	    fxFatal(_("usage: faxstat [-h server-host] [-adfgilrsv]"));
100 	}
101     fxStr emsg;
102     if (callServer(emsg)) {
103 	if (login(NULL, emsg)) {
104 	    if (checkInfo)
105 		(void) recvData(writeStdout, 0, emsg, 0,
106 		    "RETR " FAX_STATUSDIR "/any." FAX_INFOSUF);
107 	    for (u_int i = 0, n = dirs.length(); i < n; i++) {
108 		header = (i > 0 ? "\n" : "");
109 		if (dirs[i] == FAX_SENDDIR || dirs[i] == FAX_DONEDIR) {
110 		    getJobStatusHeader(header);
111 		    header.append('\n');
112 		} else if (dirs[i] == FAX_RECVDIR) {
113 		    getRecvStatusHeader(header);
114 		    header.append('\n');
115 		} else if (dirs[i] == FAX_STATUSDIR) {
116 		    fxStr notused;
117 		    getModemStatusHeader(notused);
118 		}
119 		if (!listWithHeader(dirs[i], emsg))
120 		    break;
121 	    }
122 	}
123 	hangupServer();
124     }
125     if (emsg != "")
126 	printError("%s", (const char*) emsg);
127 }
128 
129 bool
listWithHeader(const fxStr & dir,fxStr & emsg)130 faxStatApp::listWithHeader(const fxStr& dir, fxStr& emsg)
131 {
132     if (!setMode(MODE_S))
133 	goto bad;
134     if (!initDataConn(emsg))
135 	goto bad;
136     if (command("LIST " | dir) != PRELIM)
137 	goto bad;
138     if (!openDataConn(emsg))
139 	goto bad;
140     u_long byte_count; byte_count = 0;			// XXX for __GNUC__
141     for (;;) {
142 	char buf[16*1024];
143 	int cc = read(getDataFd(), buf, sizeof (buf));
144 	if (cc == 0) {
145 	    closeDataConn();
146 	    return (getReply(false) == COMPLETE);
147 	}
148 	if (cc < 0) {
149 	    emsg = fxStr::format(_("Data Connection: %s"), strerror(errno));
150 	    (void) getReply(false);
151 	    break;
152 	}
153 	if (byte_count == 0 && header.length() > 0)
154 	    (void) Sys::write(STDOUT_FILENO, header, header.length());
155 	byte_count += cc;
156 	(void) Sys::write(STDOUT_FILENO, buf, cc);
157     }
158 bad:
159     closeDataConn();
160     return (false);
161 }
162 
163 int
main(int argc,char ** argv)164 main(int argc, char** argv)
165 {
166     NLS::Setup("hylafax-client");
167     faxStatApp app;
168     app.run(argc, argv);
169     return 0;
170 }
171