]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/finger/net.c
unfinished sblive driver, playback/mixer only for now - not enabled in
[FreeBSD/FreeBSD.git] / usr.bin / finger / net.c
1 /*
2  * Copyright (c) 1989, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Tony Nardo of the Johns Hopkins University/Applied Physics Lab.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *      This product includes software developed by the University of
19  *      California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36
37 #ifndef lint
38 #if 0
39 static char sccsid[] = "@(#)net.c       8.4 (Berkeley) 4/28/95";
40 #else
41 static const char rcsid[] =
42   "$FreeBSD$";
43 #endif
44 #endif /* not lint */
45
46 #include <sys/types.h>
47 #include <sys/param.h>
48 #include <sys/socket.h>
49 #include <netinet/in.h>
50 #include <arpa/inet.h>
51 #include <netdb.h>
52 #include <db.h>
53 #include <err.h>
54 #include <unistd.h>
55 #include <pwd.h>
56 #include <utmp.h>
57 #include <stdio.h>
58 #include <ctype.h>
59 #include <string.h>
60 #include <sys/uio.h>
61 #include <signal.h>
62 #include <limits.h>
63 #include "finger.h"
64
65 void
66 cleanup(sig)
67         int sig;
68 {
69         exit(0);
70 }
71
72 void
73 netfinger(name)
74         char *name;
75 {
76         int cnt;
77         int line_len;
78         extern int lflag;
79         extern int Tflag;
80         register FILE *fp;
81         register int c, lastc;
82         struct in_addr defaddr;
83         struct hostent *hp, def;
84         struct servent *sp;
85         struct sockaddr_in sin;
86         int s;
87         char *alist[1], *host;
88         struct iovec iov[3];
89         struct msghdr msg;
90
91         if (!(host = rindex(name, '@')))
92                 return;
93         *host++ = '\0';
94         signal(SIGALRM, cleanup);
95         (void) alarm(TIME_LIMIT);
96         if (isdigit(*host) && (defaddr.s_addr = inet_addr(host)) != -1) {
97                 def.h_name = host;
98                 def.h_addr_list = alist;
99                 def.h_addr = (char *)&defaddr;
100                 def.h_length = sizeof(struct in_addr);
101                 def.h_addrtype = AF_INET;
102                 def.h_aliases = 0;
103                 hp = &def;
104         } else if (!(hp = gethostbyname(host))) {
105                 warnx("unknown host: %s", host);
106                 return;
107         }
108         if (!(sp = getservbyname("finger", "tcp"))) {
109                 warnx("tcp/finger: unknown service");
110                 return;
111         }
112         sin.sin_family = hp->h_addrtype;
113         bcopy(hp->h_addr, (char *)&sin.sin_addr, MIN(hp->h_length,sizeof(sin.sin_addr)));
114         sin.sin_port = sp->s_port;
115         if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
116                 perror("finger: socket");
117                 return;
118         }
119
120         /* have network connection; identify the host connected with */
121         (void)printf("[%s]\n", hp->h_name);
122
123         msg.msg_name = (void *)&sin;
124         msg.msg_namelen = sizeof sin;
125         msg.msg_iov = iov;
126         msg.msg_iovlen = 0;
127         msg.msg_control = 0;
128         msg.msg_controllen = 0;
129         msg.msg_flags = 0;
130
131         /* -l flag for remote fingerd  */
132         if (lflag) {
133                 iov[msg.msg_iovlen].iov_base = "/W ";
134                 iov[msg.msg_iovlen++].iov_len = 3;
135         }
136         /* send the name followed by <CR><LF> */
137         iov[msg.msg_iovlen].iov_base = name;
138         iov[msg.msg_iovlen++].iov_len = strlen(name);
139         iov[msg.msg_iovlen].iov_base = "\r\n";
140         iov[msg.msg_iovlen++].iov_len = 2;
141
142         /* -T disables T/TCP: compatibility option to finger broken hosts */
143         if (Tflag && connect(s, (struct sockaddr *)&sin, sizeof (sin))) {
144                 perror("finger: connect");
145                 return;
146         }
147
148         if (sendmsg(s, &msg, 0) < 0) {
149                 perror("finger: sendmsg");
150                 close(s);
151                 return;
152         }
153
154         /*
155          * Read from the remote system; once we're connected, we assume some
156          * data.  If none arrives, we hang until the user interrupts.
157          *
158          * If we see a <CR> or a <CR> with the high bit set, treat it as
159          * a newline; if followed by a newline character, only output one
160          * newline.
161          *
162          * Otherwise, all high bits are stripped; if it isn't printable and
163          * it isn't a space, we can simply set the 7th bit.  Every ASCII
164          * character with bit 7 set is printable.
165          */
166         lastc = 0;
167         if ((fp = fdopen(s, "r")) != NULL) {
168                 cnt = 0;
169                 line_len = 0;
170                 while ((c = getc(fp)) != EOF) {
171                         if (++cnt > OUTPUT_MAX) {
172                                 printf("\n\n Output truncated at %d bytes...\n",
173                                         cnt - 1);
174                                 break;
175                         }
176                         if (c == 0x0d) {
177                                 if (lastc == '\r')      /* ^M^M - skip dupes */
178                                         continue;
179                                 c = '\n';
180                                 lastc = '\r';
181                         } else {
182                                 if (!isprint(c) && !isspace(c)) {
183                                         c &= 0x7f;
184                                         c |= 0x40;
185                                 }
186                                 if (lastc != '\r' || c != '\n')
187                                         lastc = c;
188                                 else {
189                                         lastc = '\n';
190                                         continue;
191                                 }
192                         }
193                         putchar(c);
194                         if (c != '\n' && ++line_len > _POSIX2_LINE_MAX) {
195                                 putchar('\\');
196                                 putchar('\n');
197                                 lastc = '\r';
198                         }
199                         if (lastc == '\n' || lastc == '\r')
200                                 line_len = 0;
201                 }
202                 if (lastc != '\n')
203                         putchar('\n');
204
205                 if (ferror(fp)) {
206                         /*
207                          * Assume that whatever it was set errno...
208                          */
209                         perror("finger: read");
210                 }
211                 (void)fclose(fp);
212         }
213 }