PageRenderTime 46ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/netkit-ntalk-0.17/talkd/announce.c

#
C | 219 lines | 135 code | 14 blank | 70 comment | 25 complexity | 6ed3d6452c51123124765269313c4830 MD5 | raw file
  1. /*
  2. * Copyright (c) 1983 Regents of the University of California.
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. All advertising materials mentioning features or use of this software
  14. * must display the following acknowledgement:
  15. * This product includes software developed by the University of
  16. * California, Berkeley and its contributors.
  17. * 4. Neither the name of the University nor the names of its contributors
  18. * may be used to endorse or promote products derived from this software
  19. * without specific prior written permission.
  20. *
  21. * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24. * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. */
  33. /*
  34. * From: @(#)announce.c 5.9 (Berkeley) 2/26/91
  35. */
  36. char ann_rcsid[] =
  37. "$Id: announce.c,v 1.8 2000/07/22 15:27:39 dholland Exp $";
  38. #include <sys/types.h>
  39. #include <sys/stat.h>
  40. #include <sys/time.h>
  41. #include <time.h>
  42. #include <sys/wait.h>
  43. #include <sys/socket.h>
  44. #include <errno.h>
  45. #include <syslog.h>
  46. #include <unistd.h>
  47. #include <stdio.h>
  48. #include <fcntl.h>
  49. #include <string.h>
  50. #include <paths.h>
  51. #include "prot_talkd.h"
  52. #include "proto.h"
  53. /*
  54. * Announce an invitation to talk.
  55. *
  56. * Because the tty driver insists on attaching a terminal-less
  57. * process to any terminal that it writes on, we must fork a child
  58. * to protect ourselves.
  59. *
  60. * That hasn't been true since, hrm, 4.2BSD maybe? Even in System V,
  61. * we can use O_NOCTTY. On the other hand, forking is a good idea in
  62. * case the tty hangs. But at present we don't take advantage of that;
  63. * we'd wait() forever.
  64. */
  65. /*
  66. * Reject control codes and other crap.
  67. * FUTURE: don't clear high ascii if the tty is in 8-bit mode
  68. * Note that we don't need to let through tabs or newlines here.
  69. */
  70. static int safechar(int ch) {
  71. if (ch>127 || ch<32) ch = '?';
  72. return ch;
  73. }
  74. #define max(a,b) ( (a) > (b) ? (a) : (b) )
  75. #define N_LINES 5
  76. #define N_CHARS 120
  77. /*
  78. * Build a block of characters containing the message.
  79. * It is sent blank filled and in a single block to
  80. * try to keep the message in one piece if the recipient
  81. * is in, say, vi at the time.
  82. */
  83. static void
  84. print_mesg(int fd, CTL_MSG *request, const char *remote_machine)
  85. {
  86. struct timeval clocc;
  87. struct timezone zone;
  88. struct tm *localclock;
  89. char line_buf[N_LINES][N_CHARS];
  90. int sizes[N_LINES];
  91. char big_buf[N_LINES*(N_CHARS+2)+16];
  92. char *bptr, *lptr;
  93. int i, j, max_size;
  94. time_t footime;
  95. i = 0;
  96. max_size = 0;
  97. gettimeofday(&clocc, &zone);
  98. footime = clocc.tv_sec;
  99. localclock = localtime(&footime);
  100. snprintf(line_buf[i], N_CHARS, " ");
  101. sizes[i] = strlen(line_buf[i]);
  102. max_size = max(max_size, sizes[i]);
  103. i++;
  104. snprintf(line_buf[i], N_CHARS,
  105. "Message from Talk_Daemon@%s at %d:%02d ...",
  106. ourhostname, localclock->tm_hour, localclock->tm_min);
  107. sizes[i] = strlen(line_buf[i]);
  108. max_size = max(max_size, sizes[i]);
  109. i++;
  110. snprintf(line_buf[i], N_CHARS, "talk: connection requested by %s@%s.",
  111. request->l_name, remote_machine);
  112. sizes[i] = strlen(line_buf[i]);
  113. max_size = max(max_size, sizes[i]);
  114. i++;
  115. if (strpbrk(request->l_name, ":!.") != NULL)
  116. snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s -x",
  117. request->l_name, remote_machine);
  118. else
  119. snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s",
  120. request->l_name, remote_machine);
  121. sizes[i] = strlen(line_buf[i]);
  122. max_size = max(max_size, sizes[i]);
  123. i++;
  124. snprintf(line_buf[i], N_CHARS, " ");
  125. sizes[i] = strlen(line_buf[i]);
  126. max_size = max(max_size, sizes[i]);
  127. i++;
  128. bptr = big_buf;
  129. *bptr++ = ''; /* send something to wake them up */
  130. *bptr++ = '\r'; /* add a \r in case of raw mode */
  131. *bptr++ = '\n';
  132. for (i = 0; i < N_LINES; i++) {
  133. /* copy the line into the big buffer */
  134. lptr = line_buf[i];
  135. while (*lptr != '\0')
  136. *(bptr++) = safechar(*(lptr++));
  137. /* pad out the rest of the lines with blanks */
  138. for (j = sizes[i]; j < max_size + 2; j++)
  139. *(bptr++) = ' ';
  140. *(bptr++) = '\r'; /* add a \r in case of raw mode */
  141. *(bptr++) = '\n';
  142. }
  143. *bptr = 0;
  144. write(fd, big_buf, strlen(big_buf));
  145. }
  146. /*
  147. * See if the user is accepting messages. If so, announce that
  148. * a talk is requested.
  149. */
  150. static int
  151. announce_proc(CTL_MSG *request, const char *remote_machine)
  152. {
  153. char full_tty[32];
  154. int fd;
  155. struct stat stbuf;
  156. snprintf(full_tty, sizeof(full_tty), "%s/%s", _PATH_DEV,
  157. request->r_tty);
  158. if (access(full_tty, F_OK) != 0)
  159. return FAILED;
  160. fd = open(full_tty, O_WRONLY|O_NOCTTY);
  161. if (fd<0) {
  162. return (PERMISSION_DENIED);
  163. }
  164. if (fstat(fd, &stbuf) < 0) {
  165. return (PERMISSION_DENIED);
  166. }
  167. if ((stbuf.st_mode&020) == 0) {
  168. return (PERMISSION_DENIED);
  169. }
  170. print_mesg(fd, request, remote_machine);
  171. close(fd);
  172. return SUCCESS;
  173. }
  174. int
  175. announce(CTL_MSG *request, const char *remote_machine)
  176. {
  177. int pid, val, status;
  178. pid = fork();
  179. if (pid==-1) {
  180. /* fork failed */
  181. return FAILED;
  182. }
  183. if (pid==0) {
  184. /* child */
  185. status = announce_proc(request, remote_machine);
  186. _exit(status);
  187. }
  188. /* we are the parent, so wait for the child */
  189. do {
  190. val = wait(&status);
  191. if (val == -1) {
  192. if (errno == EINTR || errno == EAGAIN)
  193. continue;
  194. /* shouldn't happen */
  195. syslog(LOG_WARNING, "announce: wait: %m");
  196. return (FAILED);
  197. }
  198. } while (val != pid);
  199. if (WIFSIGNALED(status)) {
  200. /* we were killed by some signal */
  201. return FAILED;
  202. }
  203. /* Send back the exit/return code */
  204. return (WEXITSTATUS(status));
  205. }