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.4 (Berkeley) 10/22/87"; 9 #endif not lint 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 (void)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 (void)sprintf(line_buf[i], " "); 125 sizes[i] = strlen(line_buf[i]); 126 max_size = max(max_size, sizes[i]); 127 i++; 128 (void)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 (void)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 (void)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 (void)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 fprintf(tf, big_buf); 164 fflush(tf); 165 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0); 166 } 167