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