Article View: vmsnet.sources
Article #114ISEND for VMS, part 01/01
From: Jim Gerland
Date: Fri, 04 Sep 1992 06:12
Date: Fri, 04 Sep 1992 06:12
1185 lines
41660 bytes
41660 bytes
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
Technical Details
Message-ID:
<8045724@MVB.SAIC.COM>Path:
arc1-ca.pugleaf.net!sparky!uunet!stanford.edu!agate!dog.ee.lbl.gov!network.ucsd.edu!mvb.saic.com!vmsnet-sourcesShow Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!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