122387Sdist /* 222387Sdist * Copyright (c) 1983 Regents of the University of California. 334360Sbostic * All rights reserved. 434360Sbostic * 542673Sbostic * %sccs.include.redist.c% 622387Sdist */ 722387Sdist 816362Skarels #ifndef lint 9*46683Sbostic static char sccsid[] = "@(#)announce.c 5.9 (Berkeley) 02/26/91"; 1034360Sbostic #endif /* not lint */ 1116341Skarels 1226839Smckusick #include <sys/types.h> 1316341Skarels #include <sys/stat.h> 1416341Skarels #include <sys/time.h> 1516341Skarels #include <sys/wait.h> 16*46683Sbostic #include <sys/socket.h> 17*46683Sbostic #include <protocols/talkd.h> 18*46683Sbostic #include <sgtty.h> 1916341Skarels #include <errno.h> 2026839Smckusick #include <syslog.h> 21*46683Sbostic #include <unistd.h> 22*46683Sbostic #include <stdio.h> 23*46683Sbostic #include <string.h> 2437991Sbostic #include <paths.h> 2516341Skarels 26*46683Sbostic extern char hostname[]; 2716341Skarels 2816341Skarels /* 2926839Smckusick * Announce an invitation to talk. 3026839Smckusick * 3116341Skarels * Because the tty driver insists on attaching a terminal-less 3216341Skarels * process to any terminal that it writes on, we must fork a child 3316341Skarels * to protect ourselves 3416341Skarels */ 3516341Skarels announce(request, remote_machine) 3616362Skarels CTL_MSG *request; 3716362Skarels char *remote_machine; 3816341Skarels { 3916362Skarels int pid, val, status; 4016341Skarels 4116362Skarels if (pid = fork()) { 4216362Skarels /* we are the parent, so wait for the child */ 4316362Skarels if (pid == -1) /* the fork failed */ 4426839Smckusick return (FAILED); 4516362Skarels do { 4616362Skarels val = wait(&status); 4716362Skarels if (val == -1) { 4816362Skarels if (errno == EINTR) 4916362Skarels continue; 5016362Skarels /* shouldn't happen */ 5126839Smckusick syslog(LOG_WARNING, "announce: wait: %m"); 5216362Skarels return (FAILED); 5316362Skarels } 5416362Skarels } while (val != pid); 5516362Skarels if (status&0377 > 0) /* we were killed by some signal */ 5616362Skarels return (FAILED); 5716362Skarels /* Get the second byte, this is the exit/return code */ 5816362Skarels return ((status >> 8) & 0377); 5916341Skarels } 6016362Skarels /* we are the child, go and do it */ 6116341Skarels _exit(announce_proc(request, remote_machine)); 6216341Skarels } 6316341Skarels 6416362Skarels /* 6516362Skarels * See if the user is accepting messages. If so, announce that 6616362Skarels * a talk is requested. 6716362Skarels */ 6816341Skarels announce_proc(request, remote_machine) 6916362Skarels CTL_MSG *request; 7016362Skarels char *remote_machine; 7116341Skarels { 7216362Skarels int pid, status; 7316362Skarels char full_tty[32]; 7416362Skarels FILE *tf; 7516362Skarels struct stat stbuf; 7616341Skarels 7737991Sbostic (void)sprintf(full_tty, "%s/%s", _PATH_DEV, request->r_tty); 7816362Skarels if (access(full_tty, 0) != 0) 7916362Skarels return (FAILED); 8016362Skarels if ((tf = fopen(full_tty, "w")) == NULL) 8116362Skarels return (PERMISSION_DENIED); 8216362Skarels /* 8326839Smckusick * On first tty open, the server will have 8426839Smckusick * it's pgrp set, so disconnect us from the 8526839Smckusick * tty before we catch a signal. 8616362Skarels */ 8716362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 8816362Skarels if (fstat(fileno(tf), &stbuf) < 0) 8916362Skarels return (PERMISSION_DENIED); 9026854Smckusick if ((stbuf.st_mode&020) == 0) 9116362Skarels return (PERMISSION_DENIED); 9216362Skarels print_mesg(tf, request, remote_machine); 9316362Skarels fclose(tf); 9416362Skarels return (SUCCESS); 9516341Skarels } 9616341Skarels 9716341Skarels #define max(a,b) ( (a) > (b) ? (a) : (b) ) 9816341Skarels #define N_LINES 5 9916341Skarels #define N_CHARS 120 10016341Skarels 10116362Skarels /* 10216362Skarels * Build a block of characters containing the message. 10316362Skarels * It is sent blank filled and in a single block to 10416362Skarels * try to keep the message in one piece if the recipient 10516362Skarels * in in vi at the time 10616362Skarels */ 10716341Skarels print_mesg(tf, request, remote_machine) 10816362Skarels FILE *tf; 10916362Skarels CTL_MSG *request; 11016362Skarels char *remote_machine; 11116341Skarels { 11216362Skarels struct timeval clock; 11316362Skarels struct timezone zone; 11416362Skarels struct tm *localtime(); 11516362Skarels struct tm *localclock; 11616362Skarels char line_buf[N_LINES][N_CHARS]; 11716362Skarels int sizes[N_LINES]; 11816362Skarels char big_buf[N_LINES*N_CHARS]; 11916362Skarels char *bptr, *lptr; 12016362Skarels int i, j, max_size; 12116341Skarels 12216362Skarels i = 0; 12316362Skarels max_size = 0; 12416362Skarels gettimeofday(&clock, &zone); 12516362Skarels localclock = localtime( &clock.tv_sec ); 12632465Sbostic (void)sprintf(line_buf[i], " "); 12716362Skarels sizes[i] = strlen(line_buf[i]); 12816362Skarels max_size = max(max_size, sizes[i]); 12916362Skarels i++; 13032465Sbostic (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...", 13116341Skarels hostname, localclock->tm_hour , localclock->tm_min ); 13216362Skarels sizes[i] = strlen(line_buf[i]); 13316362Skarels max_size = max(max_size, sizes[i]); 13416362Skarels i++; 13532465Sbostic (void)sprintf(line_buf[i], "talk: connection requested by %s@%s.", 13616341Skarels request->l_name, remote_machine); 13716362Skarels sizes[i] = strlen(line_buf[i]); 13816362Skarels max_size = max(max_size, sizes[i]); 13916362Skarels i++; 14032465Sbostic (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s", 14116341Skarels request->l_name, remote_machine); 14216362Skarels sizes[i] = strlen(line_buf[i]); 14316362Skarels max_size = max(max_size, sizes[i]); 14416362Skarels i++; 14532465Sbostic (void)sprintf(line_buf[i], " "); 14616362Skarels sizes[i] = strlen(line_buf[i]); 14716362Skarels max_size = max(max_size, sizes[i]); 14816362Skarels i++; 14916362Skarels bptr = big_buf; 15026839Smckusick *bptr++ = ''; /* send something to wake them up */ 15126839Smckusick *bptr++ = '\r'; /* add a \r in case of raw mode */ 15226839Smckusick *bptr++ = '\n'; 15316362Skarels for (i = 0; i < N_LINES; i++) { 15416362Skarels /* copy the line into the big buffer */ 15516362Skarels lptr = line_buf[i]; 15616362Skarels while (*lptr != '\0') 15716362Skarels *(bptr++) = *(lptr++); 15816362Skarels /* pad out the rest of the lines with blanks */ 15916362Skarels for (j = sizes[i]; j < max_size + 2; j++) 16016362Skarels *(bptr++) = ' '; 16116362Skarels *(bptr++) = '\r'; /* add a \r in case of raw mode */ 16216362Skarels *(bptr++) = '\n'; 16316362Skarels } 16416362Skarels *bptr = '\0'; 16516362Skarels fprintf(tf, big_buf); 16616362Skarels fflush(tf); 16716362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 16816341Skarels } 169