Path: utzoo!utgpu!jarvis.csri.toronto.edu!rutgers!ucsd!tut.cis.ohio-state.edu!bloom-beacon!math.mit.edu!drw From: drw@schubert.math.mit.edu (Dale R. Worley) Newsgroups: alt.sources Subject: Duplicate output to multiple terminals Message-ID: Date: 14 Nov 89 03:53:23 GMT Sender: daemon@bloom-beacon.MIT.EDU Distribution: alt.sources Organization: MIT Dept. of Mathematics, Cambridge, MA, USA Lines: 306 Here's a program I use that uses interprocessor communications. It seems to work fine. It was hacked up from the Emacs client/server code. To run the master program, do: program | broadcast Then just: receiver to run a slave. broadcast and receiver have to be run in the same account. These could be hacked up to use Internet IPC, etc. to make them more useful, but they do what I needed done. Dale ---------------------------------------- broadcast.c /* Broadcast stdin to everybody who wants to listen */ /* Communication subprocess for GNU Emacs acting as server. Copyright (C) 1986, 1987 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is distributed in the hope that it will be useful, but without any warranty. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Everyone is granted permission to copy, modify and redistribute GNU Emacs, but only under the conditions described in the document "GNU Emacs copying permission notice". An exact copy of the document is supposed to have been given to you along with GNU Emacs so that you can know how you may redistribute it all. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* The GNU Emacs edit server process is run as a subprocess of Emacs under control of the file lisp/server.el. This program accepts communication from client (program emacsclient.c) and passes their commands (consisting of keyboard characters) up to the Emacs which then executes them. */ /* This code is BSD only. */ #include #include #include #include #include #include #include #include extern int errno; main () { int s, infd, fromlen; struct sockaddr_un server, fromunix; char *homedir; char *str, string[BUFSIZ], code[BUFSIZ]; FILE *infile; FILE **openfiles; int openfiles_size; int i; char *getenv (); openfiles_size = 20; openfiles = (FILE **) malloc (openfiles_size * sizeof (FILE *)); if (openfiles == 0) abort (); for (i = 0; i < openfiles_size; i++) openfiles[i] == NULL; /* * Open up an AF_UNIX socket in this person's home directory */ if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { perror ("socket"); exit (1); } server.sun_family = AF_UNIX; if ((homedir = getenv ("HOME")) == NULL) { fprintf (stderr,"No home directory\n"); exit (1); } strcpy (server.sun_path, homedir); strcat (server.sun_path, "/.broadcast"); unlink(server.sun_path); if (bind (s, &server, strlen (server.sun_path) + 2) < 0) { perror ("bind"); exit (1); } /* * Now, just wait for everything to come in.. */ if (listen (s, 5) < 0) { perror ("listen"); exit (1); } fprintf(stderr, "[Waiting for clients.]\n"); /* Disable sigpipes in case luser kills client... */ signal (SIGPIPE, SIG_IGN); /* Make stdin non-blocking */ fcntl(stdin->_file, F_SETFL, FNDELAY); for (;;) { int rmask = (1 << s) + 1; /* wait for input from new client or stdin */ if (select (s + 1, &rmask, 0, 0, 0) < 0) perror ("select"); if (rmask & (1 << s)) /* client sends list of filenames */ { /* new client calling */ fromlen = sizeof (fromunix); fromunix.sun_family = AF_UNIX; infd = accept (s, &fromunix, &fromlen); /* open socket fd */ if (infd < 0) { if (errno == EMFILE || errno == ENFILE) fprintf (stderr, "Too many clients.\n"); else perror ("accept"); continue; } while (infd >= openfiles_size) { int i; openfiles_size *= 2; openfiles = (FILE **) realloc (openfiles, openfiles_size * sizeof (FILE *)); if (openfiles == 0) abort (); for (i = openfiles_size/2; i < openfiles_size; i++) openfiles[i] == NULL; } infile = fdopen (infd, "r+"); /* open stream */ if (infile == NULL) { fprintf (stderr, "Too many clients.\n"); write (infd, "Too many clients.\n", 18); close (infd); /* Prevent descriptor leak.. */ continue; } openfiles[infd] = infile; fprintf (stderr, "[Client: %d]\n", infd); fflush (stderr); continue; } else if (rmask & 1) { /* text from stdin -- broadcast it to all clients */ /* Read from stdin and copy to the streams until we get 'wouldblock' * or EOF. */ while (1) { int c; int i; int retcode; #define BUFSIZE 100 char buffer[BUFSIZE]; /* Read some input. */ errno = 0; retcode = read(stdin->_file, buffer, BUFSIZE); /* Handle errors and EOF. */ if (retcode == -1 || retcode == 0) { if (errno == EWOULDBLOCK) /* wouldblock -- go back to waiting */ break; else { /* EOF on input -- exit */ fprintf(stderr, "[Exiting]\n"); exit(0); } } /* Write characters to all open streams */ for (i = 0; i < openfiles_size; i++) { if (openfiles[i] != NULL) write (openfiles[i]->_file, buffer, retcode); } /* Copy to stdout */ write (stdout->_file, buffer, retcode); } continue; } } } ---------------------------------------- receiver.c /* Client process that communicates with GNU Emacs acting as server. Copyright (C) 1986, 1987 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is distributed in the hope that it will be useful, but without any warranty. No author or distributor accepts responsibility to anyone for the consequences of using it or for whether it serves any particular purpose or works at all, unless he says so in writing. Everyone is granted permission to copy, modify and redistribute GNU Emacs, but only under the conditions described in the document "GNU Emacs copying permission notice". An exact copy of the document is supposed to have been given to you along with GNU Emacs so that you can know how you may redistribute it all. It should be in a file named COPYING. Among other things, the copyright notice and this notice must be preserved on all copies. */ /* This code is BSD only. */ #include #include #include #include main (argc, argv) int argc; char **argv; { int s, n, i; FILE *out; struct sockaddr_un server; char *homedir, *cwd, *str; char string[BUFSIZ]; int c; char *getenv (), *getwd (); /* * Open up an AF_UNIX socket in this person's home directory */ if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) < 0) { perror ("socket"); exit (1); } server.sun_family = AF_UNIX; if ((homedir = getenv ("HOME")) == NULL) { fprintf (stderr, "No home directory\n"); exit (1); } strcpy (server.sun_path, homedir); strcat (server.sun_path, "/.broadcast"); if (connect (s, &server, strlen (server.sun_path) + 2) < 0) { perror ("connect"); exit (1); } if ((out = fdopen (s, "r+")) == NULL) { perror ("fdopen"); exit (1); } cwd = getwd (string); if (cwd == 0) abort (); fprintf(stderr, "[Connected.]\n"); setbuf(stdout, NULL); while (1) { int retcode; #define BUFSIZE 100 char buffer[BUFSIZE]; /* Read some input. */ retcode = read(s, buffer, BUFSIZE); /* Handle errors and EOF. */ if (retcode == -1 || retcode == 0) break; /* Copy to stdout */ write (stdout->_file, buffer, retcode); } printf("\n[Disconnected]\n"); }