1 /* vi: set sw=4 ts=4: */
5 * Copyright (C) 2007 Denys Vlasenko
7 * Licensed under GPLv2, see file LICENSE in this source tree.
10 //usage:#define fakeidentd_trivial_usage
11 //usage: "[-fiw] [-b ADDR] [STRING]"
12 //usage:#define fakeidentd_full_usage "\n\n"
13 //usage: "Provide fake ident (auth) service\n"
14 //usage: "\n -f Run in foreground"
15 //usage: "\n -i Inetd mode"
16 //usage: "\n -w Inetd 'wait' mode"
17 //usage: "\n -b ADDR Bind to specified address"
18 //usage: "\n STRING Ident answer string (default: nobody)"
21 #include "common_bufsiz.h"
25 enum { TIMEOUT
= 20 };
27 typedef struct identd_buf_t
{
29 char buf
[64 - sizeof(int)];
32 #define bogouser bb_common_bufsiz1
34 static int new_peer(isrv_state_t
*state
, int fd
)
37 identd_buf_t
*buf
= xzalloc(sizeof(*buf
));
39 peer
= isrv_register_peer(state
, buf
);
41 return 0; /* failure */
42 if (isrv_register_fd(state
, peer
, fd
) < 0)
43 return peer
; /* failure, unregister peer */
46 isrv_want_rd(state
, fd
);
50 static int do_rd(int fd
, void **paramp
)
52 identd_buf_t
*buf
= *paramp
;
56 cur
= buf
->buf
+ buf
->pos
;
58 sz
= safe_read(fd
, cur
, sizeof(buf
->buf
) - 1 - buf
->pos
);
63 return 0; /* "session is ok" */
67 buf
->buf
[buf
->pos
] = '\0';
68 p
= strpbrk(cur
, "\r\n");
72 return 0; /* "session is ok" */
74 /* Terminate session. If we are in server mode, then
75 * fd is still in nonblocking mode - we never block here */
77 fd
++; /* inetd mode? then write to fd 1 */
78 fdprintf(fd
, "%s : USERID : UNIX : %s\r\n", buf
->buf
, bogouser
);
80 * Why bother if we are going to close fd now anyway?
86 return 1; /* "terminate" */
89 static int do_timeout(void **paramp UNUSED_PARAM
)
91 return 1; /* terminate session */
94 static void inetd_mode(void)
96 identd_buf_t
*buf
= xzalloc(sizeof(*buf
));
97 /* buf->pos = 0; - xzalloc did it */
100 /* Note: we do NOT want nonblocking I/O here! */
101 while (do_rd(0, (void*)&buf
) == 0);
104 int fakeidentd_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
105 int fakeidentd_main(int argc UNUSED_PARAM
, char **argv
)
108 OPT_foreground
= 0x1,
115 const char *bind_address
= NULL
;
119 setup_common_bufsiz();
121 opt
= getopt32(argv
, "fiwb:", &bind_address
);
122 strcpy(bogouser
, "nobody");
124 strncpy(bogouser
, argv
[optind
], COMMON_BUFSIZE
- 1);
126 /* Daemonize if no -f and no -i and no -w */
127 if (!(opt
& OPT_fiw
))
128 bb_daemonize_or_rexec(0, argv
);
130 /* Where to log in inetd modes? "Classic" inetd
131 * probably has its stderr /dev/null'ed (we need log to syslog?),
132 * but daemontools-like utilities usually expect that children
133 * log to stderr. I like daemontools more. Go their way.
134 * (Or maybe we need yet another option "log to syslog") */
135 if (!(opt
& OPT_fiw
) /* || (opt & OPT_syslog) */) {
136 openlog(applet_name
, LOG_PID
, LOG_DAEMON
);
137 logmode
= LOGMODE_SYSLOG
;
140 if (opt
& OPT_inetd
) {
145 /* Ignore closed connections when writing */
146 signal(SIGPIPE
, SIG_IGN
);
149 if (!(opt
& OPT_inetdwait
)) {
150 fd
= create_and_bind_stream_or_die(bind_address
,
151 bb_lookup_port("identd", "tcp", 113));
155 isrv_run(fd
, new_peer
, do_rd
, /*do_wr:*/ NULL
, do_timeout
,
156 TIMEOUT
, (opt
& OPT_inetdwait
) ? TIMEOUT
: 0);