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/";
9 #include "sysincludes.h"
20 static void filan_usage(FILE *fd
);
23 int main(int argc
, const char *argv
[]) {
24 const char **arg1
, *a
;
25 const char *filename
= NULL
, *waittimetxt
;
26 unsigned int m
= 0; /* first FD (default) */
27 unsigned int n
= FD_SETSIZE
; /* last excl. */
30 struct timespec waittime
= { 0, 0 };
32 const char *outfname
= NULL
;
35 diag_set('p', strchr(argv
[0], '/') ? strrchr(argv
[0], '/')+1 : argv
[0]);
37 arg1
= argv
+1; --argc
;
38 while (arg1
[0] && (arg1
[0][0] == '-')) {
42 filan_usage(stdout
); exit(0);
45 case 'V': filan_version(stdout
); exit(0);
47 case 'L': filan_followsymlinks
= true; break;
48 case 'd': diag_set('d', NULL
); break;
49 case 's': style
= arg1
[0][1]; break;
50 case 'S': style
= arg1
[0][1]; break;
51 case 'r': filan_rawoutput
= true; break;
52 case 'i': if (arg1
[0][2]) {
56 if ((a
= *arg1
) == NULL
) {
57 Error("option -i requires an argument");
58 filan_usage(stderr
); exit(1);
61 m
= strtoul(a
, (char **)&a
, 0);
64 case 'n': if (arg1
[0][2]) {
68 if ((a
= *arg1
) == NULL
) {
69 Error("option -n requires an argument");
70 filan_usage(stderr
); exit(1);
73 n
= strtoul(a
, (char **)&a
, 0);
75 case 'f': if (arg1
[0][2]) {
79 if ((filename
= *arg1
) == NULL
) {
80 Error("option -f requires an argument");
81 filan_usage(stderr
); exit(1);
85 case 'T': if (arg1
[0][2]) {
86 waittimetxt
= *arg1
+2;
89 if ((waittimetxt
= *arg1
) == NULL
) {
90 Error("option -T requires an argument");
91 filan_usage(stderr
); exit(1);
96 waittimedbl
= strtod(waittimetxt
, NULL
);
97 waittime
.tv_sec
= waittimedbl
;
98 waittime
.tv_nsec
= (waittimedbl
-waittime
.tv_sec
) * 1000000000;
101 case 'o': if (arg1
[0][2]) {
105 if ((outfname
= *arg1
) == NULL
) {
106 Error("option -o requires an argument");
107 filan_usage(stderr
); exit(1);
113 diag_set_int('e', E_FATAL
);
114 Error1("unknown option %s", arg1
[0]);
121 if (arg1
[0][1] == '\0')
127 Error1("%d superfluous arguments", argc
);
133 if (!strcmp(outfname
,"stdin")) { fdout
=stdin
; }
134 else if (!strcmp(outfname
,"stdout")) { fdout
=stdout
; }
135 else if (!strcmp(outfname
,"stderr")) { fdout
=stderr
; }
136 /* file descriptor */
137 else if (*outfname
== '+') {
139 fildes
= strtoul(a
, (char **)&a
, 0);
140 if ((fdout
= fdopen(fildes
, "w")) == NULL
) {
141 Error2("can't fdopen file descriptor %lu: %s\n", fildes
, strerror(errno
));
146 if ((fdout
= fopen(outfname
, "w")) == NULL
) {
147 Error2("can't fopen '%s': %s\n",
148 outfname
, strerror(errno
));
154 Nanosleep(&waittime
, NULL
);
157 /* this style gives detailled infos, but requires a file descriptor */
159 #if LATER /* this is just in case that S_ISSOCK does not work */
163 if (Stat(filename
, &buf
) < 0) {
164 Error3("stat(\"%s\", %p): %s", filename
, &buf
, strerror(errno
));
166 /* note: when S_ISSOCK was undefined, it always gives 0 */
167 if (S_ISSOCK(buf
.st_mode
)) {
168 Error("cannot analyze UNIX domain socket");
171 filan_file(filename
, fdout
);
176 for (i
= m
; i
< n
; ++i
) {
181 /* this style gives only type and path / socket addresses, and works from
182 file descriptor or filename (with restrictions) */
184 /* filename: NULL means yet unknown; "" means no name at all */
188 Open(filename
, O_RDONLY
|O_NOCTTY
|O_NONBLOCK
194 Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
195 filename
, strerror(errno
));
197 fdname(filename
, fd
, fdout
, NULL
, style
);
199 fdname(filename
, -1, fdout
, NULL
, style
);
202 fdname("", m
, fdout
, NULL
, style
);
204 for (i
= m
; i
< n
; ++i
) {
205 fdname("", i
, fdout
, "%5u ", style
);
210 if (outfname
&& fdout
!= stdout
&& fdout
!= stderr
) {
218 static void filan_usage(FILE *fd
) {
219 fputs(copyright
, fd
); fputc('\n', fd
);
220 fputs("Analyze file descriptors of the process\n", fd
);
221 fputs("Usage:\n", fd
);
222 fputs("filan [options]\n", fd
);
223 fputs(" options:\n", fd
);
225 fputs(" -V print version information to stdout, and exit\n", fd
);
228 fputs(" -?|-h print this help text\n", fd
);
229 fputs(" -d increase verbosity (use up to 4 times)\n", fd
);
232 fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd
);
233 fputs(" -lf<logfile> log to file\n", fd
);
234 fputs(" -ls log to stderr (default if no other log)\n", fd
);
236 fputs(" -i<fdnum> only analyze this fd\n", fd
);
237 fprintf(fd
, " -n<fdnum> analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE
);
238 fputs(" -s simple output with just type and socket address or path\n", fd
);
239 fputs(" -S like -s but improved format and contents\n", fd
);
240 /* fputs(" -c alternate device visualization\n", fd);*/
241 fputs(" -f<filename> analyze file system entry\n", fd
);
242 fputs(" -T<seconds> wait before analyzing, useful to connect with debugger\n", fd
);
243 fputs(" -r raw output for time stamps and rdev\n", fd
);
244 fputs(" -L follow symbolic links instead of showing their properties\n", fd
);
245 fputs(" -o<filename> output goes to filename, that can be:\n", fd
);
246 fputs(" a regular file name, the output goes to that\n", fd
);
247 fputs(" +<filedes> , output goes to the file descriptor (which must be open writable)\n", fd
);
248 fputs(" the 3 special names stdin stdout and stderr\n", fd
);
250 #endif /* WITH_HELP */