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