1*37405Sbostic /* 2*37405Sbostic * Copyright (c) 1983 Regents of the University of California. 3*37405Sbostic * All rights reserved. The Berkeley software License Agreement 4*37405Sbostic * specifies the terms and conditions for redistribution. 5*37405Sbostic */ 6*37405Sbostic 7*37405Sbostic #ifndef lint 8*37405Sbostic static char sccsid[] = "@(#)announce.c 5.1 (Berkeley) 6/6/85"; 9*37405Sbostic #endif not lint 10*37405Sbostic 11*37405Sbostic #include "ctl.h" 12*37405Sbostic 13*37405Sbostic #include <sys/stat.h> 14*37405Sbostic #include <sgtty.h> 15*37405Sbostic #include <sys/ioctl.h> 16*37405Sbostic #include <sys/time.h> 17*37405Sbostic #include <stdio.h> 18*37405Sbostic #include <sys/wait.h> 19*37405Sbostic #include <errno.h> 20*37405Sbostic 21*37405Sbostic char *sprintf(); 22*37405Sbostic 23*37405Sbostic extern int errno; 24*37405Sbostic extern char hostname[]; 25*37405Sbostic int nofork = 0; /* to be set from the debugger */ 26*37405Sbostic 27*37405Sbostic /* 28*37405Sbostic * Because the tty driver insists on attaching a terminal-less 29*37405Sbostic * process to any terminal that it writes on, we must fork a child 30*37405Sbostic * to protect ourselves 31*37405Sbostic */ 32*37405Sbostic 33*37405Sbostic announce(request, remote_machine) 34*37405Sbostic CTL_MSG *request; 35*37405Sbostic char *remote_machine; 36*37405Sbostic { 37*37405Sbostic int pid, val, status; 38*37405Sbostic 39*37405Sbostic if (nofork) 40*37405Sbostic return(announce_proc(request, remote_machine)); 41*37405Sbostic if (pid = fork()) { 42*37405Sbostic /* we are the parent, so wait for the child */ 43*37405Sbostic if (pid == -1) /* the fork failed */ 44*37405Sbostic return(FAILED); 45*37405Sbostic do { 46*37405Sbostic val = wait(&status); 47*37405Sbostic if (val == -1) { 48*37405Sbostic if (errno == EINTR) 49*37405Sbostic continue; 50*37405Sbostic /* shouldn't happen */ 51*37405Sbostic perror("wait"); 52*37405Sbostic return (FAILED); 53*37405Sbostic } 54*37405Sbostic } while (val != pid); 55*37405Sbostic if (status&0377 > 0) /* we were killed by some signal */ 56*37405Sbostic return (FAILED); 57*37405Sbostic /* Get the second byte, this is the exit/return code */ 58*37405Sbostic return ((status >> 8) & 0377); 59*37405Sbostic } 60*37405Sbostic /* we are the child, go and do it */ 61*37405Sbostic _exit(announce_proc(request, remote_machine)); 62*37405Sbostic } 63*37405Sbostic 64*37405Sbostic /* 65*37405Sbostic * See if the user is accepting messages. If so, announce that 66*37405Sbostic * a talk is requested. 67*37405Sbostic */ 68*37405Sbostic announce_proc(request, remote_machine) 69*37405Sbostic CTL_MSG *request; 70*37405Sbostic char *remote_machine; 71*37405Sbostic { 72*37405Sbostic int pid, status; 73*37405Sbostic char full_tty[32]; 74*37405Sbostic FILE *tf; 75*37405Sbostic struct stat stbuf; 76*37405Sbostic 77*37405Sbostic (void) sprintf(full_tty, "/dev/%s", request->r_tty); 78*37405Sbostic if (access(full_tty, 0) != 0) 79*37405Sbostic return (FAILED); 80*37405Sbostic if ((tf = fopen(full_tty, "w")) == NULL) 81*37405Sbostic return (PERMISSION_DENIED); 82*37405Sbostic /* 83*37405Sbostic * Open gratuitously attaches the talkd to 84*37405Sbostic * any tty it opens, so disconnect us from the 85*37405Sbostic * tty before we catch a signal 86*37405Sbostic */ 87*37405Sbostic ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 88*37405Sbostic if (fstat(fileno(tf), &stbuf) < 0) 89*37405Sbostic return (PERMISSION_DENIED); 90*37405Sbostic if ((stbuf.st_mode&020) == 0) 91*37405Sbostic return (PERMISSION_DENIED); 92*37405Sbostic print_mesg(tf, request, remote_machine); 93*37405Sbostic fclose(tf); 94*37405Sbostic return (SUCCESS); 95*37405Sbostic } 96*37405Sbostic 97*37405Sbostic #define max(a,b) ( (a) > (b) ? (a) : (b) ) 98*37405Sbostic #define N_LINES 5 99*37405Sbostic #define N_CHARS 120 100*37405Sbostic 101*37405Sbostic /* 102*37405Sbostic * Build a block of characters containing the message. 103*37405Sbostic * It is sent blank filled and in a single block to 104*37405Sbostic * try to keep the message in one piece if the recipient 105*37405Sbostic * in in vi at the time 106*37405Sbostic */ 107*37405Sbostic print_mesg(tf, request, remote_machine) 108*37405Sbostic FILE *tf; 109*37405Sbostic CTL_MSG *request; 110*37405Sbostic char *remote_machine; 111*37405Sbostic { 112*37405Sbostic struct timeval clock; 113*37405Sbostic struct timezone zone; 114*37405Sbostic struct tm *localtime(); 115*37405Sbostic struct tm *localclock; 116*37405Sbostic char line_buf[N_LINES][N_CHARS]; 117*37405Sbostic int sizes[N_LINES]; 118*37405Sbostic char big_buf[N_LINES*N_CHARS]; 119*37405Sbostic char *bptr, *lptr; 120*37405Sbostic int i, j, max_size; 121*37405Sbostic 122*37405Sbostic i = 0; 123*37405Sbostic max_size = 0; 124*37405Sbostic gettimeofday(&clock, &zone); 125*37405Sbostic localclock = localtime( &clock.tv_sec ); 126*37405Sbostic sprintf(line_buf[i], " "); 127*37405Sbostic sizes[i] = strlen(line_buf[i]); 128*37405Sbostic max_size = max(max_size, sizes[i]); 129*37405Sbostic i++; 130*37405Sbostic sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...", 131*37405Sbostic hostname, localclock->tm_hour , localclock->tm_min ); 132*37405Sbostic sizes[i] = strlen(line_buf[i]); 133*37405Sbostic max_size = max(max_size, sizes[i]); 134*37405Sbostic i++; 135*37405Sbostic sprintf(line_buf[i], "talk: connection requested by %s@%s.", 136*37405Sbostic request->l_name, remote_machine); 137*37405Sbostic sizes[i] = strlen(line_buf[i]); 138*37405Sbostic max_size = max(max_size, sizes[i]); 139*37405Sbostic i++; 140*37405Sbostic sprintf(line_buf[i], "talk: respond with: /usr/old/talk %s@%s", 141*37405Sbostic request->l_name, remote_machine); 142*37405Sbostic sizes[i] = strlen(line_buf[i]); 143*37405Sbostic max_size = max(max_size, sizes[i]); 144*37405Sbostic i++; 145*37405Sbostic sprintf(line_buf[i], " "); 146*37405Sbostic sizes[i] = strlen(line_buf[i]); 147*37405Sbostic max_size = max(max_size, sizes[i]); 148*37405Sbostic i++; 149*37405Sbostic bptr = big_buf; 150*37405Sbostic *(bptr++) = ''; /* send something to wake them up */ 151*37405Sbostic *(bptr++) = '\r'; /* add a \r in case of raw mode */ 152*37405Sbostic *(bptr++) = '\n'; 153*37405Sbostic for (i = 0; i < N_LINES; i++) { 154*37405Sbostic /* copy the line into the big buffer */ 155*37405Sbostic lptr = line_buf[i]; 156*37405Sbostic while (*lptr != '\0') 157*37405Sbostic *(bptr++) = *(lptr++); 158*37405Sbostic /* pad out the rest of the lines with blanks */ 159*37405Sbostic for (j = sizes[i]; j < max_size + 2; j++) 160*37405Sbostic *(bptr++) = ' '; 161*37405Sbostic *(bptr++) = '\r'; /* add a \r in case of raw mode */ 162*37405Sbostic *(bptr++) = '\n'; 163*37405Sbostic } 164*37405Sbostic *bptr = '\0'; 165*37405Sbostic fprintf(tf, big_buf); 166*37405Sbostic fflush(tf); 167*37405Sbostic ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 168*37405Sbostic } 169