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.
18 static char sccsid
[] = "@(#) safe_finger.c 1.4 94/12/28 17:42:41";
21 /* System libraries */
23 #include <sys/types.h>
34 char path
[] = "PATH=/bin:/usr/bin:/usr/ucb:/usr/bsd:/etc:/usr/etc:/usr/sbin";
36 #define TIME_LIMIT 60 /* Do not keep listinging forever */
37 #define INPUT_LENGTH 100000 /* Do not keep listinging forever */
38 #define LINE_LENGTH 128 /* Editors can choke on long lines */
39 #define FINGER_PROGRAM "finger" /* Most, if not all, UNIX systems */
40 #define UNPRIV_NAME "nobody" /* Preferred privilege level */
41 #define UNPRIV_UGID 32767 /* Default uid and gid */
48 kill(finger_pid
, SIGKILL
);
65 * First of all, let's don't run with superuser privileges.
67 if (getuid() == 0 || geteuid() == 0) {
68 if ((pwd
= getpwnam(UNPRIV_NAME
)) && pwd
->pw_uid
> 0) {
78 * Redirect our standard input through the raw finger command.
81 fprintf(stderr
, "%s: putenv: out of memory", argv
[0]);
84 argv
[0] = FINGER_PROGRAM
;
85 finger_pid
= pipe_stdin(argv
);
88 * Don't wait forever (Peter Wemm <peter@gecko.DIALix.oz.au>).
90 signal(SIGALRM
, cleanup
);
91 (void) alarm(TIME_LIMIT
);
96 while ((c
= getchar()) != EOF
) {
97 if (input_count
++ >= INPUT_LENGTH
) { /* don't listen forever */
99 printf("\n\n Input truncated to %d bytes...\n", input_count
- 1);
102 if (c
== '\n') { /* good: end of line */
106 if (line_length
>= LINE_LENGTH
) { /* force end of line */
110 if (line_length
== 0) { /* protect left margin */
114 if (isascii(c
) && (isprint(c
) || isspace(c
))) { /* text */
121 } else { /* quote all other thash */
122 printf("\\%03o", c
& 0377);
129 * Wait until the finger child process has terminated and account for its
130 * exit status. Which will always be zero on most systems.
132 while ((wait_pid
= wait(&finger_status
)) != -1 && wait_pid
!= finger_pid
)
134 return (wait_pid
!= finger_pid
|| finger_status
!= 0);
137 /* perror_exit - report system error text and terminate */
139 void perror_exit(text
)
146 /* pipe_stdin - pipe stdin through program (from my ANSI to OLD C converter) */
157 * The code that sets up the pipe requires that file descriptors 0,1,2
158 * are already open. All kinds of mysterious things will happen if that
159 * is not the case. The following loops makes sure that descriptors 0,1,2
160 * are set up properly.
163 for (i
= 0; i
< 3; i
++) {
164 if (fstat(i
, &st
) == -1 && open("/dev/null", 2) != i
)
165 perror_exit("open /dev/null");
169 * Set up the pipe that interposes the command into our standard input
176 switch (pid
= fork()) {
181 (void) close(pipefds
[0]); /* close reading end */
182 (void) close(1); /* connect stdout to pipe */
183 if (dup(pipefds
[1]) != 1)
185 (void) close(pipefds
[1]); /* close redundant fd */
186 (void) execvp(argv
[0], argv
);
187 perror_exit(argv
[0]);
189 default: /* parent */
190 (void) close(pipefds
[1]); /* close writing end */
191 (void) close(0); /* connect stdin to pipe */
192 if (dup(pipefds
[0]) != 0)
194 (void) close(pipefds
[0]); /* close redundant fd */