1 /* 2 * Copyright (c) 1983 Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)announce.c 5.9 (Berkeley) 02/26/91"; 10 #endif /* not lint */ 11 12 #include <sys/types.h> 13 #include <sys/stat.h> 14 #include <sys/time.h> 15 #include <sys/wait.h> 16 #include <sys/socket.h> 17 #include <protocols/talkd.h> 18 #include <sgtty.h> 19 #include <errno.h> 20 #include <syslog.h> 21 #include <unistd.h> 22 #include <stdio.h> 23 #include <string.h> 24 #include <paths.h> 25 26 extern char hostname[]; 27 28 /* 29 * Announce an invitation to talk. 30 * 31 * Because the tty driver insists on attaching a terminal-less 32 * process to any terminal that it writes on, we must fork a child 33 * to protect ourselves 34 */ 35 announce(request, remote_machine) 36 CTL_MSG *request; 37 char *remote_machine; 38 { 39 int pid, val, status; 40 41 if (pid = fork()) { 42 /* we are the parent, so wait for the child */ 43 if (pid == -1) /* the fork failed */ 44 return (FAILED); 45 do { 46 val = wait(&status); 47 if (val == -1) { 48 if (errno == EINTR) 49 continue; 50 /* shouldn't happen */ 51 syslog(LOG_WARNING, "announce: wait: %m"); 52 return (FAILED); 53 } 54 } while (val != pid); 55 if (status&0377 > 0) /* we were killed by some signal */ 56 return (FAILED); 57 /* Get the second byte, this is the exit/return code */ 58 return ((status >> 8) & 0377); 59 } 60 /* we are the child, go and do it */ 61 _exit(announce_proc(request, remote_machine)); 62 } 63 64 /* 65 * See if the user is accepting messages. If so, announce that 66 * a talk is requested. 67 */ 68 announce_proc(request, remote_machine) 69 CTL_MSG *request; 70 char *remote_machine; 71 { 72 int pid, status; 73 char full_tty[32]; 74 FILE *tf; 75 struct stat stbuf; 76 77 (void)sprintf(full_tty, "%s/%s", _PATH_DEV, request->r_tty); 78 if (access(full_tty, 0) != 0) 79 return (FAILED); 80 if ((tf = fopen(full_tty, "w")) == NULL) 81 return (PERMISSION_DENIED); 82 /* 83 * On first tty open, the server will have 84 * it's pgrp set, so disconnect us from the 85 * tty before we catch a signal. 86 */ 87 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 88 if (fstat(fileno(tf), &stbuf) < 0) 89 return (PERMISSION_DENIED); 90 if ((stbuf.st_mode&020) == 0) 91 return (PERMISSION_DENIED); 92 print_mesg(tf, request, remote_machine); 93 fclose(tf); 94 return (SUCCESS); 95 } 96 97 #define max(a,b) ( (a) > (b) ? (a) : (b) ) 98 #define N_LINES 5 99 #define N_CHARS 120 100 101 /* 102 * Build a block of characters containing the message. 103 * It is sent blank filled and in a single block to 104 * try to keep the message in one piece if the recipient 105 * in in vi at the time 106 */ 107 print_mesg(tf, request, remote_machine) 108 FILE *tf; 109 CTL_MSG *request; 110 char *remote_machine; 111 { 112 struct timeval clock; 113 struct timezone zone; 114 struct tm *localtime(); 115 struct tm *localclock; 116 char line_buf[N_LINES][N_CHARS]; 117 int sizes[N_LINES]; 118 char big_buf[N_LINES*N_CHARS]; 119 char *bptr, *lptr; 120 int i, j, max_size; 121 122 i = 0; 123 max_size = 0; 124 gettimeofday(&clock, &zone); 125 localclock = localtime( &clock.tv_sec ); 126 (void)sprintf(line_buf[i], " "); 127 sizes[i] = strlen(line_buf[i]); 128 max_size = max(max_size, sizes[i]); 129 i++; 130 (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...", 131 hostname, localclock->tm_hour , localclock->tm_min ); 132 sizes[i] = strlen(line_buf[i]); 133 max_size = max(max_size, sizes[i]); 134 i++; 135 (void)sprintf(line_buf[i], "talk: connection requested by %s@%s.", 136 request->l_name, remote_machine); 137 sizes[i] = strlen(line_buf[i]); 138 max_size = max(max_size, sizes[i]); 139 i++; 140 (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s", 141 request->l_name, remote_machine); 142 sizes[i] = strlen(line_buf[i]); 143 max_size = max(max_size, sizes[i]); 144 i++; 145 (void)sprintf(line_buf[i], " "); 146 sizes[i] = strlen(line_buf[i]); 147 max_size = max(max_size, sizes[i]); 148 i++; 149 bptr = big_buf; 150 *bptr++ = ''; /* send something to wake them up */ 151 *bptr++ = '\r'; /* add a \r in case of raw mode */ 152 *bptr++ = '\n'; 153 for (i = 0; i < N_LINES; i++) { 154 /* copy the line into the big buffer */ 155 lptr = line_buf[i]; 156 while (*lptr != '\0') 157 *(bptr++) = *(lptr++); 158 /* pad out the rest of the lines with blanks */ 159 for (j = sizes[i]; j < max_size + 2; j++) 160 *(bptr++) = ' '; 161 *(bptr++) = '\r'; /* add a \r in case of raw mode */ 162 *(bptr++) = '\n'; 163 } 164 *bptr = '\0'; 165 fprintf(tf, big_buf); 166 fflush(tf); 167 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 168 } 169