Check which getprotobynumber_r() variant to use
[socat.git] / filan_main.c
blob3f6f7e63f4a8693835ea0800bfdf308fbc8f64b6
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, *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 = 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]) {
53 a = *arg1+2;
54 } else {
55 ++arg1, --argc;
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);
62 n = m;
63 break;
64 case 'n': if (arg1[0][2]) {
65 a = *arg1+2;
66 } else {
67 ++arg1, --argc;
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);
74 break;
75 case 'f': if (arg1[0][2]) {
76 filename = *arg1+2;
77 } else {
78 ++arg1, --argc;
79 if ((filename = *arg1) == NULL) {
80 Error("option -f requires an argument");
81 filan_usage(stderr); exit(1);
84 break;
85 case 'T': if (arg1[0][2]) {
86 waittimetxt = *arg1+2;
87 } else {
88 ++arg1, --argc;
89 if ((waittimetxt = *arg1) == NULL) {
90 Error("option -T requires an argument");
91 filan_usage(stderr); exit(1);
95 double waittimedbl;
96 waittimedbl = strtod(waittimetxt, NULL);
97 waittime.tv_sec = waittimedbl;
98 waittime.tv_nsec = (waittimedbl-waittime.tv_sec) * 1000000000;
100 break;
101 case 'o': if (arg1[0][2]) {
102 outfname = *arg1+2;
103 } else {
104 ++arg1, --argc;
105 if ((outfname = *arg1) == NULL) {
106 Error("option -o requires an argument");
107 filan_usage(stderr); exit(1);
110 break;
111 case '\0': break;
112 default:
113 diag_set_int('e', E_FATAL);
114 Error1("unknown option %s", arg1[0]);
115 #if WITH_HELP
116 filan_usage(stderr);
117 #endif
118 exit(1);
120 #if 0
121 if (arg1[0][1] == '\0')
122 break;
123 #endif
124 ++arg1; --argc;
126 if (argc != 0) {
127 Error1("%d superfluous arguments", argc);
128 filan_usage(stderr);
129 exit(1);
131 if (outfname) {
132 /* special cases */
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 == '+') {
138 a = outfname+1;
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));
142 exit(1);
144 } else {
145 /* file name */
146 if ((fdout = fopen(outfname, "w")) == NULL) {
147 Error2("can't fopen '%s': %s\n",
148 outfname, strerror(errno));
149 exit(1);
154 Nanosleep(&waittime, NULL);
156 if (style == 0) {
157 /* this style gives detailled infos, but requires a file descriptor */
158 if (filename) {
159 #if LATER /* this is just in case that S_ISSOCK does not work */
160 struct stat buf;
161 int fd;
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");
170 #endif
171 filan_file(filename, fdout);
172 } else {
173 if (m == n) {
174 ++n;
176 for (i = m; i < n; ++i) {
177 filan_fd(i, fdout);
180 } else {
181 /* this style gives only type and path / socket addresses, and works from
182 file descriptor or filename (with restrictions) */
183 if (filename) {
184 /* filename: NULL means yet unknown; "" means no name at all */
185 #if LATER
186 int fd;
187 if ((fd =
188 Open(filename, O_RDONLY|O_NOCTTY|O_NONBLOCK
189 #ifdef O_LARGEFILE
190 |O_LARGEFILE
191 #endif
192 , 0700))
193 < 0) {
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);
198 #endif
199 fdname(filename, -1, fdout, NULL, style);
200 } else {
201 if (m == n) {
202 fdname("", m, fdout, NULL, style);
203 } else {
204 for (i = m; i < n; ++i) {
205 fdname("", i, fdout, "%5u ", style);
210 if (outfname && fdout != stdout && fdout != stderr) {
211 fclose(fdout);
213 return 0;
217 #if WITH_HELP
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);
224 #if LATER
225 fputs(" -V print version information to stdout, and exit\n", fd);
226 #endif
227 #if WITH_HELP
228 fputs(" -?|-h print this help text\n", fd);
229 fputs(" -d increase verbosity (use up to 4 times)\n", fd);
230 #endif
231 #if 0
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);
235 #endif
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 */