chatchat.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. #include <sys/time.h>
  79. #include <stdio.h>
  80. #include <sys/types.h>
  81. #include <sys/stat.h>
  82. #include <fcntl.h>
  83. #include <unistd.h>
  84. #include <string.h>
  85. /* MAXINPUT - the data typed into chatchat must be fewer */
  86. /* characters than this. */
  87. #define MAXINPUT 80
  88. /* *************************************************************************
  89. NAME: main
  90. USAGE:
  91. int argc;
  92. char * argv[];
  93. main(argc, argv[]);
  94. returns: int
  95. DESCRIPTION:
  96. if the pipe file name is given on the command line,
  97. create the pipe, prompt the user and put whatever
  98. is typed into the pipe.
  99. returns -1 on error
  100. else # characters entered
  101. REFERENCES:
  102. LIMITATIONS:
  103. GLOBAL VARIABLES:
  104. accessed: none
  105. modified: none
  106. FUNCTIONS CALLED:
  107. REVISION HISTORY:
  108. STR Description of Revision Author
  109. 25-Mar-99 initial coding gpk
  110. ************************************************************************* */
  111. int main(int argc, char * argv[])
  112. {
  113. int retval;
  114. int create_and_write_pipe(char * pipename);
  115. if (argc != 2)
  116. {
  117. fprintf(stderr, "usage: %s pipename\n", argv[0]);
  118. retval = -1;
  119. }
  120. else
  121. {
  122. retval = create_and_write_pipe(argv[1]);
  123. }
  124. return (retval);
  125. }
  126. /* *************************************************************************
  127. NAME: create_and_write_pipe
  128. USAGE:
  129. int some_int;
  130. char * pipename;
  131. some_int = create_and_write_pipe(pipename);
  132. returns: int
  133. DESCRIPTION:
  134. given the pipename, create the pipe, open it,
  135. prompt the user for a string to put into the
  136. pipe, write the string, and close the pipe
  137. on error, print out an error message and return -1
  138. returns -1 on error
  139. else #bytes written into the pipe
  140. REFERENCES:
  141. LIMITATIONS:
  142. GLOBAL VARIABLES:
  143. accessed: none
  144. modified: none
  145. FUNCTIONS CALLED:
  146. REVISION HISTORY:
  147. STR Description of Revision Author
  148. 25-Mar-99 initial coding gpk
  149. 12-May-99 remove pipe after closing paulus
  150. ************************************************************************* */
  151. int create_and_write_pipe(char * pipename)
  152. {
  153. int retval, created, pipefd, nread, nwritten;
  154. char input[MAXINPUT];
  155. char errstring[180];
  156. int create_pipe(char * pipename);
  157. int write_to_pipe(int pipefd, char * input, int nchar);
  158. created = create_pipe(pipename);
  159. if (-1 == created)
  160. {
  161. sprintf(errstring, "unable to create pipe '%s'", pipename);
  162. perror(errstring);
  163. retval = -1;
  164. }
  165. else
  166. {
  167. /* note: this open won't succeed until chat has the pipe */
  168. /* open and ready to read. this makes for nice timing. */
  169. pipefd = open(pipename, O_WRONLY);
  170. if (-1 == pipefd)
  171. {
  172. sprintf(errstring, "unable to open pipe '%s'", pipename);
  173. perror(errstring);
  174. retval = -1;
  175. }
  176. else
  177. {
  178. fprintf(stderr, "%s \n %s",
  179. "type PIN into SecurID card and",
  180. "enter resulting passcode:");
  181. nread = read(STDIN_FILENO, (void *)input, MAXINPUT);
  182. if (0 >= nread)
  183. {
  184. perror("unable to read from stdin");
  185. retval = -1;
  186. }
  187. else
  188. {
  189. /* munch off the newline character, chat supplies */
  190. /* a return when it sends the string out. */
  191. input[nread -1] = 0;
  192. nread--;
  193. nwritten = write_to_pipe(pipefd, input, nread);
  194. /* printf("wrote [%d]: '%s'\n", nwritten, input); */
  195. retval = nwritten;
  196. }
  197. close(pipefd);
  198. /* Now make the pipe go away. It won't actually go away
  199. completely until chat closes it. */
  200. if (unlink(pipename) < 0)
  201. perror("Warning: couldn't remove pipe");
  202. }
  203. }
  204. return(retval);
  205. }
  206. /* *************************************************************************
  207. NAME: create_pipe
  208. USAGE:
  209. int some_int;
  210. char * pipename;
  211. some_int = create_pipe(pipename);
  212. returns: int
  213. DESCRIPTION:
  214. create a pipe of the given name
  215. if there is an error (like the pipe already exists)
  216. print an error message and return
  217. return -1 on failure else success
  218. REFERENCES:
  219. LIMITATIONS:
  220. GLOBAL VARIABLES:
  221. accessed: none
  222. modified: none
  223. FUNCTIONS CALLED:
  224. REVISION HISTORY:
  225. STR Description of Revision Author
  226. 25-Mar-99 initial coding gpk
  227. ************************************************************************* */
  228. int create_pipe(char * pipename)
  229. {
  230. mode_t old_umask;
  231. int created;
  232. /* hijack the umask temporarily to get the mode I want */
  233. /* on the pipe. */
  234. old_umask = umask(000);
  235. created = mknod(pipename, S_IFIFO | S_IRWXU | S_IWGRP | S_IWOTH,
  236. (dev_t)NULL);
  237. /* now restore umask. */
  238. (void)umask(old_umask);
  239. if (-1 == created)
  240. {
  241. perror("unable to create pipe");
  242. }
  243. return(created);
  244. }
  245. /* *************************************************************************
  246. NAME: write_to_pipe
  247. USAGE:
  248. int some_int;
  249. int pipefd;
  250. char * input;
  251. int nchar;
  252. some_int = write_to_pipe(pipefd, input, nchar);
  253. returns: int
  254. DESCRIPTION:
  255. write nchars of data from input to pipefd
  256. on error print a message to stderr
  257. return -1 on error, else # bytes written
  258. REFERENCES:
  259. LIMITATIONS:
  260. GLOBAL VARIABLES:
  261. accessed: none
  262. modified: none
  263. FUNCTIONS CALLED:
  264. REVISION HISTORY:
  265. STR Description of Revision Author
  266. 25-Mar-99 initial coding gpk
  267. 12-May-99 don't write count word first paulus
  268. ************************************************************************* */
  269. int write_to_pipe(int pipefd, char * input, int nchar)
  270. {
  271. int nwritten;
  272. /* nwritten = write(pipefd, (void *)&nchar, sizeof(nchar)); */
  273. nwritten = write(pipefd, (void *)input, nchar);
  274. if (-1 == nwritten)
  275. {
  276. perror("unable to write to pipe");
  277. }
  278. return(nwritten);
  279. }