Version 1.8.0.0
[socat.git] / filan_main.c
blob24dd5e996b5de5143c52964b1343aa4fa5511eea
1 /* source: filan_main.c */
2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 const char copyright[] = "filan by Gerhard Rieger and contributors - see http://www.dest-unreach.org/socat/";
7 #include "config.h"
8 #include "xioconfig.h"
9 #include "sysincludes.h"
11 #include "mytypes.h"
12 #include "compat.h"
13 #include "error.h"
14 #include "sycls.h"
15 #include "filan.h"
18 #define WITH_HELP 1
20 static void filan_usage(FILE *fd);
23 int main(int argc, const char *argv[]) {
24 const char **arg1, *a0, *a;
25 const char *filename = NULL, *waittimetxt;
26 unsigned int m = 0; /* first FD (default) */
27 unsigned int n = FD_SETSIZE; /* last excl. */
28 unsigned int i;
29 int style = 0;
30 struct timespec waittime = { 0, 0 };
31 FILE *fdout = stdout;
32 const char *outfname = NULL;
33 unsigned long fildes;
35 diag_set('I', NULL);
36 diag_set('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
38 arg1 = argv+1; --argc;
39 while (arg1[0] && (arg1[0][0] == '-')) {
40 switch (arg1[0][1]) {
41 #if WITH_HELP
42 case '?': case 'h':
43 filan_usage(stdout); exit(0);
44 #endif
45 #if LATER
46 case 'V': filan_version(stdout); exit(0);
47 #endif
48 case 'L': filan_followsymlinks = true; break;
49 case 'd': diag_set('d', NULL); break;
50 case 's': style = arg1[0][1]; break;
51 case 'S': style = arg1[0][1]; break;
52 case 'r': filan_rawoutput = true; break;
53 case 'i': if (arg1[0][2]) {
54 a = a0 = *arg1+2;
55 } else {
56 ++arg1, --argc;
57 if ((a = a0 = *arg1) == NULL) {
58 Error("option -i requires an argument");
59 filan_usage(stderr); exit(1);
62 m = strtoul(a, (char **)&a, 0);
63 if (a == a0) {
64 Error1("not a numerical arg in \"-i %s\"", a0);
66 if (*a != '\0') {
67 Error1("trailing garbage in \"-i %s\"", a0);
69 n = m;
70 break;
71 case 'n': if (arg1[0][2]) {
72 a = a0 = *arg1+2;
73 } else {
74 ++arg1, --argc;
75 if ((a = a0 = *arg1) == NULL) {
76 Error("option -n requires an argument");
77 filan_usage(stderr); exit(1);
80 n = strtoul(a, (char **)&a, 0);
81 if (a == a0) {
82 Error1("not a numerical arg in \"-n %s\"", a0);
84 if (*a != '\0') {
85 Error1("trailing garbage in \"-n %s\"", a0);
87 break;
88 case 'f': if (arg1[0][2]) {
89 filename = *arg1+2;
90 } else {
91 ++arg1, --argc;
92 if ((filename = *arg1) == NULL) {
93 Error("option -f requires an argument");
94 filan_usage(stderr); exit(1);
97 break;
98 case 'T': if (arg1[0][2]) {
99 waittimetxt = *arg1+2;
100 } else {
101 ++arg1, --argc;
102 if ((waittimetxt = *arg1) == NULL) {
103 Error("option -T requires an argument");
104 filan_usage(stderr); exit(1);
108 double waittimedbl;
109 waittimedbl = strtod(waittimetxt, NULL);
110 waittime.tv_sec = waittimedbl;
111 waittime.tv_nsec = (waittimedbl-waittime.tv_sec) * 1000000000;
113 break;
114 case 'o': if (arg1[0][2]) {
115 outfname = *arg1+2;
116 } else {
117 ++arg1, --argc;
118 if ((outfname = *arg1) == NULL) {
119 Error("option -o requires an argument");
120 filan_usage(stderr); exit(1);
123 break;
124 case '\0': break;
125 default:
126 diag_set_int('e', E_FATAL);
127 Error1("unknown option %s", arg1[0]);
128 #if WITH_HELP
129 filan_usage(stderr);
130 #endif
131 exit(1);
133 #if 0
134 if (arg1[0][1] == '\0')
135 break;
136 #endif
137 ++arg1; --argc;
139 if (argc != 0) {
140 Error1("%d superfluous arguments", argc);
141 filan_usage(stderr);
142 exit(1);
144 if (outfname) {
145 /* special cases */
146 if (!strcmp(outfname,"stdin")) { fdout=stdin; }
147 else if (!strcmp(outfname,"stdout")) { fdout=stdout; }
148 else if (!strcmp(outfname,"stderr")) { fdout=stderr; }
149 /* file descriptor */
150 else if (*outfname == '+') {
151 a = outfname+1;
152 fildes = strtoul(a, (char **)&a, 0);
153 if ((fdout = fdopen(fildes, "w")) == NULL) {
154 Error2("can't fdopen file descriptor %lu: %s\n", fildes, strerror(errno));
155 exit(1);
157 } else {
158 /* file name */
159 if ((fdout = fopen(outfname, "w")) == NULL) {
160 Error2("can't fopen '%s': %s\n",
161 outfname, strerror(errno));
162 exit(1);
167 Nanosleep(&waittime, NULL);
169 if (style == 0) {
170 /* this style gives detailled infos, but requires a file descriptor */
171 if (filename) {
172 #if LATER /* this is just in case that S_ISSOCK does not work */
173 struct stat buf;
174 int fd;
176 if (Stat(filename, &buf) < 0) {
177 Error3("stat(\"%s\", %p): %s", filename, &buf, strerror(errno));
179 /* note: when S_ISSOCK was undefined, it always gives 0 */
180 if (S_ISSOCK(buf.st_mode)) {
181 Error("cannot analyze UNIX domain socket");
183 #endif
184 filan_file(filename, fdout);
185 } else {
186 if (m == n) {
187 ++n;
189 for (i = m; i < n; ++i) {
190 filan_fd(i, fdout);
193 } else {
194 /* this style gives only type and path / socket addresses, and works from
195 file descriptor or filename (with restrictions) */
196 if (filename) {
197 /* filename: NULL means yet unknown; "" means no name at all */
198 #if LATER
199 int fd;
200 if ((fd =
201 Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
202 #ifdef O_LARGEFILE
203 |O_LARGEFILE
204 #endif
205 , 0700))
206 < 0) {
207 Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
208 filename, strerror(errno));
210 fdname(filename, fd, fdout, NULL, style);
211 #endif
212 fdname(filename, -1, fdout, NULL, style);
213 } else {
214 if (m == n) {
215 fdname("", m, fdout, NULL, style);
216 } else {
217 for (i = m; i < n; ++i) {
218 fdname("", i, fdout, "%5u ", style);
223 if (outfname && fdout != stdout && fdout != stderr) {
224 fclose(fdout);
226 return 0;
230 #if WITH_HELP
231 static void filan_usage(FILE *fd) {
232 fputs(copyright, fd); fputc('\n', fd);
233 fputs("Analyze file descriptors of the process\n", fd);
234 fputs("Usage:\n", fd);
235 fputs("filan [options]\n", fd);
236 fputs(" options:\n", fd);
237 #if LATER
238 fputs(" -V print version information to stdout, and exit\n", fd);
239 #endif
240 #if WITH_HELP
241 fputs(" -?|-h print this help text\n", fd);
242 fputs(" -d increase verbosity (use up to 4 times)\n", fd);
243 #endif
244 #if 0
245 fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd);
246 fputs(" -lf<logfile> log to file\n", fd);
247 fputs(" -ls log to stderr (default if no other log)\n", fd);
248 #endif
249 fputs(" -i<fdnum> only analyze this fd\n", fd);
250 fprintf(fd, " -n<fdnum> analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE);
251 fputs(" -s simple output with just type and socket address or path\n", fd);
252 fputs(" -S like -s but improved format and contents\n", fd);
253 /* fputs(" -c alternate device visualization\n", fd);*/
254 fputs(" -f<filename> analyze file system entry\n", fd);
255 fputs(" -T<seconds> wait before analyzing, useful to connect with debugger\n", fd);
256 fputs(" -r raw output for time stamps and rdev\n", fd);
257 fputs(" -L follow symbolic links instead of showing their properties\n", fd);
258 fputs(" -o<filename> output goes to filename, that can be:\n", fd);
259 fputs(" a regular file name, the output goes to that\n", fd);
260 fputs(" +<filedes> , output goes to the file descriptor (which must be open writable)\n", fd);
261 fputs(" the 3 special names stdin stdout and stderr\n", fd);
263 #endif /* WITH_HELP */