122387Sdist /* 222387Sdist * Copyright (c) 1983 Regents of the University of California. 3*34360Sbostic * All rights reserved. 4*34360Sbostic * 5*34360Sbostic * Redistribution and use in source and binary forms are permitted 6*34360Sbostic * provided that this notice is preserved and that due credit is given 7*34360Sbostic * to the University of California at Berkeley. The name of the University 8*34360Sbostic * may not be used to endorse or promote products derived from this 9*34360Sbostic * software without specific prior written permission. This software 10*34360Sbostic * is provided ``as is'' without express or implied warranty. 1122387Sdist */ 1222387Sdist 1316362Skarels #ifndef lint 14*34360Sbostic static char sccsid[] = "@(#)announce.c 5.5 (Berkeley) 05/20/88"; 15*34360Sbostic #endif /* not lint */ 1616341Skarels 1726839Smckusick #include <sys/types.h> 1816341Skarels #include <sys/stat.h> 1916341Skarels #include <sgtty.h> 2016341Skarels #include <sys/ioctl.h> 2116341Skarels #include <sys/time.h> 2216341Skarels #include <stdio.h> 2316341Skarels #include <sys/wait.h> 2416341Skarels #include <errno.h> 2526839Smckusick #include <syslog.h> 2616341Skarels 2726839Smckusick #include <protocols/talkd.h> 2816341Skarels 2926839Smckusick extern int errno; 3026839Smckusick extern char hostname[]; 3116341Skarels 3216341Skarels /* 3326839Smckusick * Announce an invitation to talk. 3426839Smckusick * 3516341Skarels * Because the tty driver insists on attaching a terminal-less 3616341Skarels * process to any terminal that it writes on, we must fork a child 3716341Skarels * to protect ourselves 3816341Skarels */ 3916341Skarels announce(request, remote_machine) 4016362Skarels CTL_MSG *request; 4116362Skarels char *remote_machine; 4216341Skarels { 4316362Skarels int pid, val, status; 4416341Skarels 4516362Skarels if (pid = fork()) { 4616362Skarels /* we are the parent, so wait for the child */ 4716362Skarels if (pid == -1) /* the fork failed */ 4826839Smckusick return (FAILED); 4916362Skarels do { 5016362Skarels val = wait(&status); 5116362Skarels if (val == -1) { 5216362Skarels if (errno == EINTR) 5316362Skarels continue; 5416362Skarels /* shouldn't happen */ 5526839Smckusick syslog(LOG_WARNING, "announce: wait: %m"); 5616362Skarels return (FAILED); 5716362Skarels } 5816362Skarels } while (val != pid); 5916362Skarels if (status&0377 > 0) /* we were killed by some signal */ 6016362Skarels return (FAILED); 6116362Skarels /* Get the second byte, this is the exit/return code */ 6216362Skarels return ((status >> 8) & 0377); 6316341Skarels } 6416362Skarels /* we are the child, go and do it */ 6516341Skarels _exit(announce_proc(request, remote_machine)); 6616341Skarels } 6716341Skarels 6816362Skarels /* 6916362Skarels * See if the user is accepting messages. If so, announce that 7016362Skarels * a talk is requested. 7116362Skarels */ 7216341Skarels announce_proc(request, remote_machine) 7316362Skarels CTL_MSG *request; 7416362Skarels char *remote_machine; 7516341Skarels { 7616362Skarels int pid, status; 7716362Skarels char full_tty[32]; 7816362Skarels FILE *tf; 7916362Skarels struct stat stbuf; 8016341Skarels 8132465Sbostic (void)sprintf(full_tty, "/dev/%s", request->r_tty); 8216362Skarels if (access(full_tty, 0) != 0) 8316362Skarels return (FAILED); 8416362Skarels if ((tf = fopen(full_tty, "w")) == NULL) 8516362Skarels return (PERMISSION_DENIED); 8616362Skarels /* 8726839Smckusick * On first tty open, the server will have 8826839Smckusick * it's pgrp set, so disconnect us from the 8926839Smckusick * tty before we catch a signal. 9016362Skarels */ 9116362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 9216362Skarels if (fstat(fileno(tf), &stbuf) < 0) 9316362Skarels return (PERMISSION_DENIED); 9426854Smckusick if ((stbuf.st_mode&020) == 0) 9516362Skarels return (PERMISSION_DENIED); 9616362Skarels print_mesg(tf, request, remote_machine); 9716362Skarels fclose(tf); 9816362Skarels return (SUCCESS); 9916341Skarels } 10016341Skarels 10116341Skarels #define max(a,b) ( (a) > (b) ? (a) : (b) ) 10216341Skarels #define N_LINES 5 10316341Skarels #define N_CHARS 120 10416341Skarels 10516362Skarels /* 10616362Skarels * Build a block of characters containing the message. 10716362Skarels * It is sent blank filled and in a single block to 10816362Skarels * try to keep the message in one piece if the recipient 10916362Skarels * in in vi at the time 11016362Skarels */ 11116341Skarels print_mesg(tf, request, remote_machine) 11216362Skarels FILE *tf; 11316362Skarels CTL_MSG *request; 11416362Skarels char *remote_machine; 11516341Skarels { 11616362Skarels struct timeval clock; 11716362Skarels struct timezone zone; 11816362Skarels struct tm *localtime(); 11916362Skarels struct tm *localclock; 12016362Skarels char line_buf[N_LINES][N_CHARS]; 12116362Skarels int sizes[N_LINES]; 12216362Skarels char big_buf[N_LINES*N_CHARS]; 12316362Skarels char *bptr, *lptr; 12416362Skarels int i, j, max_size; 12516341Skarels 12616362Skarels i = 0; 12716362Skarels max_size = 0; 12816362Skarels gettimeofday(&clock, &zone); 12916362Skarels localclock = localtime( &clock.tv_sec ); 13032465Sbostic (void)sprintf(line_buf[i], " "); 13116362Skarels sizes[i] = strlen(line_buf[i]); 13216362Skarels max_size = max(max_size, sizes[i]); 13316362Skarels i++; 13432465Sbostic (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...", 13516341Skarels hostname, localclock->tm_hour , localclock->tm_min ); 13616362Skarels sizes[i] = strlen(line_buf[i]); 13716362Skarels max_size = max(max_size, sizes[i]); 13816362Skarels i++; 13932465Sbostic (void)sprintf(line_buf[i], "talk: connection requested by %s@%s.", 14016341Skarels request->l_name, remote_machine); 14116362Skarels sizes[i] = strlen(line_buf[i]); 14216362Skarels max_size = max(max_size, sizes[i]); 14316362Skarels i++; 14432465Sbostic (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s", 14516341Skarels request->l_name, remote_machine); 14616362Skarels sizes[i] = strlen(line_buf[i]); 14716362Skarels max_size = max(max_size, sizes[i]); 14816362Skarels i++; 14932465Sbostic (void)sprintf(line_buf[i], " "); 15016362Skarels sizes[i] = strlen(line_buf[i]); 15116362Skarels max_size = max(max_size, sizes[i]); 15216362Skarels i++; 15316362Skarels bptr = big_buf; 15426839Smckusick *bptr++ = ''; /* send something to wake them up */ 15526839Smckusick *bptr++ = '\r'; /* add a \r in case of raw mode */ 15626839Smckusick *bptr++ = '\n'; 15716362Skarels for (i = 0; i < N_LINES; i++) { 15816362Skarels /* copy the line into the big buffer */ 15916362Skarels lptr = line_buf[i]; 16016362Skarels while (*lptr != '\0') 16116362Skarels *(bptr++) = *(lptr++); 16216362Skarels /* pad out the rest of the lines with blanks */ 16316362Skarels for (j = sizes[i]; j < max_size + 2; j++) 16416362Skarels *(bptr++) = ' '; 16516362Skarels *(bptr++) = '\r'; /* add a \r in case of raw mode */ 16616362Skarels *(bptr++) = '\n'; 16716362Skarels } 16816362Skarels *bptr = '\0'; 16916362Skarels fprintf(tf, big_buf); 17016362Skarels fflush(tf); 17116362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 17216341Skarels } 173