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
= 1; break;
50 case 'r': filan_rawoutput
= true; break;
51 case 'i': if (arg1
[0][2]) {
55 if ((a
= *arg1
) == NULL
) {
56 Error("option -i requires an argument");
57 filan_usage(stderr
); exit(1);
60 m
= strtoul(a
, (char **)&a
, 0);
63 case 'n': if (arg1
[0][2]) {
67 if ((a
= *arg1
) == NULL
) {
68 Error("option -n requires an argument");
69 filan_usage(stderr
); exit(1);
72 n
= strtoul(a
, (char **)&a
, 0);
74 case 'f': if (arg1
[0][2]) {
78 if ((filename
= *arg1
) == NULL
) {
79 Error("option -f requires an argument");
80 filan_usage(stderr
); exit(1);
84 case 'T': if (arg1
[0][2]) {
85 waittimetxt
= *arg1
+2;
88 if ((waittimetxt
= *arg1
) == NULL
) {
89 Error("option -T requires an argument");
90 filan_usage(stderr
); exit(1);
95 waittimedbl
= strtod(waittimetxt
, NULL
);
96 waittime
.tv_sec
= waittimedbl
;
97 waittime
.tv_nsec
= (waittimedbl
-waittime
.tv_sec
) * 1000000000;
100 case 'o': if (arg1
[0][2]) {
104 if ((outfname
= *arg1
) == NULL
) {
105 Error("option -o requires an argument");
106 filan_usage(stderr
); exit(1);
112 diag_set_int('e', E_FATAL
);
113 Error1("unknown option %s", arg1
[0]);
120 if (arg1
[0][1] == '\0')
126 Error1("%d superfluous arguments", argc
);
132 if (!strcmp(outfname
,"stdin")) { fdout
=stdin
; }
133 else if (!strcmp(outfname
,"stdout")) { fdout
=stdout
; }
134 else if (!strcmp(outfname
,"stderr")) { fdout
=stderr
; }
135 /* file descriptor */
136 else if (*outfname
== '+') {
138 fildes
= strtoul(a
, (char **)&a
, 0);
139 if ((fdout
= fdopen(fildes
, "w")) == NULL
) {
140 Error2("can't fdopen file descriptor %lu: %s\n", fildes
, strerror(errno
));
145 if ((fdout
= fopen(outfname
, "w")) == NULL
) {
146 Error2("can't fopen '%s': %s\n",
147 outfname
, strerror(errno
));
153 Nanosleep(&waittime
, NULL
);
156 /* this style gives detailled infos, but requires a file descriptor */
158 #if LATER /* this is just in case that S_ISSOCK does not work */
162 if (Stat(filename
, &buf
) < 0) {
163 Error3("stat(\"%s\", %p): %s", filename
, &buf
, strerror(errno
));
165 /* note: when S_ISSOCK was undefined, it always gives 0 */
166 if (S_ISSOCK(buf
.st_mode
)) {
167 Error("cannot analyze UNIX domain socket");
170 filan_file(filename
, fdout
);
175 for (i
= m
; i
< n
; ++i
) {
180 /* this style gives only type and path / socket addresses, and works from
181 file descriptor or filename (with restrictions) */
183 /* filename: NULL means yet unknown; "" means no name at all */
187 Open(filename
, O_RDONLY
|O_NOCTTY
|O_NONBLOCK
193 Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
194 filename
, strerror(errno
));
196 fdname(filename
, fd
, fdout
, NULL
);
198 fdname(filename
, -1, fdout
, NULL
);
201 fdname("", m
, fdout
, NULL
);
203 for (i
= m
; i
< n
; ++i
) {
204 fdname("", i
, fdout
, "%5u ");
209 if (outfname
&& fdout
!= stdout
&& fdout
!= stderr
) {
217 static void filan_usage(FILE *fd
) {
218 fputs(copyright
, fd
); fputc('\n', fd
);
219 fputs("Analyze file descriptors of the process\n", fd
);
220 fputs("Usage:\n", fd
);
221 fputs("filan [options]\n", fd
);
222 fputs(" options:\n", fd
);
224 fputs(" -V print version information to stdout, and exit\n", fd
);
227 fputs(" -?|-h print this help text\n", fd
);
228 fputs(" -d increase verbosity (use up to 4 times)\n", fd
);
231 fputs(" -ly[facility] log to syslog, using facility (default is daemon)\n", fd
);
232 fputs(" -lf<logfile> log to file\n", fd
);
233 fputs(" -ls log to stderr (default if no other log)\n", fd
);
235 fputs(" -i<fdnum> only analyze this fd\n", fd
);
236 fprintf(fd
, " -n<fdnum> analyze all fds from 0 up to fdnum-1 (default: %u)\n", FD_SETSIZE
);
237 fputs(" -s simple output with just type and socket address or path\n", fd
);
238 /* fputs(" -c alternate device visualization\n", fd);*/
239 fputs(" -f<filename> analyze file system entry\n", fd
);
240 fputs(" -T<seconds> wait before analyzing, useful to connect with debugger\n", fd
);
241 fputs(" -r raw output for time stamps and rdev\n", fd
);
242 fputs(" -L follow symbolic links instead of showing their properties\n", fd
);
243 fputs(" -o<filename> output goes to filename, that can be:\n", fd
);
244 fputs(" a regular file name, the output goes to that\n", fd
);
245 fputs(" +<filedes> , output goes to the file descriptor (which must be open writable)\n", fd
);
246 fputs(" the 3 special names stdin stdout and stderr\n", fd
);
248 #endif /* WITH_HELP */