1*22387Sdist /* 2*22387Sdist * Copyright (c) 1983 Regents of the University of California. 3*22387Sdist * All rights reserved. The Berkeley software License Agreement 4*22387Sdist * specifies the terms and conditions for redistribution. 5*22387Sdist */ 6*22387Sdist 716362Skarels #ifndef lint 8*22387Sdist static char sccsid[] = "@(#)announce.c 5.1 (Berkeley) 06/06/85"; 9*22387Sdist #endif not lint 1016341Skarels 1116341Skarels #include "ctl.h" 1216341Skarels 1316341Skarels #include <sys/stat.h> 1416341Skarels #include <sgtty.h> 1516341Skarels #include <sys/ioctl.h> 1616341Skarels #include <sys/time.h> 1716341Skarels #include <stdio.h> 1816341Skarels #include <sys/wait.h> 1916341Skarels #include <errno.h> 2016341Skarels 2116341Skarels char *sprintf(); 2216341Skarels 2316341Skarels extern int errno; 2416341Skarels extern char hostname[]; 2516341Skarels int nofork = 0; /* to be set from the debugger */ 2616341Skarels 2716341Skarels /* 2816341Skarels * Because the tty driver insists on attaching a terminal-less 2916341Skarels * process to any terminal that it writes on, we must fork a child 3016341Skarels * to protect ourselves 3116341Skarels */ 3216341Skarels 3316341Skarels announce(request, remote_machine) 3416362Skarels CTL_MSG *request; 3516362Skarels char *remote_machine; 3616341Skarels { 3716362Skarels int pid, val, status; 3816341Skarels 3916362Skarels if (nofork) 4016362Skarels return(announce_proc(request, remote_machine)); 4116362Skarels if (pid = fork()) { 4216362Skarels /* we are the parent, so wait for the child */ 4316362Skarels if (pid == -1) /* the fork failed */ 4416362Skarels return(FAILED); 4516362Skarels do { 4616362Skarels val = wait(&status); 4716362Skarels if (val == -1) { 4816362Skarels if (errno == EINTR) 4916362Skarels continue; 5016362Skarels /* shouldn't happen */ 5116362Skarels perror("wait"); 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 7716362Skarels (void) sprintf(full_tty, "/dev/%s", 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 /* 8316362Skarels * Open gratuitously attaches the talkd to 8416362Skarels * any tty it opens, so disconnect us from the 8516362Skarels * 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); 9016362Skarels if ((stbuf.st_mode&02) == 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 ); 12616362Skarels sprintf(line_buf[i], " "); 12716362Skarels sizes[i] = strlen(line_buf[i]); 12816362Skarels max_size = max(max_size, sizes[i]); 12916362Skarels i++; 13016362Skarels 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++; 13516362Skarels 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++; 14016362Skarels 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++; 14516362Skarels 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; 15016362Skarels *(bptr++) = ''; /* send something to wake them up */ 15116341Skarels *(bptr++) = '\r'; /* add a \r in case of raw mode */ 15216341Skarels *(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