version 1.7.3.0
[socat.git] / filan_main.c
blob6bfb29788aff9baebd6d7771e873fc83a24d4fa1
1 /* source: filan_main.c */
2 /* Copyright Gerhard Rieger */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 const char copyright[] = "filan by Gerhard Rieger - 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, *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('p', strchr(argv[0], '/') ? strrchr(argv[0], '/')+1 : argv[0]);
37 arg1 = argv+1; --argc;
38 while (arg1[0] && (arg1[0][0] == '-')) {
39 switch (arg1[0][1]) {
40 #if WITH_HELP
41 case '?': case 'h':
42 filan_usage(stdout); exit(0);
43 #endif
44 #if LATER
45 case 'V': filan_version(stdout); exit(0);
46 #endif
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]) {
52 a = *arg1+2;
53 } else {
54 ++arg1, --argc;
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);
61 n = m;
62 break;
63 case 'n': if (arg1[0][2]) {
64 a = *arg1+2;
65 } else {
66 ++arg1, --argc;
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);
73 break;
74 case 'f': if (arg1[0][2]) {
75 filename = *arg1+2;
76 } else {
77 ++arg1, --argc;
78 if ((filename = *arg1) == NULL) {
79 Error("option -f requires an argument");
80 filan_usage(stderr); exit(1);
83 break;
84 case 'T': if (arg1[0][2]) {
85 waittimetxt = *arg1+2;
86 } else {
87 ++arg1, --argc;
88 if ((waittimetxt = *arg1) == NULL) {
89 Error("option -T requires an argument");
90 filan_usage(stderr); exit(1);
94 double waittimedbl;
95 waittimedbl = strtod(waittimetxt, NULL);
96 waittime.tv_sec = waittimedbl;
97 waittime.tv_nsec = (waittimedbl-waittime.tv_sec) * 1000000000;
99 break;
100 case 'o': if (arg1[0][2]) {
101 outfname = *arg1+2;
102 } else {
103 ++arg1, --argc;
104 if ((outfname = *arg1) == NULL) {
105 Error("option -o requires an argument");
106 filan_usage(stderr); exit(1);
109 break;
110 case '\0': break;
111 default:
112 diag_set_int('e', E_FATAL);
113 Error1("unknown option %s", arg1[0]);
114 #if WITH_HELP
115 filan_usage(stderr);
116 #endif
117 exit(1);
119 #if 0
120 if (arg1[0][1] == '\0')
121 break;
122 #endif
123 ++arg1; --argc;
125 if (argc != 0) {
126 Error1("%d superfluous arguments", argc);
127 filan_usage(stderr);
128 exit(1);
130 if (outfname) {
131 /* special cases */
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 == '+') {
137 a = outfname+1;
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));
141 exit(1);
143 } else {
144 /* file name */
145 if ((fdout = fopen(outfname, "w")) == NULL) {
146 Error2("can't fopen '%s': %s\n",
147 outfname, strerror(errno));
148 exit(1);
153 Nanosleep(&waittime, NULL);
155 if (style == 0) {
156 /* this style gives detailled infos, but requires a file descriptor */
157 if (filename) {
158 #if LATER /* this is just in case that S_ISSOCK does not work */
159 struct stat buf;
160 int fd;
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");
169 #endif
170 filan_file(filename, fdout);
171 } else {
172 if (m == n) {
173 ++n;
175 for (i = m; i < n; ++i) {
176 filan_fd(i, fdout);
179 } else {
180 /* this style gives only type and path / socket addresses, and works from
181 file descriptor or filename (with restrictions) */
182 if (filename) {
183 /* filename: NULL means yet unknown; "" means no name at all */
184 #if LATER
185 int fd;
186 if ((fd =
187 Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
188 #ifdef O_LARGEFILE
189 |O_LARGEFILE
190 #endif
191 , 0700))
192 < 0) {
193 Debug2("open(\"%s\", O_RDONLY|O_NOCTTY|O_NONBLOCK|O_LARGEFILE, 0700): %s",
194 filename, strerror(errno));
196 fdname(filename, fd, fdout, NULL);
197 #endif
198 fdname(filename, -1, fdout, NULL);
199 } else {
200 if (m == n) {
201 fdname("", m, fdout, NULL);
202 } else {
203 for (i = m; i < n; ++i) {
204 fdname("", i, fdout, "%5u ");
209 if (outfname && fdout != stdout && fdout != stderr) {
210 fclose(fdout);
212 return 0;
216 #if WITH_HELP
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);
223 #if LATER
224 fputs(" -V print version information to stdout, and exit\n", fd);
225 #endif
226 #if WITH_HELP
227 fputs(" -?|-h print this help text\n", fd);
228 fputs(" -d increase verbosity (use up to 4 times)\n", fd);
229 #endif
230 #if 0
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);
234 #endif
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 */