source: trunk/minix/commands/talk/talk.c@ 20

Last change on this file since 20 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 4.8 KB
Line 
1/* talk.c Copyright Michael Temari 08/01/1996 All Rights Reserved */
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <stdio.h>
6#include <string.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <signal.h>
10#include <utmp.h>
11#include <termios.h>
12#include <net/gen/netdb.h>
13#include <net/hton.h>
14#include <net/gen/socket.h>
15#include <net/gen/in.h>
16#include <net/gen/inet.h>
17#include <net/gen/tcp.h>
18#include <net/gen/udp.h>
19
20#include "talk.h"
21#include "proto.h"
22#include "net.h"
23#include "screen.h"
24
25_PROTOTYPE(int main, (int argc, char *argv[]));
26_PROTOTYPE(void DoTalk, (void));
27
28int main(argc, argv)
29int argc;
30char *argv[];
31{
32char *p;
33struct hostent *hp;
34struct stat st;
35struct utmp utmp;
36int slot;
37FILE *fp;
38
39 if(argc < 2 || argc > 3) {
40 fprintf(stderr, "Usage: talk user[@host] [tty]\n");
41 return(-1);
42 }
43
44 /* get local host name */
45 if(gethostname(lhost, HOST_SIZE) < 0) {
46 fprintf(stderr, "talk: Error getting local host name\n");
47 return(-1);
48 }
49
50 /* get local user name and tty */
51 if((slot = ttyslot()) < 0) {
52 fprintf(stderr, "talk: You are not on a terminal\n");
53 return(-1);
54 }
55 if((fp = fopen(UTMP, "r")) == (FILE *)NULL) {
56 fprintf(stderr, "talk: Could not open %s\n", UTMP);
57 return(-1);
58 }
59 if(fseek(fp, (off_t) sizeof(utmp) * slot, SEEK_SET)) {
60 fprintf(stderr, "talk: Could not seek %s\n", UTMP);
61 fclose(fp);
62 return(-1);
63 }
64 if(fread((char *)&utmp, sizeof(utmp), 1 , fp) != 1) {
65 fprintf(stderr, "talk: Could not read %s\n", UTMP);
66 fclose(fp);
67 return(-1);
68 }
69 fclose(fp);
70 strncpy(luser, utmp.ut_user, USER_SIZE < sizeof(utmp.ut_user) ?
71 USER_SIZE : sizeof(utmp.ut_user));
72 luser[USER_SIZE] = '\0';
73
74 /* get local tty */
75 if((p = ttyname(0)) == (char *)NULL) {
76 fprintf(stderr, "talk: You are not on a terminal\n");
77 return(-1);
78 }
79 strncpy(ltty, p+5, TTY_SIZE);
80 ltty[TTY_SIZE] = '\0';
81
82 /* check if local tty is going to be writable */
83 if(stat(p, &st) < 0) {
84 perror("talk: Could not stat local tty");
85 return(-1);
86 }
87 if((st.st_mode & S_IWGRP) == 0) {
88 fprintf(stderr, "talk: Your terminal is not writable. Use: mesg y\n");
89 return(-1);
90 }
91
92 /* get remote user and host name */
93 if((p = strchr(argv[1], '@')) != (char *)NULL)
94 *p++ = '\0';
95 else
96 p = lhost;
97 strncpy(ruser, argv[1], USER_SIZE);
98 ruser[USER_SIZE] = '\0';
99 strncpy(rhost, p, HOST_SIZE);
100 rhost[HOST_SIZE] = '\0';
101
102 /* get remote tty */
103 if(argc > 2)
104 strncpy(rtty, argv[2], TTY_SIZE);
105 else
106 rtty[0] = '\0';
107 rtty[TTY_SIZE] = '\0';
108
109 if((hp = gethostbyname(rhost)) == (struct hostent *)NULL) {
110 fprintf(stderr, "talk: Could not determine address of %s\n", rhost);
111 return(-1);
112 }
113 memcpy((char *)&raddr, (char *)hp->h_addr, hp->h_length);
114
115 if(NetInit()) {
116 fprintf(stderr, "talk: Error in NetInit\n");
117 return(-1);
118 }
119
120 if(ScreenInit())
121 return(-1);
122
123 if(!TalkInit())
124 DoTalk();
125
126 ScreenEnd();
127
128 return(0);
129}
130
131struct pdata {
132 int win;
133 int len;
134 char buffer[64];
135} pdata;
136
137void DoTalk()
138{
139int s;
140int s2;
141int kid;
142int pfd[2];
143int win;
144int len;
145struct termios termios;
146char lcc[3];
147char rcc[3];
148
149 ScreenMsg("");
150 ScreenWho(ruser, rhost);
151
152 /* Get and send edit characters */
153 s = tcgetattr(0, &termios);
154 if(s < 0) {
155 perror("talk: tcgetattr");
156 return;
157 }
158 lcc[0] = termios.c_cc[VERASE];
159 lcc[1] = termios.c_cc[VKILL];
160 lcc[2] = 0x17; /* Control - W */
161 s = write(tcp_fd, lcc, sizeof(lcc));
162 if(s != sizeof(lcc)) {
163 ScreenMsg("Connection Closing due to error");
164 return;
165 }
166 s = read(tcp_fd, rcc, sizeof(rcc));
167 if(s != sizeof(rcc)) {
168 ScreenMsg("Connection Closing due to error");
169 return;
170 }
171 ScreenEdit(lcc, rcc);
172
173 s = pipe(pfd);
174 if(s < 0) {
175 ScreenMsg("Could not create pipes");
176 return;
177 }
178
179 if((kid = fork()) < 0) {
180 ScreenMsg("Could not fork");
181 close(pfd[0]);
182 close(pfd[1]);
183 return;
184 }
185
186 if(kid == 0) {
187 close(tcp_fd);
188 close(pfd[1]);
189 while(1) {
190 s = read(pfd[0], &pdata, sizeof(pdata));
191 if(s != sizeof(pdata)) {
192 close(pfd[0]);
193 exit(-1);
194 }
195 ScreenPut(pdata.buffer, pdata.len, pdata.win);
196 }
197 }
198
199 close(pfd[0]);
200
201 if((kid = fork()) < 0) {
202 ScreenMsg("Could not fork");
203 close(pfd[1]);
204 return;
205 }
206
207 if(kid == 0) {
208 pdata.win = REMOTEWIN;
209 while(!ScreenDone) {
210 s = read(tcp_fd, pdata.buffer, sizeof(pdata.buffer));
211 if(s <= 0)
212 break;
213 pdata.len = s;
214 write(pfd[1], &pdata, sizeof(pdata));
215 }
216 close(pfd[1]);
217 close(tcp_fd);
218 kill(getppid(), SIGINT);
219 exit(-1);
220 }
221
222 pdata.win = LOCALWIN;
223 while(!ScreenDone) {
224 s = read(0, pdata.buffer, sizeof(pdata.buffer));
225 if(s <= 0)
226 break;
227 pdata.len = s;
228 write(pfd[1], &pdata, sizeof(pdata));
229 s2 = write(tcp_fd, pdata.buffer, s);
230 if(s2 != s)
231 break;
232 }
233 kill(kid, SIGINT);
234 close(pfd[1]);
235 close(tcp_fd);
236 return;
237}
Note: See TracBrowser for help on using the repository browser.