1*66683Sbostic /*-
2*66683Sbostic * Copyright (c) 1983, 1985
3*66683Sbostic * The Regents of the University of California. All rights reserved.
4*66683Sbostic *
5*66683Sbostic * %sccs.include.redist.c%
637405Sbostic */
737405Sbostic
837405Sbostic #ifndef lint
937405Sbostic static char sccsid[] = "@(#)announce.c 5.1 (Berkeley) 6/6/85";
1037405Sbostic #endif not lint
1137405Sbostic
1237405Sbostic #include "ctl.h"
1337405Sbostic
1437405Sbostic #include <sys/stat.h>
1537405Sbostic #include <sgtty.h>
1637405Sbostic #include <sys/ioctl.h>
1737405Sbostic #include <sys/time.h>
1837405Sbostic #include <stdio.h>
1937405Sbostic #include <sys/wait.h>
2037405Sbostic #include <errno.h>
2137405Sbostic
2237405Sbostic extern int errno;
2337405Sbostic extern char hostname[];
2437405Sbostic int nofork = 0; /* to be set from the debugger */
2537405Sbostic
2637405Sbostic /*
2737405Sbostic * Because the tty driver insists on attaching a terminal-less
2837405Sbostic * process to any terminal that it writes on, we must fork a child
2937405Sbostic * to protect ourselves
3037405Sbostic */
3137405Sbostic
announce(request,remote_machine)3237405Sbostic announce(request, remote_machine)
3337405Sbostic CTL_MSG *request;
3437405Sbostic char *remote_machine;
3537405Sbostic {
3637405Sbostic int pid, val, status;
3737405Sbostic
3837405Sbostic if (nofork)
3937405Sbostic return(announce_proc(request, remote_machine));
4037405Sbostic if (pid = fork()) {
4137405Sbostic /* we are the parent, so wait for the child */
4237405Sbostic if (pid == -1) /* the fork failed */
4337405Sbostic return(FAILED);
4437405Sbostic do {
4537405Sbostic val = wait(&status);
4637405Sbostic if (val == -1) {
4737405Sbostic if (errno == EINTR)
4837405Sbostic continue;
4937405Sbostic /* shouldn't happen */
5037405Sbostic perror("wait");
5137405Sbostic return (FAILED);
5237405Sbostic }
5337405Sbostic } while (val != pid);
5437405Sbostic if (status&0377 > 0) /* we were killed by some signal */
5537405Sbostic return (FAILED);
5637405Sbostic /* Get the second byte, this is the exit/return code */
5737405Sbostic return ((status >> 8) & 0377);
5837405Sbostic }
5937405Sbostic /* we are the child, go and do it */
6037405Sbostic _exit(announce_proc(request, remote_machine));
6137405Sbostic }
6237405Sbostic
6337405Sbostic /*
6437405Sbostic * See if the user is accepting messages. If so, announce that
6537405Sbostic * a talk is requested.
6637405Sbostic */
announce_proc(request,remote_machine)6737405Sbostic announce_proc(request, remote_machine)
6837405Sbostic CTL_MSG *request;
6937405Sbostic char *remote_machine;
7037405Sbostic {
7137405Sbostic int pid, status;
7237405Sbostic char full_tty[32];
7337405Sbostic FILE *tf;
7437405Sbostic struct stat stbuf;
7537405Sbostic
7637405Sbostic (void) sprintf(full_tty, "/dev/%s", request->r_tty);
7737405Sbostic if (access(full_tty, 0) != 0)
7837405Sbostic return (FAILED);
7937405Sbostic if ((tf = fopen(full_tty, "w")) == NULL)
8037405Sbostic return (PERMISSION_DENIED);
8137405Sbostic /*
8237405Sbostic * Open gratuitously attaches the talkd to
8337405Sbostic * any tty it opens, so disconnect us from the
8437405Sbostic * tty before we catch a signal
8537405Sbostic */
8637405Sbostic ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
8737405Sbostic if (fstat(fileno(tf), &stbuf) < 0)
8837405Sbostic return (PERMISSION_DENIED);
8937405Sbostic if ((stbuf.st_mode&020) == 0)
9037405Sbostic return (PERMISSION_DENIED);
9137405Sbostic print_mesg(tf, request, remote_machine);
9237405Sbostic fclose(tf);
9337405Sbostic return (SUCCESS);
9437405Sbostic }
9537405Sbostic
9637405Sbostic #define max(a,b) ( (a) > (b) ? (a) : (b) )
9737405Sbostic #define N_LINES 5
9837405Sbostic #define N_CHARS 120
9937405Sbostic
10037405Sbostic /*
10137405Sbostic * Build a block of characters containing the message.
10237405Sbostic * It is sent blank filled and in a single block to
10337405Sbostic * try to keep the message in one piece if the recipient
10437405Sbostic * in in vi at the time
10537405Sbostic */
print_mesg(tf,request,remote_machine)10637405Sbostic print_mesg(tf, request, remote_machine)
10737405Sbostic FILE *tf;
10837405Sbostic CTL_MSG *request;
10937405Sbostic char *remote_machine;
11037405Sbostic {
11137405Sbostic struct timeval clock;
11237405Sbostic struct timezone zone;
11337405Sbostic struct tm *localtime();
11437405Sbostic struct tm *localclock;
11537405Sbostic char line_buf[N_LINES][N_CHARS];
11637405Sbostic int sizes[N_LINES];
11737405Sbostic char big_buf[N_LINES*N_CHARS];
11837405Sbostic char *bptr, *lptr;
11937405Sbostic int i, j, max_size;
12037405Sbostic
12137405Sbostic i = 0;
12237405Sbostic max_size = 0;
12337405Sbostic gettimeofday(&clock, &zone);
12437405Sbostic localclock = localtime( &clock.tv_sec );
12537405Sbostic sprintf(line_buf[i], " ");
12637405Sbostic sizes[i] = strlen(line_buf[i]);
12737405Sbostic max_size = max(max_size, sizes[i]);
12837405Sbostic i++;
12937405Sbostic sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
13037405Sbostic hostname, localclock->tm_hour , localclock->tm_min );
13137405Sbostic sizes[i] = strlen(line_buf[i]);
13237405Sbostic max_size = max(max_size, sizes[i]);
13337405Sbostic i++;
13437405Sbostic sprintf(line_buf[i], "talk: connection requested by %s@%s.",
13537405Sbostic request->l_name, remote_machine);
13637405Sbostic sizes[i] = strlen(line_buf[i]);
13737405Sbostic max_size = max(max_size, sizes[i]);
13837405Sbostic i++;
13937405Sbostic sprintf(line_buf[i], "talk: respond with: /usr/old/talk %s@%s",
14037405Sbostic request->l_name, remote_machine);
14137405Sbostic sizes[i] = strlen(line_buf[i]);
14237405Sbostic max_size = max(max_size, sizes[i]);
14337405Sbostic i++;
14437405Sbostic sprintf(line_buf[i], " ");
14537405Sbostic sizes[i] = strlen(line_buf[i]);
14637405Sbostic max_size = max(max_size, sizes[i]);
14737405Sbostic i++;
14837405Sbostic bptr = big_buf;
14937405Sbostic *(bptr++) = ''; /* send something to wake them up */
15037405Sbostic *(bptr++) = '\r'; /* add a \r in case of raw mode */
15137405Sbostic *(bptr++) = '\n';
15237405Sbostic for (i = 0; i < N_LINES; i++) {
15337405Sbostic /* copy the line into the big buffer */
15437405Sbostic lptr = line_buf[i];
15537405Sbostic while (*lptr != '\0')
15637405Sbostic *(bptr++) = *(lptr++);
15737405Sbostic /* pad out the rest of the lines with blanks */
15837405Sbostic for (j = sizes[i]; j < max_size + 2; j++)
15937405Sbostic *(bptr++) = ' ';
16037405Sbostic *(bptr++) = '\r'; /* add a \r in case of raw mode */
16137405Sbostic *(bptr++) = '\n';
16237405Sbostic }
16337405Sbostic *bptr = '\0';
16437405Sbostic fprintf(tf, big_buf);
16537405Sbostic fflush(tf);
16637405Sbostic ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
16737405Sbostic }
168