|
1 /* FINGER.C |
|
2 * |
|
3 * Portions Copyright (c) 1993-2004 Nokia Corporation and/or its subsidiary(-ies). |
|
4 * All rights reserved. |
|
5 */ |
|
6 |
|
7 /* |
|
8 * Copyright (c) 1989, 1993 |
|
9 * The Regents of the University of California. All rights reserved. |
|
10 * |
|
11 * This code is derived from software contributed to Berkeley by |
|
12 * Tony Nardo of the Johns Hopkins University/Applied Physics Lab. |
|
13 * |
|
14 * Redistribution and use in source and binary forms, with or without |
|
15 * modification, are permitted provided that the following conditions |
|
16 * are met: |
|
17 * 1. Redistributions of source code must retain the above copyright |
|
18 * notice, this list of conditions and the following disclaimer. |
|
19 * 2. Redistributions in binary form must reproduce the above copyright |
|
20 * notice, this list of conditions and the following disclaimer in the |
|
21 * documentation and/or other materials provided with the distribution. |
|
22 * 3. All advertising materials mentioning features or use of this software |
|
23 * must display the following acknowledgement: |
|
24 * This product includes software developed by the University of |
|
25 * California, Berkeley and its contributors. |
|
26 * 4. Neither the name of the University nor the names of its contributors |
|
27 * may be used to endorse or promote products derived from this software |
|
28 * without specific prior written permission. |
|
29 * |
|
30 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
31 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
33 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
40 * SUCH DAMAGE. |
|
41 */ |
|
42 |
|
43 #include <sys/types.h> |
|
44 #include <sys/socket.h> |
|
45 #include <libc/netinet/in.h> |
|
46 #include <libc/arpa/inet.h> |
|
47 #include <netdb.h> |
|
48 #include <unistd.h> |
|
49 #include <stdio.h> |
|
50 #include <ctype.h> |
|
51 #include <string.h> |
|
52 #include <stdlib.h> |
|
53 |
|
54 int main (int argc, char* argv[]) |
|
55 { |
|
56 int c, lastc; |
|
57 struct in_addr defaddr; |
|
58 struct hostent *hp, def; |
|
59 struct sockaddr_in sin; |
|
60 int s, i; |
|
61 char *alist[1], *host; |
|
62 char request[100]; |
|
63 char input[80]; |
|
64 char* name; |
|
65 |
|
66 if (argc >= 2) |
|
67 { |
|
68 name = argv[1]; |
|
69 } |
|
70 else |
|
71 { |
|
72 printf("user@hostname? "); |
|
73 fflush(stdout); |
|
74 name = input; |
|
75 do |
|
76 { |
|
77 c = getchar(); |
|
78 if (c=='\b') /* DIY backspace processing */ |
|
79 { |
|
80 if (name > input) |
|
81 name--; |
|
82 continue; |
|
83 } |
|
84 if (c=='\n' || c=='\r') |
|
85 break; |
|
86 *name++ = c; |
|
87 } |
|
88 while (name < input+78); |
|
89 *name++ = '\0'; |
|
90 name = input; |
|
91 } |
|
92 host = strrchr(name, '@'); |
|
93 if (host==0) |
|
94 { |
|
95 printf("Usage: finger user@hostname\n"); |
|
96 exit(-2); |
|
97 } |
|
98 *host++ = NULL; |
|
99 |
|
100 /* Step 1 - resolve the IP address */ |
|
101 |
|
102 printf("\nLooking up IP address of %s...\n", host); |
|
103 |
|
104 if (isdigit(*host) && (defaddr.s_addr = inet_addr(host)) != INADDR_ANY) |
|
105 { |
|
106 def.h_name = host; |
|
107 def.h_addr_list = alist; |
|
108 def.h_addr = (char *)&defaddr; |
|
109 def.h_length = sizeof(struct in_addr); |
|
110 def.h_addrtype = AF_INET; |
|
111 def.h_aliases = 0; |
|
112 hp = &def; |
|
113 } |
|
114 else |
|
115 { |
|
116 hp = gethostbyname(host); |
|
117 if(!hp) |
|
118 { |
|
119 (void)fprintf(stderr, "finger: unknown host: %s\n", host); |
|
120 exit(-3); |
|
121 } |
|
122 } |
|
123 sin.sin_family = hp->h_addrtype; |
|
124 memcpy((char *)&sin.sin_addr, hp->h_addr, hp->h_length); |
|
125 if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { |
|
126 perror("finger: socket"); |
|
127 exit(-4); |
|
128 } |
|
129 |
|
130 (void)printf("\n %s => %s\n", hp->h_name, inet_ntoa(sin.sin_addr)); |
|
131 |
|
132 /* Step 2 - Connect to the finger port on the target host */ |
|
133 |
|
134 printf("\nConnecting to %s...", host); |
|
135 fflush(stdout); |
|
136 |
|
137 sin.sin_port = htons(IPPORT_FINGER); |
|
138 if (connect(s, (struct sockaddr *)&sin, sizeof (sin))) { |
|
139 perror("finger: connect"); |
|
140 exit(-5); |
|
141 } |
|
142 |
|
143 printf("OK\n"); |
|
144 |
|
145 /* Step 3 - Finger the user and read the result... */ |
|
146 |
|
147 printf("\nFinger %s@%s\n", name, host); |
|
148 |
|
149 /* send the name followed by <CR><LF> */ |
|
150 sprintf(request, "%s\r\n", name); |
|
151 if (write(s, request, strlen(request)) < 0) { |
|
152 perror("finger: write"); |
|
153 close(s); |
|
154 exit(-6); |
|
155 } |
|
156 |
|
157 /* Read from the remote system; once we're connected, we assume some |
|
158 * data. If none arrives, we hang until the user interrupts. |
|
159 * |
|
160 * If we see a <CR> or a <CR> with the high bit set, treat it as |
|
161 * a newline; if followed by a newline character, only output one |
|
162 * newline. |
|
163 * |
|
164 * Otherwise, all high bits are stripped; if it isn't printable and |
|
165 * it isn't a space, we can simply set the 7th bit. Every ASCII |
|
166 * character with bit 7 set is printable. |
|
167 */ |
|
168 lastc = '\n'; |
|
169 |
|
170 while (recv(s, &request[0], 1, 0) > 0) { |
|
171 c = request[0]; |
|
172 if (c == 0x0d) { |
|
173 if (lastc == '\r') /* ^M^M - skip dupes */ |
|
174 continue; |
|
175 c = '\n'; |
|
176 lastc = '\r'; |
|
177 } else { |
|
178 if (!isprint(c) && !isspace(c)) { |
|
179 c &= 0x7f; |
|
180 c |= 0x40; |
|
181 } |
|
182 if (lastc != '\r' || c != '\n') |
|
183 lastc = c; |
|
184 else { |
|
185 lastc = '\n'; |
|
186 continue; |
|
187 } |
|
188 } |
|
189 putchar(c); |
|
190 } |
|
191 if (lastc != '\n') |
|
192 putchar('\n'); |
|
193 close(s); |
|
194 |
|
195 /* Step 4 - Check the time on the remote machine as well */ |
|
196 |
|
197 if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) { |
|
198 perror("finger: socket"); |
|
199 exit(-7); |
|
200 } |
|
201 |
|
202 sin.sin_port = htons(IPPORT_DAYTIME); |
|
203 if (connect(s, (struct sockaddr *)&sin, sizeof (sin))) { |
|
204 perror("finger: connect"); |
|
205 exit(-8); |
|
206 } |
|
207 |
|
208 i = recv(s, request, sizeof(request)-1, 0); |
|
209 if (i<0) |
|
210 { |
|
211 perror("finger: recv"); |
|
212 exit(-9); |
|
213 } |
|
214 request[i] = '\0'; |
|
215 |
|
216 printf("\nThe time on %s is %s\n", host, request); |
|
217 close(s); |
|
218 |
|
219 return 0; |
|
220 } |