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