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
, *a0
, *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
;
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] == '-')) {
43 filan_usage(stdout
); exit(0);
46 case 'V': filan_version(stdout
); exit(0);
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]) {
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);
64 Error1("not a numerical arg in \"-i %s\"", a0
);
67 Error1("trailing garbage in \"-i %s\"", a0
);
71 case 'n': if (arg1
[0][2]) {
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);
82 Error1("not a numerical arg in \"-n %s\"", a0
);
85 Error1("trailing garbage in \"-n %s\"", a0
);
88 case 'f': if (arg1
[0][2]) {
92 if ((filename
= *arg1
) == NULL
) {
93 Error("option -f requires an argument");
94 filan_usage(stderr
); exit(1);
98 case 'T': if (arg1
[0][2]) {
99 waittimetxt
= *arg1
+2;
102 if ((waittimetxt
= *arg1
) == NULL
) {
103 Error("option -T requires an argument");
104 filan_usage(stderr
); exit(1);
109 waittimedbl
= strtod(waittimetxt
, NULL
);
110 waittime
.tv_sec
= waittimedbl
;
111 waittime
.tv_nsec
= (waittimedbl
-waittime
.tv_sec
) * 1000000000;
114 case 'o': if (arg1
[0][2]) {
118 if ((outfname
= *arg1
) == NULL
) {
119 Error("option -o requires an argument");
120 filan_usage(stderr
); exit(1);
126 diag_set_int('e', E_FATAL
);
127 Error1("unknown option %s", arg1
[0]);
134 if (arg1
[0][1] == '\0')
140 Error1("%d superfluous arguments", argc
);
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
== '+') {
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
));
159 if ((fdout
= fopen(outfname
, "w")) == NULL
) {
160 Error2("can't fopen '%s': %s\n",
161 outfname
, strerror(errno
));
167 Nanosleep(&waittime
, NULL
);
170 /* this style gives detailled infos, but requires a file descriptor */
172 #if LATER /* this is just in case that S_ISSOCK does not work */
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");
184 filan_file(filename
, fdout
);
189 for (i
= m
; i
< n
; ++i
) {
194 /* this style gives only type and path / socket addresses, and works from
195 file descriptor or filename (with restrictions) */
197 /* filename: NULL means yet unknown; "" means no name at all */
201 Open(filename
, O_RDONLY
|O_NOCTTY
|O_NONBLOCK
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
);
212 fdname(filename
, -1, fdout
, NULL
, style
);
215 fdname("", m
, fdout
, NULL
, style
);
217 for (i
= m
; i
< n
; ++i
) {
218 fdname("", i
, fdout
, "%5u ", style
);
223 if (outfname
&& fdout
!= stdout
&& fdout
!= stderr
) {
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
);
238 fputs(" -V print version information to stdout, and exit\n", fd
);
241 fputs(" -?|-h print this help text\n", fd
);
242 fputs(" -d increase verbosity (use up to 4 times)\n", fd
);
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
);
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 */