blob: 4534fb9e3ebcac8c650363e6e10faeedeff5d817 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* *************************************************************************
2* NAME: chatchat.c
3*
4* DESCRIPTION:
5*
6* This program creates a pipe for the chat process to read. The user
7* can supply information (like a password) that will be picked up
8* by chat and sent just like the regular contents of a chat script.
9*
10* Usage is:
11*
12* chatchat <filename>
13*
14* where <filename> matches the option given in the chat script.
15*
16* for instance the chat script fragment:
17*
18* ...
19* name: \\dmyname \
20* word: @/var/tmp/p \
21* ...
22* ^
23* (note: leave some whitespace after the filename)
24*
25* expect "name:", reply with a delay followed by "myname"
26* expect "word:", reply with the data read from the pipe /var/tmp/p
27*
28* the matching usage of chatchat would be:
29*
30* chatchat /var/tmp/p
31*
32* eg:
33*
34* $chatchat /var/tmp/p
35* ...
36* some other process eventually starts:
37* chat ...
38* chat parses the "@/var/tmp/p" option and opens
39* /var/tmp/p
40* (chatchat prompts:)
41*
42* type PIN into SecurID card
43* enter resulting passcode: [user inputs something]
44*
45* chat reads /var/tmp/p & gets what the
46* user typed at chatchat's "enter string" prompt
47* chat removes the pipe file
48* chat sends the user's input as a response in
49* place of "@/var/tmp/p"
50*
51* PROCESS:
52*
53* gcc -g -o chatchat chatchat.c
54*
55*
56* GLOBALS: none
57*
58* REFERENCES:
59*
60* see the man pages and documentation that come with the 'chat' program
61* (part of the ppp package). you will need to use the modified chat
62* program that accepts the '@' operator.
63*
64* LIMITATIONS:
65*
66* REVISION HISTORY:
67*
68* STR Description Author
69*
70* 23-Mar-99 initial coding gpk
71* 12-May-99 unlink the pipe after closing paulus
72*
73* TARGET: ANSI C
74* This program is in the public domain.
75*
76*
77* ************************************************************************* */
78
79
80
81
82#include <sys/time.h>
83#include <stdio.h>
84#include <sys/types.h>
85#include <sys/stat.h>
86#include <fcntl.h>
87#include <unistd.h>
88#include <string.h>
89
90/* MAXINPUT - the data typed into chatchat must be fewer */
91/* characters than this. */
92
93#define MAXINPUT 80
94
95
96
97
98
99
100/* *************************************************************************
101
102
103 NAME: main
104
105
106 USAGE:
107
108 int argc;
109 char * argv[];
110
111 main(argc, argv[]);
112
113 returns: int
114
115 DESCRIPTION:
116 if the pipe file name is given on the command line,
117 create the pipe, prompt the user and put whatever
118 is typed into the pipe.
119
120 returns -1 on error
121 else # characters entered
122 REFERENCES:
123
124 LIMITATIONS:
125
126 GLOBAL VARIABLES:
127
128 accessed: none
129
130 modified: none
131
132 FUNCTIONS CALLED:
133
134 REVISION HISTORY:
135
136 STR Description of Revision Author
137
138 25-Mar-99 initial coding gpk
139
140 ************************************************************************* */
141
142int main(int argc, char * argv[])
143{
144 int retval;
145
146 int create_and_write_pipe(char * pipename);
147
148 if (argc != 2)
149 {
150 fprintf(stderr, "usage: %s pipename\n", argv[0]);
151 retval = -1;
152 }
153 else
154 {
155 retval = create_and_write_pipe(argv[1]);
156 }
157 return (retval);
158}
159
160
161
162
163/* *************************************************************************
164
165
166 NAME: create_and_write_pipe
167
168
169 USAGE:
170
171 int some_int;
172 char * pipename;
173
174 some_int = create_and_write_pipe(pipename);
175
176 returns: int
177
178 DESCRIPTION:
179 given the pipename, create the pipe, open it,
180 prompt the user for a string to put into the
181 pipe, write the string, and close the pipe
182
183 on error, print out an error message and return -1
184
185 returns -1 on error
186 else #bytes written into the pipe
187 REFERENCES:
188
189 LIMITATIONS:
190
191 GLOBAL VARIABLES:
192
193 accessed: none
194
195 modified: none
196
197 FUNCTIONS CALLED:
198
199 REVISION HISTORY:
200
201 STR Description of Revision Author
202
203 25-Mar-99 initial coding gpk
204 12-May-99 remove pipe after closing paulus
205
206 ************************************************************************* */
207
208int create_and_write_pipe(char * pipename)
209{
210 int retval, created, pipefd, nread, nwritten;
211 char input[MAXINPUT];
212 char errstring[180];
213
214 int create_pipe(char * pipename);
215 int write_to_pipe(int pipefd, char * input, int nchar);
216
217 created = create_pipe(pipename);
218
219 if (-1 == created)
220 {
221 sprintf(errstring, "unable to create pipe '%s'", pipename);
222 perror(errstring);
223 retval = -1;
224 }
225 else
226 {
227
228 /* note: this open won't succeed until chat has the pipe */
229 /* open and ready to read. this makes for nice timing. */
230
231 pipefd = open(pipename, O_WRONLY);
232
233 if (-1 == pipefd)
234 {
235 sprintf(errstring, "unable to open pipe '%s'", pipename);
236 perror(errstring);
237 retval = -1;
238 }
239 else
240 {
241 fprintf(stderr, "%s \n %s",
242 "type PIN into SecurID card and",
243 "enter resulting passcode:");
244 nread = read(STDIN_FILENO, (void *)input, MAXINPUT);
245
246
247 if (0 >= nread)
248 {
249 perror("unable to read from stdin");
250 retval = -1;
251 }
252 else
253 {
254 /* munch off the newline character, chat supplies */
255 /* a return when it sends the string out. */
256 input[nread -1] = 0;
257 nread--;
258 nwritten = write_to_pipe(pipefd, input, nread);
259 /* printf("wrote [%d]: '%s'\n", nwritten, input); */
260 retval = nwritten;
261 }
262 close(pipefd);
263
264 /* Now make the pipe go away. It won't actually go away
265 completely until chat closes it. */
266 if (unlink(pipename) < 0)
267 perror("Warning: couldn't remove pipe");
268 }
269 }
270 return(retval);
271}
272
273
274
275
276
277
278
279/* *************************************************************************
280
281
282 NAME: create_pipe
283
284
285 USAGE:
286
287 int some_int;
288 char * pipename;
289
290 some_int = create_pipe(pipename);
291
292 returns: int
293
294 DESCRIPTION:
295 create a pipe of the given name
296
297 if there is an error (like the pipe already exists)
298 print an error message and return
299
300 return -1 on failure else success
301
302 REFERENCES:
303
304 LIMITATIONS:
305
306 GLOBAL VARIABLES:
307
308 accessed: none
309
310 modified: none
311
312 FUNCTIONS CALLED:
313
314 REVISION HISTORY:
315
316 STR Description of Revision Author
317
318 25-Mar-99 initial coding gpk
319
320 ************************************************************************* */
321
322int create_pipe(char * pipename)
323{
324 mode_t old_umask;
325 int created;
326
327 /* hijack the umask temporarily to get the mode I want */
328 /* on the pipe. */
329
330 old_umask = umask(000);
331
332 created = mknod(pipename, S_IFIFO | S_IRWXU | S_IWGRP | S_IWOTH,
333 (dev_t)NULL);
334
335 /* now restore umask. */
336
337 (void)umask(old_umask);
338
339 if (-1 == created)
340 {
341 perror("unable to create pipe");
342 }
343
344 return(created);
345}
346
347
348
349
350
351
352/* *************************************************************************
353
354
355 NAME: write_to_pipe
356
357
358 USAGE:
359
360 int some_int;
361 int pipefd;
362 char * input;
363 int nchar;
364
365 some_int = write_to_pipe(pipefd, input, nchar);
366
367 returns: int
368
369 DESCRIPTION:
370 write nchars of data from input to pipefd
371
372 on error print a message to stderr
373
374 return -1 on error, else # bytes written
375 REFERENCES:
376
377 LIMITATIONS:
378
379 GLOBAL VARIABLES:
380
381 accessed: none
382
383 modified: none
384
385 FUNCTIONS CALLED:
386
387 REVISION HISTORY:
388
389 STR Description of Revision Author
390
391 25-Mar-99 initial coding gpk
392 12-May-99 don't write count word first paulus
393
394 ************************************************************************* */
395
396int write_to_pipe(int pipefd, char * input, int nchar)
397{
398 int nwritten;
399
400 /* nwritten = write(pipefd, (void *)&nchar, sizeof(nchar)); */
401 nwritten = write(pipefd, (void *)input, nchar);
402
403 if (-1 == nwritten)
404 {
405 perror("unable to write to pipe");
406 }
407
408 return(nwritten);
409}