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