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