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