home *** CD-ROM | disk | FTP | other *** search
- Path: sparky!uunet!stanford.edu!agate!dog.ee.lbl.gov!network.ucsd.edu!mvb.saic.com!vmsnet-sources
- Newsgroups: vmsnet.sources
- From: gerland@ubvmsb.cc.buffalo.edu (Jim Gerland)
- Subject: ISEND for VMS, part 01/01
- Date: Fri, 04 Sep 1992 06:12:44 GMT
- Message-ID: <8045724@MVB.SAIC.COM>
- Keywords: ISEND TALK MSP
- Reply-To: gerland@ubvmsb.cc.buffalo.edu
- Organization: University at Buffalo
- Lines: 1185
- Approved: Mark.Berryman@Mvb.Saic.Com
-
- Submitted-by: gerland@ubvmsb.cc.buffalo.edu (Jim Gerland)
- Posting-number: Volume 3, Issue 163
- Archive-name: isend/part01
-
- [ This submission is an implementation of the messaging
- protocol described in RFC 1312 (an earlier version of
- this protocol is described in RFC 1159). This protocol
- provides a means of sending messages to a remote user's
- terminal using UDP datagrams. ]
-
- $! ------------------ CUT HERE -----------------------
- $ v='f$verify(f$trnlnm("SHARE_VERIFY"))'
- $!
- $! This archive created by VMS_SHARE Version 7.2-007 22-FEB-1990
- $! On 12-AUG-1992 08:34:25.46 By user GERLAND (Jim Gerland - University at Buffalo)
- $!
- $! This VMS_SHARE Written by:
- $! Andy Harper, Kings College London UK
- $!
- $! Acknowledgements to:
- $! James Gray - Original VMS_SHARE
- $! Michael Bednarek - Original Concept and implementation
- $!
- $! TO UNPACK THIS SHARE FILE, CONCATENATE ALL PARTS IN ORDER
- $! AND EXECUTE AS A COMMAND PROCEDURE ( @name )
- $!
- $! THE FOLLOWING FILE(S) WILL BE CREATED AFTER UNPACKING:
- $! 1. AAAREADME.TXT;12
- $! 2. COMPILE.;2
- $! 3. COMPILE.COM;6
- $! 4. ISEND.C;41
- $! 5. ISEND.HLP;1
- $! 6. ISEND.OPT;2
- $! 7. ISEND.RNH;5
- $! 8. ISENDD.C;48
- $! 9. MAKEFILE.;5
- $! 10. MULTINET.OPT;2
- $! 11. START-ISEND-SERVER.COM;3
- $! 12. UNIX_BRDCST.C;3
- $! 13. VMS_BROADCAST.C;7
- $! 14. WIN.OPT;3
- $!
- $set="set"
- $set symbol/scope=(nolocal,noglobal)
- $f=f$parse("SHARE_TEMP","SYS$SCRATCH:.TMP_"+f$getjpi("","PID"))
- $e="write sys$error ""%UNPACK"", "
- $w="write sys$output ""%UNPACK"", "
- $ if f$trnlnm("SHARE_LOG") then $ w = "!"
- $ ve=f$getsyi("version")
- $ if ve-f$extract(0,1,ve) .ges. "4.4" then $ goto START
- $ e "-E-OLDVER, Must run at least VMS 4.4"
- $ v=f$verify(v)
- $ exit 44
- $UNPACK: SUBROUTINE ! P1=filename, P2=checksum
- $ if f$search(P1) .eqs. "" then $ goto file_absent
- $ e "-W-EXISTS, File ''P1' exists. Skipped."
- $ delete 'f'*
- $ exit
- $file_absent:
- $ if f$parse(P1) .nes. "" then $ goto dirok
- $ dn=f$parse(P1,,,"DIRECTORY")
- $ w "-I-CREDIR, Creating directory ''dn'."
- $ create/dir 'dn'
- $ if $status then $ goto dirok
- $ e "-E-CREDIRFAIL, Unable to create ''dn'. File skipped."
- $ delete 'f'*
- $ exit
- $dirok:
- $ w "-I-PROCESS, Processing file ''P1'."
- $ if .not. f$verify() then $ define/user sys$output nl:
- $ EDIT/TPU/NOSEC/NODIS/COM=SYS$INPUT 'f'/OUT='P1'
- PROCEDURE Unpacker ON_ERROR ENDON_ERROR;SET(FACILITY_NAME,"UNPACK");SET(
- SUCCESS,OFF);SET(INFORMATIONAL,OFF);f:=GET_INFO(COMMAND_LINE,"file_name");b:=
- CREATE_BUFFER(f,f);p:=SPAN(" ")@r&LINE_END;POSITION(BEGINNING_OF(b));
- LOOP EXITIF SEARCH(p,FORWARD)=0;POSITION(r);ERASE(r);ENDLOOP;POSITION(
- BEGINNING_OF(b));g:=0;LOOP EXITIF MARK(NONE)=END_OF(b);x:=ERASE_CHARACTER(1);
- IF g=0 THEN IF x="X" THEN MOVE_VERTICAL(1);ENDIF;IF x="V" THEN APPEND_LINE;
- MOVE_HORIZONTAL(-CURRENT_OFFSET);MOVE_VERTICAL(1);ENDIF;IF x="+" THEN g:=1;
- ERASE_LINE;ENDIF;ELSE IF x="-" THEN IF INDEX(CURRENT_LINE,"+-+-+-+-+-+-+-+")=
- 1 THEN g:=0;ENDIF;ENDIF;ERASE_LINE;ENDIF;ENDLOOP;t:="0123456789ABCDEF";
- POSITION(BEGINNING_OF(b));LOOP r:=SEARCH("`",FORWARD);EXITIF r=0;POSITION(r);
- ERASE(r);x1:=INDEX(t,ERASE_CHARACTER(1))-1;x2:=INDEX(t,ERASE_CHARACTER(1))-1;
- COPY_TEXT(ASCII(16*x1+x2));ENDLOOP;WRITE_FILE(b,GET_INFO(COMMAND_LINE,
- "output_file"));ENDPROCEDURE;Unpacker;QUIT;
- $ delete/nolog 'f'*
- $ CHECKSUM 'P1'
- $ IF CHECKSUM$CHECKSUM .eqs. P2 THEN $ EXIT
- $ e "-E-CHKSMFAIL, Checksum of ''P1' failed."
- $ ENDSUBROUTINE
- $START:
- $ create 'f'
- XCOPYRIGHT NOTICE:
- X This program was written at the Hebrew University and is given for a publi
- Vc
- X use as long as it is used for non-profit interests. The Hebrew university
- X is not responsible for any damage that might be caused due to use or mis-us
- Ve
- X of this software. It is given as-is with no waranty.
- X
- X
- XISEND is the implementation for Unix and VMS systems of RFC-1159 and RFC-131
- V2.
- XIt will compile on most Unix systems and on VMS systems that use MultiNet.
- X The headers of ISEND.C and ISENDD.C describe how to compile, link and run
- Xthem.
- X
- X Note for AIX: The compilation variable "unix" is not defined on these syste
- Vms
- Xas it is on other Unix systems. You have to enter
- X#define unix
- Xat each source file, and then you'll have hard work to make it compiling...
- X
- X Note for Ultrix: Remove the line that include <fcntl.h>
- X
- X Note for Wollogong: Modified 11-Aug-1992,`20
- X by Jim Gerland,`20
- X University at Buffalo,`20
- X - to run under WINTCP 5.2
- X - created makefile.
- X - modified compile.com to use isend.opt file
- X - created start-isend-server.com
- X
- X Note for UCX: I haven't checked it on these systems. However, you should`2
- V0
- Xmodify the include files and link with the appropriate library.
- X
- X Note for MultiNet: If you are using Multinet 2.2 (and not 3.0) then
- Xrename ISENDD.C_V22 to ISENDD.C before compiling.
- X
- XRUNNING the background process: The program ISEND should be run at the
- Xbackground. On VMS it should be run like:
- X
- X$ RUN/DETACH/INPUT=NL:/OUTPUT=NL:/ERROR=NL:/PROCESS_NAME="ISEND_task" -
- X /PRIV=(NOALL,TMPMBX,NETMBX,OPER) -
- X UTIL$:ISENDD
- X
- XOPER is needed in order to broadcast messages.
- X
- XOn Unix it should be run like:
- X
- X% isendd
- X
- Xand it will fork by itself.
- X
- X Bugs should be reported to YEHAVI@VMS.HUJI.AC.IL
- X
- X
- XRFC-1312 compatibility: The program was originaly written according to RFC-1
- V159.
- XThe server was then upgraded to support RFC-1312 as well (ignoring the new
- Xfields). The client is left with the old version in order to communicate
- Xwith older implementations of ISENDD.
- X
- X
- XFILES INCLUDED:
- X
- XAAAREADME.TXT - This file.
- XISEND.1 - Man page for Unix systems.
- XISEND.RNH - Help file for VMS. RUNOFF it.
- XISEND.C - The client program.
- XISENDD.C - The background daemon.
- XUNIX_BRDCST.C - Linked with ISENDD on Unix systems.
- XVMS_BROADCAST.C - Linked with ISENDD on VMS systems.
- XCOMPILE.COM - DCL procedure to compile on VMS
- XCOMPILE - Unix procedure for compilation.
- $ CALL UNPACK AAAREADME.TXT;12 520155160
- $ create 'f'
- Xcc -o isend isend.c
- Xcc -o isendd isendd.c unix_brdcst.c
- $ CALL UNPACK COMPILE.;2 507200431
- $ create 'f'
- X$ CC/NOLIST ISEND /DEFINE=WINTCP
- X$ CC/NOLIST ISENDD /DEFINE=WINTCP
- X$ CC/NOLIST VMS_BROADCAST
- X$ LINK ISEND,ISEND.OPT/OPTION
- X$ LINK ISENDD,VMS_BROADCAST,ISEND.OPT/OPTION
- X$ EXIT
- $ CALL UNPACK COMPILE.COM;6 556285164
- $ create 'f'
- X/* ISEND.C`09V1.0
- X `7C This program was written at the Hebrew University and is given for a p
- Vublic
- X `7C use as long as it is used for non-profit interests. The Hebrew universi
- Vty
- X `7C is not responsible for any damage that might be caused due to use or mi
- Vs-use
- X `7C of this software. It is given as-is with no waranty.
- X `7C
- X `7C This is the client program for the InterNet SEND protocol as described
- V in
- X `7C RFC-1159. It will compile on Unix and VMS systems (using MultiNet). On
- X `7C IBM-AIX systems it must be compiled with the compilation variable "unix
- V"
- X `7C defined (it is defined by the compiler on other Unix systems).
- X `7C
- X `7C USAGE:
- X `7C ISEND InternetAddress Message
- X `7C will use UDP interface, and:
- X `7C ISEND InternetAddress
- X `7C will request the text from the user line by line and will use TCP conne
- Vction.
- X `7C
- X `7C Modified: 11-Aug-1992
- X `7C Jim Gerland (JRG)
- X `7C University at Buffalo
- X `7C Added #ifdefs for Multinet & Wollongong
- X `7C
- X `7C On VMS it should be linked with the command:
- X `7C $ LINK /EXE=ISEND.EXE ISEND.OBJ,ISEND.OPT/OPTION
- X `7C and define it as a foreign DCL command.
- X */
- X#include <stdio.h>
- X#ifdef unix
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netdb.h>
- X#endif /* unix */
- X
- X#ifdef MULTINET
- X#include "multinet_root:`5Bmultinet.include.sys`5Dtypes.h"
- X#include "multinet_root:`5Bmultinet.include.sys`5Dsocket.h"
- X#include "multinet_root:`5Bmultinet.include`5Dnetdb.h"
- X/* The following are for Multinet's library: */
- X#define`09close`09socket_close
- X#define`09write`09socket_write
- X#define`09read`09socket_read
- X#define`09perror`09socket_perror
- X#endif /* MULTINET */
- X
- X/* JRG 11-Aug-1992 */
- X#ifdef WINTCP
- X#include "twg$tcp:`5Bnetdist.include.sys`5Dtypes.h"
- X#include "twg$tcp:`5Bnetdist.include.sys`5Dsocket.h"
- X#include "twg$tcp:`5Bnetdist.include`5Dnetdb.h"
- X#endif /* WINTCP */
- X
- X#define`09LINESIZE`091024`09`09/* Buffer size */
- X#define ISEND_PORT`0918`09`09/* UDP and TCP port 18 */
- X
- X#define`09UDP`090
- X#define`09TCP`091
- X
- Xchar`09LocalhostName`5B1024`5D;`09`09/* Store here the Internet name of us *
- V/
- X
- X/* This structure is the sockaddr structure usually used */
- Xstruct sockaddr_in `7B
- X`09short`09`09sin_family;`09/* family */
- X`09unsigned short`09sin_port;`09/* port number */
- X`09unsigned long`09sin_addr;`09/* Internet address */
- X`09char`09`09sin_zero`5B8`5D;`09/* unused, must be 0 */
- X`7D;
- X
- X
- X/*
- X `7C Find the local hostname, parse the parameters and dispatch.
- X */
- Xmain(cc, vv)
- Xchar`09**vv;
- Xint`09cc;
- X`7B
- X`09struct`09hostent`09*HostEntry;
- X`09char`09text`5BLINESIZE`5D,`09`09/* Construct here the message text */
- X`09`09address`5BLINESIZE`5D,`09/* To whome to send */
- X`09`09*p, *strchr();
- X`09unsigned int`09InternetAddress,`09/* IP address of host */
- X`09`09`09i, mode;`09`09/* Reliable to UDP */
- X
- X/* Get our local hostname */
- X`09if(gethostname(LocalhostName, sizeof(LocalhostName)) != 0) `7B
- X`09`09perror("Gethostname"); exit(1);
- X`09`7D
- X
- X/* See whether we have an address to send to */
- X`09if(cc < 2) `7B`09/* no... */
- X`09`09printf("Usage: ISEND address text\n"); exit(1);
- X`09`7D
- X
- X/* Get the hostname from the address */
- X`09strncpy(address, vv`5B1`5D, LINESIZE);
- X`09if((p = strchr(address, '@')) == NULL) `7B
- X`09`09p = &address`5Bstrlen(address)`5D;`09/* End of address - here will be
- V the @ */
- X`09`09strcat(address, "@localhost");`09/* Make it a local user if no hostnam
- Ve */
- X`09`7D
- X`09*p++ = '\0';`09/* Get to hostname and delimit username */
- X
- X/* Get the IP address of the host */
- X`09if((HostEntry = gethostbyname(p)) == NULL) `7B
- X`09`09perror("GetHostByName");
- X`09`09exit(1);
- X`09`7D
- X
- X`09if(HostEntry->h_length != 4) `7B`09/* Illegal */
- X`09`09printf("Illegal address length=%d\n", HostEntry->h_length);
- X`09`09exit(1);
- X`09`7D
- X
- X/* Assemble the address into a longword */
- X`09InternetAddress =`20
- X`09`09(((HostEntry->h_addr)`5B0`5D & 0xff) << 24) +
- X`09`09(((HostEntry->h_addr)`5B1`5D & 0xff) << 16) +
- X`09`09(((HostEntry->h_addr)`5B2`5D & 0xff) << 8) +
- X`09`09(((HostEntry->h_addr)`5B3`5D & 0xff));
- X
- X/* Get the parameters */
- X`09if(cc > 2) `7B`09/* The text is there */
- X`09`09mode = UDP;`09`09/* Use unrliable mode in this case */
- X`09`09/* Construct the text from the parameters */
- X`09`09*text = '\0';
- X`09`09for(i = 2; i < cc; i++) `7B
- X`09`09`09strcat(text, vv`5Bi`5D); strcat(text, " ");
- X`09`09`7D
- X`09`09text`5Bstrlen(text) - 1`5D = '\0';`09/* Remove the last blank */
- X`09`09send_message(InternetAddress, address, mode, text);
- X`09`09exit(1);
- X`09`7D
- X`09else
- X`09`09mode = TCP;`09/* No text - have to read it and we'll also use reliable
- V mode */
- X
- X
- X/* We have to read it interactively. Loop untill blank line */
- X`09printf("Hit your message. End with empty line\n");
- X`09for(;;) `7B
- X`09`09printf("%s: ", address);
- X`09`09if(fgets(text, sizeof text, stdin) == NULL)
- X`09`09`09break;`09/* Null line */
- X`09`09if((p = (char*)strchr(text, '\n')) != NULL) *p = '\0';
- X`09`09if(*text == '\0') break;`09/* Another sign of empty line */
- X`09`09send_message(InternetAddress, address, mode, text);
- X`09`7D
- X`09exit(0);
- X`7D
- X
- X
- X/*
- X `7C Send the given text to the given IP address. USe UDP or TCP as requeste
- Vd in
- X `7C mode argument.
- X */
- Xsend_message(InternetAddress, ToUsername, mode, text)
- Xunsigned int`09mode,`09`09/* TCP or UDP */
- X`09`09InternetAddress;
- Xchar`09*ToUsername, *text;
- X`7B
- X`09unsigned char`09*p, line`5BLINESIZE`5D,
- X`09`09`09from`5BLINESIZE`5D;`09/* Construct the sender's address here */
- X`09struct`09sockaddr_in`09SocketName;
- X`09int`09Socket, i, size;
- X
- X/* Remove all controls */
- X`09for(p = (unsigned char *)text; *p != '\0'; *p++)
- X`09`09if((*p < ' ') `7C`7C (*p > '\176')) *p = ' ';
- X
- X/* Create the sender's address. We preceed the message with it for clarity *
- V/
- X`09cuserid(from); strcat(from, "@"); strcat(from, LocalhostName);
- X
- X/* Create the message buffer:
- X A - Protocol version 1.
- X Username (Null terminated)
- X Terminal name (Null terminated) - we use an empty terminal name
- X Text
- X*/
- X`09sprintf(line, "A%s", ToUsername);
- X`09size = strlen(line);`09/* First part - A + username */
- X`09line`5Bsize++`5D = '\0';`09/* Null - end of username (just for programmin
- Vg beauti... */
- X`09line`5Bsize++`5D = '\0';`09/* Null terminal name (Sprintf can't print two
- V nulls */
- X`09sprintf(&line`5Bsize`5D, "%s: %s", from, text);
- X`09size += (strlen(&line`5Bsize`5D) + 1);`09/* +1 for the terminating null *
- V/
- X
- X/* Create a local socket */
- X`09if(mode == UDP) `7B
- X`09`09if((Socket = socket(AF_INET, SOCK_DGRAM, 0)) == -1) `7B
- X`09`09`09perror("Can't create UDP local socket");
- X`09`09`09return;
- X`09`09`7D
- X`09`7D else `7B
- X`09`09if((Socket = socket(AF_INET, SOCK_STREAM, 0)) == -1) `7B
- X`09`09`09perror("Can't create TCP local socket");
- X`09`09`09return;
- X`09`09`7D
- X`09`7D
- X
- X/* Create the connect structure */
- X`09SocketName.sin_family = (AF_INET);
- X`09SocketName.sin_port = htons(ISEND_PORT);
- X`09SocketName.sin_addr = htonl(InternetAddress);
- X`09for(i = 0; i < 8; i++)
- X`09`09(SocketName.sin_zero)`5Bi`5D = 0;`09/* Must be zero */
- X
- X/* If it is UDP then simply send the message */
- X`09if(mode == UDP) `7B
- X`09`09if(sendto(Socket, line, size, 0, &SocketName, sizeof(SocketName)) == -
- V1) `7B
- X`09`09`09perror("Can't send UDP message");
- X`09`09`7D
- X`09`09else `7B
- X`09`09`09/* the other side must confirm it by echoing the message */
- X`09`09`09printf("Waiting for confirmation...");
- X`09`09`09i = sizeof(SocketName);
- X`09`09`09if((size = recvfrom(Socket, line, sizeof line, 0,
- X`09`09`09 &SocketName, &i)) <= 0)
- X`09`09`09`09perror("Recvfrom");
- X`09`09`09else `7B`09/* Ignore what we got back */
- X`09`09`09`09printf(" OK\n");
- X`09`09`09`7D
- X`09`09`7D
- X`09`09close(Socket);
- X`09`7D
- X`09else `7B
- X/* TCP - Create a connection and send the message to there */
- X`09`09printf("Connecting...");
- X`09`09if(connect(Socket, &SocketName, sizeof(SocketName)) == 0) `7B
- X`09`09`09if(send(Socket, line, size, 0) > 0)
- X`09`09`09`09printf("Sent.\n");
- X`09`09`09else
- X`09`09`09`09perror("Can't send command");
- X`09`09`7D
- X`09`09else
- X`09`09`09perror("Can't connect");
- X`09`09close(Socket);
- X`09`7D
- X`7D
- $ CALL UNPACK ISEND.C;41 760638621
- $ create 'f'
- X1 ISEND`0D`0A
- X ISEND is a program used to send one line interactive message to`0D`
- V0A
- X another user on an InterNet host that supports this protocol. It is`0D`
- V0A
- X similar to the BITnet's TELL (or SEND/MESSAGE) but it uses the`0D`
- V0A
- X InterNet protocols rather than the NJE one (thus the hosts accessible`0D`
- V0A
- X by it are usually different). It can be also thought as the Unix`0D`
- V0A
- X WRITE command but not limited to the same host.`0D`0A
- X Note that if the user is not logged-on at the time you send the`0D`
- V0A
- X message you get no indication about it and the message is lost. Thus,`0D`
- V0A
- X use the FINGER command first to check whether the other side is`0D`
- V0A
- X logged-on.`0D`0A
- X`0D`0A
- X The command's format is either:`0D`0A
- X`0D`0A
- X $ ISEND ADDRESS text`0D`0A
- X`0D`0A
- X in this case an unreliable protocol is used and the program is waiting`0D`
- V0A
- X for a confirmation from the other side. If no confirmation arrives in`0D`
- V0A
- X a reasonable time (30-60 seconds) you should abort it.`0D`0A
- X`0D`0A
- X A different method is:`0D`0A
- X`0D`0A
- X $ ISEND ADDRESS`0D`0A
- X`0D`0A
- X Now you'll be propmted for the text line by line. Each line will`0D`
- V0A
- X generate a new connection to the other host using a reliable protocol.`0D`
- V0A
- X`0D`0A
- X Incoming messages will appear on your screen with a message:`0D`0A
- X`0D`0A
- X #### InterNet message from host xxxxx ####`0D`0A
- X`0D`0A
- X Note that only the sending host can be identified correctly and the`0D`
- V0A
- X username can not be authenticated (thus it might be incorrect).`0D`0A
- X2 Examples`0D`0A
- X In order to send a message using unreliable protocol (UDP) to`0D`
- V0A
- X user XYZ on host X.Y.EDU issue the command:`0D`0A
- X`0D`0A
- X $ ISEND XYZ@X.Y.EDU This is a test from Jerusalem`0D`0A
- X`0D`0A
- X and in order to send a message to user OOO on node KUKURIKU at our`0D`
- V0A
- X university using a reliable protocol (TCP) use the command:`0D`0A
- X`0D`0A
- X $ ISEND OOO@KUKURIKU`0D`0A
- X OOO@KUKURIKU: this is another test`0D`0A
- X OOO@KUKURIKU: (hit <cr> to exit it)`0D`0A
- X`0D`0A
- X Arriving messages to us will look like:`0D`0A
- X`0D`0A
- X #### InterNet message from host KUKURIKU ####`0D`0A
- X OOO@KUKURIKU: This a test message...`0D`0A
- X`0D`0A
- X Note: Only the hostname at the first line is reliable. The address`0D`
- V0A
- X at the second line can be forged thus it should not be trusted.`0D`0A
- $ CALL UNPACK ISEND.HLP;1 6514567
- $ create 'f'
- XTWG$TCP:`5BNETDIST.LIB`5DTWGLIB.OLB /LIB
- XSYS$SHARE:VAXCRTL.EXE /SHARE
- $ CALL UNPACK ISEND.OPT;2 2054710556
- $ create 'f'
- X.LOWER CASE
- X.RIGHT MARGIN 72
- X.NOPAG
- X.LEFT MARGIN +2
- X.INDENT -2
- X1#`5E`5EISEND\\
- X.PARAGRAPH 5,0
- X`5E`5EISEND\\ IS A PROGRAM USED TO SEND ONE LINE INTERACTIVE MESSAGE TO ANOT
- VHER
- XUSER ON AN `5EINTER`5ENET HOST THAT SUPPORTS THIS PROTOCOL. `5EIT IS SIMILAR
- V TO
- XTHE `5E`5EBIT\\NET'S `5E`5ETELL\\ (OR `5E`5ESEND/MESSAGE\\) BUT IT USES THE
- V `5EINTER`5ENET
- XPROTOCOLS RATHER THAN THE `5E`5ENJE\\ ONE (THUS THE HOSTS ACCESSIBLE BY IT A
- VRE
- XUSUALLY DIFFERENT). `5EIT CAN BE ALSO THOUGHT AS THE `5EUNIX `5E`5EWRITE\\ C
- VOMMAND
- XBUT NOT LIMITED TO THE SAME HOST.
- X.PARAGRAPH
- X`5ENOTE THAT IF THE USER IS NOT LOGGED-ON AT THE TIME YOU SEND THE MESSAGE Y
- VOU
- XGET NO INDICATION ABOUT IT AND THE MESSAGE IS LOST. `5ETHUS, USE THE `5E`5EF
- VINGER\\
- XCOMMAND FIRST TO CHECK WHETHER THE OTHER SIDE IS LOGGED-ON.
- X.BLANK
- X.PARAGRAPH
- X`5ETHE COMMAND'S FORMAT IS EITHER:
- X.BLANK
- X.INDENT +5
- X`5E`5E$#ISEND##`5EADDRESS\\##TEXT
- X.BLANK
- XIN THIS CASE AN UNRELIABLE PROTOCOL IS USED AND THE PROGRAM IS WAITING FOR
- XA CONFIRMATION FROM THE OTHER SIDE. `5EIF NO CONFIRMATION ARRIVES IN A REASO
- VNABLE
- XTIME (30-60 SECONDS) YOU SHOULD ABORT IT.
- X.BLANK
- X.PARAGRAPH
- X`5EA DIFFERENT METHOD IS:
- X.BLANK
- X.INDENT +5
- X`5E`5E$#ISEND##ADDRESS\\
- X.BLANK
- X`5ENOW YOU'LL BE PROPMTED FOR THE TEXT LINE BY LINE. `5EEACH LINE WILL GENER
- VATE
- XA NEW CONNECTION TO THE OTHER HOST USING A RELIABLE PROTOCOL.
- X.BLANK
- X.PARAGRAPH
- X`5EINCOMING MESSAGES WILL APPEAR ON YOUR SCREEN WITH A MESSAGE:
- X.BLANK
- X.INDENT 5
- X_#_#_#_# `5EINTER`5ENET MESSAGE FROM HOST XXXXX _#_#_#_#
- X.BLANK
- X`5ENOTE THAT ONLY THE SENDING HOST CAN BE IDENTIFIED CORRECTLY AND THE USERN
- VAME
- XCAN NOT BE AUTHENTICATED (THUS IT MIGHT BE INCORRECT).
- X.INDENT -2
- X2#`5EEXAMPLES
- X.PARAGRAPH
- X`5EIN ORDER TO SEND A MESSAGE USING UNRELIABLE PROTOCOL (`5EU`5ED`5EP) TO US
- VER `5E`5EXYZ\\
- XON HOST `5E`5EX.Y.EDU\\ ISSUE THE COMMAND:
- X.BLANK
- X.INDENT +5
- X`5E`5E$#ISEND XYZ@X.Y.EDU\\ `5ETHIS IS A TEST FROM `5EJERUSALEM
- X.BLANK
- XAND IN ORDER TO SEND A MESSAGE TO USER `5E`5EOOO\\ ON NODE `5E`5EKUKURIKU\\
- V AT OUR
- XUNIVERSITY USING A RELIABLE PROTOCOL (`5E`5ETCP\\) USE THE COMMAND:
- X.BLANK
- X.INDENT +5
- X`5E`5E$#ISEND OOO@KUKURIKU
- X.INDENT +5
- XOOO@KUKURIKU: \\THIS IS ANOTHER TEST
- X.INDENT +5
- X`5E`5EOOO@KUKURIKU:\\ (HIT _<CR_> TO EXIT IT)
- X.BLANK
- X`5EARRIVING MESSAGES TO US WILL LOOK LIKE:
- X.BLANK
- X.INDENT +5
- X_#_#_#_# `5EINTER`5ENET MESSAGE FROM HOST `5E`5EKUKURIKU\\ _#_#_#_#
- X.INDENT +5
- X`5E`5EOOO@KUKURIKU:\\ `5ETHIS A TEST MESSAGE...
- X.BLANK
- X`5ENOTE: `5EONLY THE HOSTNAME AT THE FIRST LINE IS RELIABLE. `5ETHE ADDRESS
- V AT THE
- XSECOND LINE CAN BE FORGED THUS IT SHOULD NOT BE TRUSTED.
- $ CALL UNPACK ISEND.RNH;5 1516222054
- $ create 'f'
- X/* ISENDd.C`09V2.0
- X `7C This program was written at the Hebrew University and is given for a p
- Vublic
- X `7C use as long as it is used for non-profit interests. The Hebrew universi
- Vty
- X `7C is not responsible for any damage that might be caused due to use or mi
- Vs-use
- X `7C of this software. It is given as-is with no waranty.
- X `7C
- X `7C This is the daemon which should run at the background to receive mess
- Vages
- X `7C to local users and send them. It can be compiled either on Unix or VMS
- V with
- X `7C MultiNet. On IBM-AIX the compilation variable "unix" must be defined.
- X `7C
- X `7C Modified: 11-Aug-1992
- X `7C Jim Gerland (JRG)
- X `7C University at Buffalo
- X `7C Added #ifdefs for Multinet & Wollongong
- X `7C
- X `7C On VMS it should be linked with the command:
- X `7C $ LINK /EXE=ISENDD.EXE ISENDD.OBJ,VMS_BROADCAST.OBJ,ISEND.OPT/OPTION
- X `7C and define it as a foreign DCL command.
- X `7C
- X `7C and on Unix:
- X `7C % cc -o isendd isendd.c unix_brdcst.c
- X `7C and run it as a detached process.
- X `7C
- X `7C When receiving a message all control characters are stripped from it a
- Vnd
- X `7C it is then broadcasted to the user.
- X `7C
- X `7C Note: MultiNet does not support the Select() function. Hence, this mod
- Vule
- X `7C is a total-mess in order to be compatible with Unix and VMS at once...
- X `7C
- X `7C We can receive in parallel up to 32 TCP messages (TCP messages can com
- Ve in
- X `7C parts so we must keep a structure for each one).
- X `7C
- X `7C V2.0 - Accept format of RFC-1312 - simply ignore the extra fields.
- X */
- X#include <stdio.h>
- X#ifdef unix
- X#include <sys/types.h>
- X#include <sys/socket.h>
- X#include <netdb.h>
- X#include <sys/file.h>
- X#include <sys/ioctl.h>
- X#endif
- X
- X#ifdef MULTINET
- X#include "multinet_root:`5Bmultinet.include.sys`5Dtypes.h"
- X#include "multinet_root:`5Bmultinet.include.sys`5Dsocket.h"
- X#include "multinet_root:`5Bmultinet.include.netinet`5Din.h"
- X#include <stdio.h>
- X#include "multinet_root:`5Bmultinet.include`5Dnetdb.h"
- X#include "multinet_root:`5Bmultinet.include.vms`5Dinetiodef.h"
- X/* Multinet uses different naming in order to not clash with C routines: */
- X#define`09close`09socket_close
- X#define`09write`09socket_write
- X#define`09read`09socket_read
- X#define`09perror`09socket_perror
- X#endif /* MULTINET */
- X
- X#ifdef WINTCP /* JRG 11-Aug-1992 */
- X#include "twg$tcp:`5Bnetdist.include.sys`5Dtypes.h"
- X#include "twg$tcp:`5Bnetdist.include.sys`5Dsocket.h"
- X#include "twg$tcp:`5Bnetdist.include.netinet`5Din.h"
- X#include "twg$tcp:`5Bnetdist.include`5Dnetdb.h"
- X#endif /* WINTCP */
- X
- X#define`09LINESIZE`091024`09`09/* Our buffer size */
- X#define ISEND_PORT`0918`09`09/* UDP and TCP port 18 */
- X#define`09MAX_SESSIONS`0932`09`09/* Maximum number of concurrent TCP connect
- Vions open */
- X
- X#define`09UDP`090
- X#define`09TCP`091
- X
- Xchar`09LocalhostName`5B1024`5D;
- X
- X/* The sockaddr structure: */
- Xstruct sockaddr_in `7B
- X`09short`09`09sin_family;`09/* family */
- X`09unsigned short`09sin_port;`09/* port number */
- X`09unsigned long`09sin_addr;`09/* Internet address */
- X`09char`09`09sin_zero`5B8`5D;`09/* unused, must be 0 */
- X`7D;
- X
- X/* For TCP connections: */
- Xint`09TCPchannels`5BMAX_SESSIONS`5D,`09/* The TCP channels opened */
- X`09TCPipAddress`5BMAX_SESSIONS`5D,`09/* The IP address of sender */
- X`09TCPsizeRead`5BMAX_SESSIONS`5D;`09/* How much data we read already */
- Xchar`09TCPmessages`5BMAX_SESSIONS`5D`5BLINESIZE`5D;
- Xchar`09Message`5BLINESIZE`5D;`09`09/* Received message. Must be here for VMS
- V async IO */
- X
- X#ifndef unix
- X/* VMS does async IO and we have to keep some variables accessible by all ro
- Vutines */
- X`09short`09TCPiosb`5BMAX_SESSIONS`5D`5B4`5D,
- X`09`09UDPiosb`5B4`5D;
- X`09int`09FromLength;`09/* Length of data is FromSocket struct */
- X`09int`09UDPsocket;
- X`09struct`09sockaddr_in`09FromSocket;`09/* Fill here the sender's info */
- X#endif
- X
- X
- X/*
- X `7C Create the local sockets, bind them and then loop inside Select() for
- X `7C incoming data.
- X */
- Xmain()
- X`7B
- X`09int`09i, fd, TCPsocket,`09/* Socket descriptors */
- X`09`09status, `09`09/* Sockets on which we have read pending */
- X`09`09TableWidth;`09`09/* for Select */
- X`09int`09UDPsocket;
- X`09fd_set`09ReadFds;`09`09/* For Select */
- X`09struct`09sockaddr_in`09TCPsocketname, UDPsocketname;
- X
- X/* Create and bind local sockets */
- X`09UDPsocket = socket(AF_INET, SOCK_DGRAM, 0);
- X TCPsocket = socket(AF_INET, SOCK_STREAM, 0);
- X`09if((UDPsocket == -1) `7C`7C (TCPsocket == -1)) `7B
- X`09`09printf("Can't create local socket.\n"); exit(1);
- X`09`7D
- X
- X`09TCPsocketname.sin_family = UDPsocketname.sin_family = AF_INET;
- X`09TCPsocketname.sin_port = UDPsocketname.sin_port = htons(ISEND_PORT);
- X`09TCPsocketname.sin_addr = UDPsocketname.sin_addr = 0;`09/* Local host */
- X`09if(bind(UDPsocket, &UDPsocketname, sizeof(UDPsocketname)) == -1) `7B
- X`09`09perror("UDP socket bind"); exit(1);
- X`09`7D
- X`09if(bind(TCPsocket, &TCPsocketname, sizeof(TCPsocketname)) == -1) `7B
- X perror("TCP socket bind"); exit(1);
- X`09`7D
- X
- X/* Listen on the TCP socket (UDP have no Listen facility) */
- X`09if(listen(TCPsocket, 5) == -1) `7B
- X`09`09perror("TCP listen"); exit(1);
- X`09`7D
- X
- X/* Fork if we are a unix system */
- X#ifdef unix
- X `09if(fork()) /* Move to the background automatically */
- X `09`09exit(0);
- X `09setpgrp(0, getpid()); /* Set a new process group. */
- X `09if((fd = open("/dev/tty", O_RDWR)) >= 0) `7B
- X `09`09ioctl(fd, TIOCNOTTY, 0); /* Disconnect from terminal */
- X `09`09close(fd);
- X `09`7D
- X `09chdir("/"); /* To prevent "Mount device busy" messages */
- X#endif
- X
- X/* Clear the TCP sessions array. A size of -1 signals a free entry */
- X`09for(i = 0; i < MAX_SESSIONS; i++)
- X`09`09TCPsizeRead`5Bi`5D = -1;
- X
- X/* Now, wait for a coming call */
- X/* Unix - Wait in select for a call or data for an opened connection */
- X`09for(;;) `7B
- X#ifndef WINTCP /* JRG 11-Aug-1992 */
- X`09`09TableWidth = getdtablesize();`09/* Get descriptors table size */
- X#endif
- X`09`09FD_ZERO(&ReadFds);`09/* Clear all FDs */
- X`09`09FD_SET(TCPsocket, &ReadFds);`09/* Set the channels we want info on */
- X`09`09FD_SET(UDPsocket, &ReadFds);
- X`09`09/* Set the FD's of opened TCP connections */
- X`09`09for(i = 0; i < MAX_SESSIONS; i++)
- X`09`09`09if(TCPsizeRead`5Bi`5D >= 0)
- X`09`09`09`09FD_SET(TCPchannels`5Bi`5D, &ReadFds);
- X
- X/* Wait in select() untill something to do (last parameter NULL signals it t
- Vo
- X block untill there is something to read) */
- X`09`09if(select(TableWidth, &ReadFds, NULL, NULL, NULL) == -1) `7B
- X`09`09`09/* Error in select */
- X`09`09`09perror("Select"); exit(1);
- X`09`09`7D
- X/* Something have to be read: */
- X`09`09if(FD_ISSET(TCPsocket, &ReadFds))
- X`09`09`09accept_tcp_connection(TCPsocket);
- X`09`09/* Check the FD's of opened TCP connections */
- X`09`09for(i = 0; i < MAX_SESSIONS; i++)
- X`09`09`09if(FD_ISSET(TCPchannels`5Bi`5D, &ReadFds))
- X`09`09`09`09read_tcp_data(i);
- X`09`09if(FD_ISSET(UDPsocket, &ReadFds))
- X`09`09`09read_udp_data(UDPsocket);
- X`09`7D
- X`7D
- X
- X
- X/*
- X `7C Some data came over the UDP channel - read the packet, decompose it, an
- Vd
- X `7C send to user. Then send back the same message to sender
- X */
- Xread_udp_data(UDPsocket)
- Xint`09UDPsocket;
- X`7B
- X`09int`09MessageSize,
- X`09`09ProtocolVersion,
- X`09`09FromLength;`09/* Length of data is FromSocket struct */
- X`09struct`09sockaddr_in`09FromSocket;`09/* Fill here the sender's info */
- X`09char`09ReplyBuffer`5BLINESIZE`5D;
- X
- X/* On Unix we have to read the message now */
- X`09FromLength = sizeof(struct sockaddr_in);`09/* Have to be initialized */
- X`09MessageSize = recvfrom(UDPsocket, Message, sizeof(Message), 0,
- X`09`09`09 &FromSocket, &FromLength);
- X
- X`09if((ProtocolVersion = handle_message(Message, MessageSize,
- X`09 FromSocket.sin_addr)) != 0) `7B
- X/* Send the a message back to sender telling him we got it */
- X`09`09if(ProtocolVersion == 1)`09/* Old version */
- X`09`09`09if(sendto(UDPsocket, Message, MessageSize, 0, &FromSocket, FromLeng
- Vth) <= 0)
- X`09`09`09`09perror("Sendto");
- X`09`09else `7B
- X`09`09`09strcpy(ReplyBuffer, "+OK");
- X`09`09`09if(sendto(UDPsocket, ReplyBuffer, strlen(ReplyBuffer) + 1, 0,
- X`09`09`09`09&FromSocket, FromLength) <= 0)
- X`09`09`09`09`09perror("Sendto");
- X`09`09`7D
- X`09`7D
- X`7D
- X
- X
- X/*
- X `7C A connection has been requested. Accept it and set the TCP arrays accor
- Vdingly.
- X `7C On VMS we simply wait here inside the ACCEPT untill a new connection ar
- Vrive.
- X `7C When it is accepted we queue an IO for it and the rest of the work is d
- Vone
- X `7C in ASTs (so we can sleep again in ACCEPT).
- X */
- Xaccept_tcp_connection(TCPsocket)
- Xint`09TCPsocket;
- X`7B
- X`09int`09i, FromLength;`09/* Length pf FromSocket */
- X`09struct`09sockaddr_in`09FromSocket;
- X
- X/* Find an empty slot (REadSize = -1) */
- X`09for(i = 0; i < MAX_SESSIONS; i++)
- X`09`09if(TCPsizeRead`5Bi`5D == -1) break;`09/* Free entry */
- X`09if(i == MAX_SESSIONS)`09/* No free entry found */
- X`09`09return;`09/* Can't handle it. Hopefully we never get to here... */
- X
- X/* Accept it */
- X`09FromLength = sizeof(FromSocket);
- X`09TCPchannels`5Bi`5D = accept(TCPsocket, &FromSocket, &FromLength);
- X`09if(TCPchannels`5Bi`5D == -1) `7B`09/* Failed */
- X`09`09return;
- X`09`7D
- X
- X/* Accepted correctly - mark as occiupied and save the IP address of sender
- V */
- X`09TCPsizeRead`5Bi`5D = 0;`09/* Mark it as occiupied and no data yet */
- X`09TCPipAddress`5Bi`5D = FromSocket.sin_addr;
- X/* Accept done. Now wait for data */
- X`7D
- X
- X
- X/*
- X `7C Some data arrived from the TCP connection. Append it to our buffer and
- V wait
- X `7C for more data. If we read 0 bytes then this is a signal that the other
- V side
- X `7C closed the connection. In this case we should have now a full message.
- X */
- Xread_tcp_data(Connection)
- Xint`09Connection;`09/* Connection number in our arrays */
- X`7B
- X`09int`09size, ProtocolVersion;
- X`09char`09ReplyBuffer`5BLINESIZE`5D;
- X
- X/* Compute the size of area left in buffer for this connection */
- X`09size = LINESIZE - TCPsizeRead`5BConnection`5D;
- X`09if(size < 0) `7B`09/* Some error; hopefully will never happen */
- X`09`09close(TCPchannels`5BConnection`5D);
- X`09`09TCPsizeRead`5BConnection`5D = -1;`09/* Mark it as free */
- X`09`09return;
- X`09`7D
- X
- X`09size = recv(TCPchannels`5BConnection`5D,
- X`09`09&(TCPmessages`5BConnection`5D`5BTCPsizeRead`5BConnection`5D`5D),
- X`09`09size, 0);
- X
- X`09if(size < 0) `7B
- X`09`09close(TCPchannels`5BConnection`5D);
- X`09`09TCPsizeRead`5BConnection`5D = -1;`09/* Mark it as free */
- X`09`09return;
- X`09`7D
- X
- X/* If the size is zero then the other party closed the connection and we hav
- Ve
- X a full message */
- X`09if(size == 0) `7B
- X`09`09if((ProtocolVersion = handle_message(TCPmessages`5BConnection`5D, TCPs
- VizeRead`5BConnection`5D,
- X`09`09`09TCPipAddress`5BConnection`5D)) != 0) `7B
- X/* Send the a message back to sender telling him we got it */
- X`09`09`09if(ProtocolVersion > 1) `7B
- X`09`09`09`09strcpy(ReplyBuffer, "+OK");
- X`09`09`09`09if(send(TCPchannels`5BConnection`5D, ReplyBuffer,
- X`09`09`09`09`09strlen(ReplyBuffer) + 1, 0) <= 0)
- X`09`09`09`09`09perror("Send");
- X`09`09`09`7D
- X`09`09`7D
- X`09`09close(TCPchannels`5BConnection`5D);
- X`09`09TCPsizeRead`5BConnection`5D = -1;
- X`09`09return;
- X`09`7D
- X
- X/* Non-zero size - increase count */
- X`09TCPsizeRead`5BConnection`5D += size;
- X`7D
- X
- X
- X/*
- X `7C Common path to UDP and TCP - Decode the message and send it to the user
- V.
- X `7C Return zero if some error, 1 if ok.
- X */
- Xhandle_message(Message, MessageSize, IPaddress)
- Xchar`09*Message;`09/* The message buffer */
- Xunsigned int`09MessageSize,`09/* How much was read */
- X`09IPaddress;`09/* IP address of sending host */
- X`7B
- X`09int`09size;
- X`09char`09ToUser`5BLINESIZE`5D,`09/* USername to send to */
- X`09`09FromHost`5BLINESIZE`5D;`09/* Host name that sent us this message */
- X`09struct`09hostent`09*HostEnt;
- X
- X`09if(MessageSize <= 0) return;`09/* Some error */
- X`09Message`5BMessageSize`5D = '\0';`09/* Delimit it for C functions to work
- V correctly */
- X
- X/* First - get the hostname of the sender */
- X`09if((HostEnt = gethostbyaddr(&IPaddress, sizeof(long), AF_INET)) == NULL)
- X`09`09/* Can't get it - use numeric address */
- X`09`09sprintf(FromHost, "%d.%d.%d.%d",
- X`09`09`09((ntohl(IPaddress) >> 24) & 0xff),
- X`09`09`09((ntohl(IPaddress) >> 16) & 0xff),
- X`09`09`09((ntohl(IPaddress) >> 8) & 0xff),
- X`09`09`09((ntohl(IPaddress)) & 0xff));
- X`09else`09strcpy(FromHost, HostEnt->h_name);
- X
- X/* Check the protocol version */
- X`09if((*Message != 'A') && (*Message != 'B'))
- X`09`09return 0;`09/* Different version - ignore it */
- X`09strcpy(ToUser, &Message`5B1`5D);
- X`09if(*ToUser == '\0')`09/* No sepcific user - ignore */
- X`09`09return 0;
- X`09size = strlen(Message);`09`09/* THe next byte after username */
- X`09if(size >= MessageSize) return 0;`09/* Too short message */
- X`09size++;`09`09/* First character of terminal name */
- X`09size += (strlen(&Message`5Bsize`5D) + 1);`09/* Ignore terminal name */
- X if(size >= MessageSize) return 0; /* Too short message */
- X
- X`09broadcast_user(ToUser, &Message`5Bsize`5D, FromHost);
- X`09return(*Message - '@');`09`09/* Return the version number */
- X`7D
- X
- X/*
- X `7C remove all controls, Format and send the message to the terminal.
- X */
- Xbroadcast_user(ToUser, MessageText, FromHost)
- Xchar`09*ToUser, *MessageText, *FromHost;
- X`7B
- X`09unsigned char`09*p;
- X`09char`09Message`5BLINESIZE`5D;
- X
- X/* Remove all controls */
- X for(p = (unsigned char *)MessageText; *p != '\0'; *p++)
- X if((*p < ' ') `7C`7C (*p > '\176')) *p = ' ';
- X
- X/* Start the message with a message who sent it and append CR LF to it: */
- X`09sprintf(Message, "\007\r\n #### InterNet message from host %s ####\r\n"
- V,
- X`09`09FromHost);
- X`09strcat(Message, MessageText);`09/* Get the message text */
- X`09strcat(Message, "\r\n");
- X`09send_user(ToUser, Message);
- X`7D
- $ CALL UNPACK ISENDD.C;48 1631354280
- $ create 'f'
- X# makefile for isend & isendd
- X
- Xcflags = /NOLIST /DEFINE=WINTCP
- X
- Xisend : isend.exe isendd.exe
- X
- Xisend.exe : isend.obj
- X link /exe=isend.exe isend.obj,isend.opt /opt
- X
- Xisend.obj : isend.c
- X cc $(cflags) /obj=isend.obj isend.c
- X
- Xisendd.exe : isendd.obj vms_broadcast.obj
- X link /exe=isendd.exe isendd.obj,vms_broadcast.obj,isend.opt /opt
- X
- Xisendd.obj : isendd.c
- X cc $(cflags) /obj=isendd.obj isendd.c
- X
- Xvms_broadcast.obj : vms_broadcast.c
- X cc $(cflags) /obj=vms_broadcast.obj vms_broadcast.c
- X
- $ CALL UNPACK MAKEFILE.;5 103375806
- $ create 'f'
- XMULTINET:MULTINET_SOCKET_LIBRARY/SHARE
- XSYS$SHARE:VAXCRTL/SHARE
- $ CALL UNPACK MULTINET.OPT;2 1662129023
- $ create 'f'
- X$ RUN /DETACH /INPUT=NL: -
- X /OUTPUT=DISK$USERDISK4:`5BACS0.UTIL.MSP`5DISEND.OUT -
- X /ERROR=DISK$USERDISK4:`5BACS0.UTIL.MSP`5DISEND.ERR -
- X /PROCESS_NAME="ISEND_task" -
- X /PRIV=(NOALL,TMPMBX,NETMBX,OPER,SYSPRV,CMKRNL) -
- X DISK$USERDISK4:`5BACS0.UTIL.MSP`5DISENDD.EXE
- $ CALL UNPACK START-ISEND-SERVER.COM;3 1415273604
- $ create 'f'
- X/* UNIX_BRDCST.C `09V1.0
- X `7C This program was written at the Hebrew University and is given for a p
- Vublic
- X `7C use as long as it is used for non-profit interests. The Hebrew universi
- Vty
- X `7C is not responsible for any damage that might be caused due to use or mi
- Vs-use
- X `7C of this software. It is given as-is with no waranty.
- X `7C
- X `7C This module is used on Unix systems to broadcast a message to a given
- V user
- X `7C on all terminals he is logged-on. This module was contributed by Eitan
- X `7C Mizrotsky.
- X*/
- X
- X#include <stdio.h>
- X#include <pwd.h>
- X#include <sys/types.h> /* `5Bmea`5D Needed in some systems for <utmp.h> */
- X#include <utmp.h>
- X#include <sys/fcntl.h> /* `5Bmea`5D Needed in some systems. */
- X#include <sys/file.h>
- X#include <sys/stat.h> /* `5Bmea`5D Needed for mesg state analyse */
- X
- X
- X#define UTMP "/etc/utmp"
- X
- Xextern int errno;
- X
- X
- X/*
- X* Write the message msg to the user, on all ttys he is currently logged
- X* in.
- X* Returned value:
- X* 0 in case of error, number of messages sent otherwise.
- X* In case of error, errno can be examined.
- X*/
- Xsend_user(user, msg)
- Xchar *user, *msg;
- X`7B
- X`09int cnt = 0, fdutmp;
- X`09int ftty;
- X`09char buf`5BBUFSIZ`5D;
- X`09int i, m, n = (BUFSIZ / sizeof(struct utmp));
- X`09int bufsiz = n * sizeof(struct utmp);
- X`09char tty`5B16`5D;
- X`09struct stat stats;
- X
- X`09for(cnt = 0; cnt < strlen(user); cnt++)
- X`09`09if(user`5Bcnt`5D == ' ') `7B
- X`09`09`09user`5Bcnt`5D = '\0'; break;
- X`09`09`7D
- X`09`09else if((user`5Bcnt`5D >= 'A') && (user`5Bcnt`5D <= 'Z'))
- X`09`09`09user`5Bcnt`5D += ' '; /* lowercasify */
- X
- X`09if((fdutmp = open(UTMP, O_RDONLY)) <= 0) `7B
- X`09`09return(0);
- X`09`7D
- X
- X`09cnt = 0;
- X
- X`09while((m = read(fdutmp, buf, bufsiz)) > 0) `7B
- X`09`09m /= sizeof(struct utmp);
- X`09`09for(i = 0; i < m; i++) `7B
- X/* IBM-RS6000 specific field: */
- X#ifdef USER_PROCESS
- X`09`09`09if(((struct utmp *)buf)`5Bi`5D.ut_type != USER_PROCESS) continue;
- X#endif
- X`09`09`09if(memcmp(user, ((struct utmp *)buf)`5Bi`5D.ut_name, strlen(user))
- V != 0)
- X`09`09`09`09continue;
- X`09`09`09sprintf(tty, "/dev/%s", ((struct utmp *)buf)`5Bi`5D.ut_line);
- X`09`09`09if((ftty = open(tty, O_WRONLY)) < 0) `7B
- X`09`09`09`09continue; /* Some TTYs accept, some don't */
- X`09`09`09`7D
- X`09`09`09if(fstat(ftty,&stats)!=0 `7C`7C (stats.st_mode & 022)==0)`7B
- X`09`09`09`09close(ftty); /* mesg -n! */
- X`09`09`09`09continue; /* Some TTYs accept, some don't */
- X`09`09`09`7D
- X`09`09`09if(write(ftty, msg, strlen(msg)) < strlen(msg)) `7B
- X`09`09`09`09close(ftty);
- X`09`09`09`09continue; /* Some TTYs accept, some don't */
- X`09`09`09`7D
- X`09`09`09close(ftty);
- X`09`09`09++cnt;
- X`09`09`7D
- X`09`7D
- X`09close(fdutmp);
- X
- X`09return(cnt);
- X`7D
- $ CALL UNPACK UNIX_BRDCST.C;3 554798693
- $ create 'f'
- X/* VMS_BROADCAST.C`09V1.0
- X `7C This program was written at the Hebrew University and is given for a p
- Vublic
- X `7C use as long as it is used for non-profit interests. The Hebrew universi
- Vty
- X `7C is not responsible for any damage that might be caused due to use or mi
- Vs-use
- X `7C of this software. It is given as-is with no waranty.
- X `7C
- X `7C This module broadcasts the messages to the user on all terminals he is
- X `7C logged-in.
- X */
- X/* From STARTLET.MLB, module $BRKDEF: */
- X#define`09BRK$C_USERNAME`092
- X#define`09BRK$C_USER1`0932
- X#define`09BRK$M_CLUSTER`092048
- X
- X#define`09LINESIZE`091024
- X
- X/* VMS string descriptor */
- Xstruct DESC `7B
- X`09short`09length, class;
- X`09char`09*address;
- X`7D;
- X
- X
- X/*
- X `7C Given a user-name, find all terminals he is logged-in and send him
- X `7C the given message. We use 5 seconds timeout since this is the minimal
- X `7C time allowed by VMS.
- X `7C The function returns the number of terminals successfully notified.
- X*/
- Xint
- Xsend_user(UserName, string)
- Xchar`09*UserName, *string;
- X`7B
- X`09static struct`09DESC`09username, message;
- X`09static char`09temp`5BLINESIZE`5D, *p;
- X`09static short`09iosb`5B2`5D;
- X`09static long`09sndtyp, reqid;
- X`09long`09status;
- X
- X/* First - modify username to upper case for $BRKTHRU (can't handle lower
- X case) */
- X`09strcpy(temp, UserName);
- X`09for(p = temp; *p != '\0'; p++)
- X`09`09if((*p >= 'a') && (*p <= 'z')) *p -= ' ';
- X
- X`09message.length = strlen(string); message.address = string;`09/* Create a
- V descriptor */
- X`09username.length = strlen(temp); username.address = temp;
- X`09sndtyp = BRK$C_USERNAME;`09/* Send by username */
- X`09reqid = BRK$C_USER1;`09`09/* Type of message */
- X`09status = sys$brkthruw((long)(0),
- X`09`09&message, &username, sndtyp,
- X`09`09iosb, (long)(0), (long)(BRK$M_CLUSTER), reqid,
- X`09`09(long)(5),`09/* 5 seconds timeout */
- X`09`09(long)(0), (long)(0));
- X
- X`09return (int)(iosb`5B1`5D);`09/* Return number of users informed */
- X`7D
- X
- $ CALL UNPACK VMS_BROADCAST.C;7 420896704
- $ create 'f'
- XTWG$TCP:`5BNETDIST.LIB`5DTWGLIB.OLB /LIB
- XSYS$SHARE:VAXCRTL.EXE /SHARE
- $ CALL UNPACK WIN.OPT;3 2054710556
- $ v=f$verify(v)
- $ EXIT
- --
- Jim Gerland - Consultant, Network User Support University at Buffalo
- Academic Services, Computing & Information Technology Buffalo, NY 14260
- 716.645.3557 Work 716.645.3734 FAX
- gerland@ubvms.cc.buffalo.edu gerland@ubvms.bitnet
-