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