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