2 * safe_finger - finger client wrapper that protects against nasty stuff
3 * from finger servers. Use this program for automatic reverse finger
4 * probes, not the raw finger command.
6 * Build with: cc -o safe_finger safe_finger.c
8 * The problem: some programs may react to stuff in the first column. Other
9 * programs may get upset by thrash anywhere on a line. File systems may
10 * fill up as the finger server keeps sending data. Text editors may bomb
11 * out on extremely long lines. The finger server may take forever because
12 * it is somehow wedged. The code below takes care of all this badness.
14 * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
17 static char sccsid
[] = "@(#) safe_finger.c 1.4 94/12/28 17:42:41";
19 /* System libraries */
21 #include <sys/types.h>
33 char path
[] = "PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd:/etc:/usr/etc:/usr/sbin";
35 #define TIME_LIMIT 60 /* Do not keep listinging forever */
36 #define INPUT_LENGTH 100000 /* Do not keep listinging forever */
37 #define LINE_LENGTH 128 /* Editors can choke on long lines */
38 #define FINGER_PROGRAM "finger" /* Most, if not all, UNIX systems */
39 #define UNPRIV_NAME "nobody" /* Preferred privilege level */
40 #define UNPRIV_UGID 32767 /* Default uid and gid */
47 kill(finger_pid
, SIGKILL
);
64 * First of all, let's don't run with superuser privileges.
66 if (getuid() == 0 || geteuid() == 0) {
67 if ((pwd
= getpwnam(UNPRIV_NAME
)) && pwd
->pw_uid
> 0) {
77 * Redirect our standard input through the raw finger command.
80 fprintf(stderr
, "%s: putenv: out of memory", argv
[0]);
83 argv
[0] = FINGER_PROGRAM
;
84 finger_pid
= pipe_stdin(argv
);
87 * Don't wait forever (Peter Wemm <peter@gecko.DIALix.oz.au>).
89 signal(SIGALRM
, cleanup
);
90 (void) alarm(TIME_LIMIT
);
95 while ((c
= getchar()) != EOF
) {
96 if (input_count
++ >= INPUT_LENGTH
) { /* don't listen forever */
98 printf("\n\n Input truncated to %d bytes...\n", input_count
- 1);
101 if (c
== '\n') { /* good: end of line */
105 if (line_length
>= LINE_LENGTH
) { /* force end of line */
109 if (line_length
== 0) { /* protect left margin */
113 if (isascii(c
) && (isprint(c
) || isspace(c
))) { /* text */
120 } else { /* quote all other thash */
121 printf("\\%03o", c
& 0377);
128 * Wait until the finger child process has terminated and account for its
129 * exit status. Which will always be zero on most systems.
131 while ((wait_pid
= wait(&finger_status
)) != -1 && wait_pid
!= finger_pid
)
133 return (wait_pid
!= finger_pid
|| finger_status
!= 0);
136 /* perror_exit - report system error text and terminate */
138 void perror_exit(text
)
145 /* pipe_stdin - pipe stdin through program (from my ANSI to OLD C converter) */
156 * The code that sets up the pipe requires that file descriptors 0,1,2
157 * are already open. All kinds of mysterious things will happen if that
158 * is not the case. The following loops makes sure that descriptors 0,1,2
159 * are set up properly.
162 for (i
= 0; i
< 3; i
++) {
163 if (fstat(i
, &st
) == -1 && open("/dev/null", O_RDWR
) != i
)
164 perror_exit("open /dev/null");
168 * Set up the pipe that interposes the command into our standard input
175 switch (pid
= fork()) {
180 (void) close(pipefds
[0]); /* close reading end */
181 (void) close(1); /* connect stdout to pipe */
182 if (dup(pipefds
[1]) != 1)
184 (void) close(pipefds
[1]); /* close redundant fd */
185 (void) execvp(argv
[0], argv
);
186 perror_exit(argv
[0]);
188 default: /* parent */
189 (void) close(pipefds
[1]); /* close writing end */
190 (void) close(0); /* connect stdin to pipe */
191 if (dup(pipefds
[0]) != 0)
193 (void) close(pipefds
[0]); /* close redundant fd */