122387Sdist /* 222387Sdist * Copyright (c) 1983 Regents of the University of California. 322387Sdist * All rights reserved. The Berkeley software License Agreement 422387Sdist * specifies the terms and conditions for redistribution. 522387Sdist */ 622387Sdist 716362Skarels #ifndef lint 8*26854Smckusick static char sccsid[] = "@(#)announce.c 5.3 (Berkeley) 03/13/86"; 922387Sdist #endif not lint 1016341Skarels 1126839Smckusick #include <sys/types.h> 1216341Skarels #include <sys/stat.h> 1316341Skarels #include <sgtty.h> 1416341Skarels #include <sys/ioctl.h> 1516341Skarels #include <sys/time.h> 1616341Skarels #include <stdio.h> 1716341Skarels #include <sys/wait.h> 1816341Skarels #include <errno.h> 1926839Smckusick #include <syslog.h> 2016341Skarels 2126839Smckusick #include <protocols/talkd.h> 2216341Skarels 2326839Smckusick extern int errno; 2426839Smckusick extern char hostname[]; 2516341Skarels 2616341Skarels /* 2726839Smckusick * Announce an invitation to talk. 2826839Smckusick * 2916341Skarels * Because the tty driver insists on attaching a terminal-less 3016341Skarels * process to any terminal that it writes on, we must fork a child 3116341Skarels * to protect ourselves 3216341Skarels */ 3316341Skarels announce(request, remote_machine) 3416362Skarels CTL_MSG *request; 3516362Skarels char *remote_machine; 3616341Skarels { 3716362Skarels int pid, val, status; 3816341Skarels 3916362Skarels if (pid = fork()) { 4016362Skarels /* we are the parent, so wait for the child */ 4116362Skarels if (pid == -1) /* the fork failed */ 4226839Smckusick return (FAILED); 4316362Skarels do { 4416362Skarels val = wait(&status); 4516362Skarels if (val == -1) { 4616362Skarels if (errno == EINTR) 4716362Skarels continue; 4816362Skarels /* shouldn't happen */ 4926839Smckusick syslog(LOG_WARNING, "announce: wait: %m"); 5016362Skarels return (FAILED); 5116362Skarels } 5216362Skarels } while (val != pid); 5316362Skarels if (status&0377 > 0) /* we were killed by some signal */ 5416362Skarels return (FAILED); 5516362Skarels /* Get the second byte, this is the exit/return code */ 5616362Skarels return ((status >> 8) & 0377); 5716341Skarels } 5816362Skarels /* we are the child, go and do it */ 5916341Skarels _exit(announce_proc(request, remote_machine)); 6016341Skarels } 6116341Skarels 6216362Skarels /* 6316362Skarels * See if the user is accepting messages. If so, announce that 6416362Skarels * a talk is requested. 6516362Skarels */ 6616341Skarels announce_proc(request, remote_machine) 6716362Skarels CTL_MSG *request; 6816362Skarels char *remote_machine; 6916341Skarels { 7016362Skarels int pid, status; 7116362Skarels char full_tty[32]; 7216362Skarels FILE *tf; 7316362Skarels struct stat stbuf; 7416341Skarels 7526839Smckusick sprintf(full_tty, "/dev/%s", request->r_tty); 7616362Skarels if (access(full_tty, 0) != 0) 7716362Skarels return (FAILED); 7816362Skarels if ((tf = fopen(full_tty, "w")) == NULL) 7916362Skarels return (PERMISSION_DENIED); 8016362Skarels /* 8126839Smckusick * On first tty open, the server will have 8226839Smckusick * it's pgrp set, so disconnect us from the 8326839Smckusick * tty before we catch a signal. 8416362Skarels */ 8516362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 8616362Skarels if (fstat(fileno(tf), &stbuf) < 0) 8716362Skarels return (PERMISSION_DENIED); 88*26854Smckusick if ((stbuf.st_mode&020) == 0) 8916362Skarels return (PERMISSION_DENIED); 9016362Skarels print_mesg(tf, request, remote_machine); 9116362Skarels fclose(tf); 9216362Skarels return (SUCCESS); 9316341Skarels } 9416341Skarels 9516341Skarels #define max(a,b) ( (a) > (b) ? (a) : (b) ) 9616341Skarels #define N_LINES 5 9716341Skarels #define N_CHARS 120 9816341Skarels 9916362Skarels /* 10016362Skarels * Build a block of characters containing the message. 10116362Skarels * It is sent blank filled and in a single block to 10216362Skarels * try to keep the message in one piece if the recipient 10316362Skarels * in in vi at the time 10416362Skarels */ 10516341Skarels print_mesg(tf, request, remote_machine) 10616362Skarels FILE *tf; 10716362Skarels CTL_MSG *request; 10816362Skarels char *remote_machine; 10916341Skarels { 11016362Skarels struct timeval clock; 11116362Skarels struct timezone zone; 11216362Skarels struct tm *localtime(); 11316362Skarels struct tm *localclock; 11416362Skarels char line_buf[N_LINES][N_CHARS]; 11516362Skarels int sizes[N_LINES]; 11616362Skarels char big_buf[N_LINES*N_CHARS]; 11716362Skarels char *bptr, *lptr; 11816362Skarels int i, j, max_size; 11916341Skarels 12016362Skarels i = 0; 12116362Skarels max_size = 0; 12216362Skarels gettimeofday(&clock, &zone); 12316362Skarels localclock = localtime( &clock.tv_sec ); 12416362Skarels sprintf(line_buf[i], " "); 12516362Skarels sizes[i] = strlen(line_buf[i]); 12616362Skarels max_size = max(max_size, sizes[i]); 12716362Skarels i++; 12816362Skarels sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...", 12916341Skarels hostname, localclock->tm_hour , localclock->tm_min ); 13016362Skarels sizes[i] = strlen(line_buf[i]); 13116362Skarels max_size = max(max_size, sizes[i]); 13216362Skarels i++; 13316362Skarels sprintf(line_buf[i], "talk: connection requested by %s@%s.", 13416341Skarels request->l_name, remote_machine); 13516362Skarels sizes[i] = strlen(line_buf[i]); 13616362Skarels max_size = max(max_size, sizes[i]); 13716362Skarels i++; 13816362Skarels sprintf(line_buf[i], "talk: respond with: talk %s@%s", 13916341Skarels request->l_name, remote_machine); 14016362Skarels sizes[i] = strlen(line_buf[i]); 14116362Skarels max_size = max(max_size, sizes[i]); 14216362Skarels i++; 14316362Skarels sprintf(line_buf[i], " "); 14416362Skarels sizes[i] = strlen(line_buf[i]); 14516362Skarels max_size = max(max_size, sizes[i]); 14616362Skarels i++; 14716362Skarels bptr = big_buf; 14826839Smckusick *bptr++ = ''; /* send something to wake them up */ 14926839Smckusick *bptr++ = '\r'; /* add a \r in case of raw mode */ 15026839Smckusick *bptr++ = '\n'; 15116362Skarels for (i = 0; i < N_LINES; i++) { 15216362Skarels /* copy the line into the big buffer */ 15316362Skarels lptr = line_buf[i]; 15416362Skarels while (*lptr != '\0') 15516362Skarels *(bptr++) = *(lptr++); 15616362Skarels /* pad out the rest of the lines with blanks */ 15716362Skarels for (j = sizes[i]; j < max_size + 2; j++) 15816362Skarels *(bptr++) = ' '; 15916362Skarels *(bptr++) = '\r'; /* add a \r in case of raw mode */ 16016362Skarels *(bptr++) = '\n'; 16116362Skarels } 16216362Skarels *bptr = '\0'; 16316362Skarels fprintf(tf, big_buf); 16416362Skarels fflush(tf); 16516362Skarels ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 16616341Skarels } 167