1/* ************************************************************************* 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} 410