Jb~ TFTP_XDM.BCK TFTP_XDM.BCKLBACKUP $1$DUA33:[SYSUTIL.DECW_LOGIN]*.*/LOG PUBLIC$:[LOCAL]TFTP_XDM.BCK/SAVE YEHAVI &o4V5.5 _HUJICC::  _$1$DKA100: V5.5-2 ~ 7$*[SYSUTIL.DECW_LOGIN]AAAREADME.TXT;10+,x1./ 4Q -i0123KPWO56ϸ)g7`)g89 [@xgGHJO TFTP and XDMCP for VAX/VMS systems running MultiNet and using NCD XterminalsO ============================================================================7 The Hebrew University of Jerusalem- Computation Center' 11/1/93N The files in this directory are used to load and start the login session onONCD Xterminals. There is a TFTP server which uses the TFTP protocol to downloadLthe server's image and the fonts, and also starts the login process on theseQterminals. Another program is an XDM server which can be used instead of DW-LOGIN*mechanism (although it partially working).I NOTE: Some of these programs are run with enhanced privilege and mightOcompromise the security of your system. The Hebrew university is not reponsibleKfor any damage that might be caused to your system by using these programs.L Before compiling and linking you should skim each program and correct theK#define at its beginning to suit your node; the header of each program also<describes some side effects of it which are not listed here.ODECW$ANNOUNCE.C - This program can be used either by SYS$SYSTEM:DECW$STARTLOGINM or by DECW_LOGIN.COM; In the first case (only on VMS-5.4 and up) you haveL to define the system wide logical name DECW$LOGIN_BACKGROUND to point to3 a command procedure that will run that program.J This program opens two windows on the screen: One is our logo (100x100I pixels) and our name. The other, at the bottom of the screen displaysK the welcome message (it is not shown by the standard login procedure to# those who login via Xterminals.JTFTP_MN_SERVER.C - The TFTP server which downloads the server's image, theJ configuration files and the fonts. It will access only files which areL in a predetermined directory tree and files from SYS$COMMON:[SYSFONT...]L tree. It will serve only Xterminals listed in SYS$MANAGER:XDISPLAYS.DAT;H If you want to use TFTP to load fonts use the NCD supplied MKFONTDIRL program to create the FONTS.DIR and FONTS.ALIAS files. Then, use the VMSL utility CONVERT to convert them to STREAM_LF format. This should be done: also for each text file which will be loaded via TFTP.J This server will also start the login session by creating a subprocessM which will run SYS$SYSTEM:DECW$STARTLOGIN. It is informed to do so by the+ INFORM_TFTP_LOGIN program (see bellow).IXDMCP.C - Starts the login session when using the XDM protocol instead ofL DW-LOGIN mechanism (thus overlaps some of TFTP_MN_SERVER functionality).H It is usefull when the Xterminal has no DECnet support. It will also3 start the login session by spawnning a process.P There is a problem with Pericomm terminals which cannot use DECW$STARTLOGIN.F Instead, we use for them our DECW_LOGIN. In order to use it add anF additional paramter for these terminals called DECW_LOGIN. If this1 parameter is absent then the VMS one is used.K| XDMCP now supports call from a chooser program running on another host.I| When called from another XDM running chooser it will reply correctly.IINFORM_TFTP_LOGIN.C - Should be run by the login command procedure of theK account used by the DW-LOGIN mechanism (and this account should have noI special privileges except from NETMBX and TMPMBX). It will inform theL TFTP server to start a session on this terminal. I am using this programM instead of NCD's supplied procedure as I am over-paranoid and do not want( a public account to have privileges.QINFORM_XDMCP_LOGIN.C - Much like the previous one but connects to the XDM server.I This program runs from DECW_LOGIN.COM and serves a different purpose:I After DECW_LOGIN.C is run and the password was entered correctly, theM window is closed; this causes the Xterminal to request a new login bannerM (it doesn't know that VMS will open soon a Session manager window). Thus,M after running DECW_LOGIN XDMCP will not honor any requests to start a newH login banner. INFORM_XDM_LOGIN informs it that a session was createdL correctly and it can resume normal processing on this Xterminal (and theL next XDM request will be issued by the terminal only after the user will logout).NDECW_LOGIN.C - The most dangerous program. It is used when the login mechanismL of the terminal is XDM and DECW_LOGIN parameter is specified. It promptsJ the user for username and password. If they are correct it will submit1 DECW_LOGIN which will run the session managerN and the window manager. We have to submit it via batch as this is the onlyN easy way to start a process on behalf another user. The batch process will* terminate when the session terminates.M There is a problem finding when the terminal is truned-off and thus a newG XDM request shold be honored. This program will not notice that theL terminal is switched off. In order to cure it, it tries once a minute toO create a connection to the terminal (a connection which should be refused).P If it gets any error excpet from refusal it'll finish and free the terminal.K Note: This program is very simple. It doesn't understand , it willP not allow double-password accounts to start, it doesn't check for expirationM dates or access-time restriction, etc. It is used only temporarily untill1 DECW$STARTLOGIN will run correctly under XDM.PDECW_LOGIN.COM - Submitted by DECW_LOGIN to start a session after the user typedK in a correct password. It is needed only if you want to start the loginH banner using XDM and not DW-LOGIN. It runs the window manager at theO background, run INFORM_XDM_LOGIN to inform that we've created a successfull8 connection to the screen and then runs DECW$SESSION.PSYS$MANAGER:XDISPLAYS.DAT - Lists all Xstations which will be served by the TFTP" and XDM server. Its format is:N * IP address Name Transport for DECW$STARTLOGIN * (Star is a comment line):6 132.64.254.12 NCD19.CC.HUJI.AC.IL TCPIP7 132.64.254.20 ROSHPI DECNETJ 132.64.254.20 PERICOMM TCPIP DECW_LOGINL If you are using the DW-LOGIN mechanism for some station then its DECnet; name must appear here and the mechanism must be DECnet.0Bugs should be reported to YEHAVI@VMS.HUJI.AC.IL"*[SYSUTIL.DECW_LOGIN]COMPILE.COM;10+, ./ 4P-i0123KPWO56)8f7^9f89 <^fGHJ$ CC_PREF :== "/PREFIX=(ALL,EXCEPT=(SOCKET,CONNECT,BIND,LISTEN,SOCKET_READ,SOCKET_WRITE,SOCKET_CLOSE,SELECT,ACCEPT,BCMP,BCOPY,BZERO,GETHOSTBYNAME,"s$ CC_PREF = CC_PREF + "GETHOSTBYADDR,GETPEERNAME,GETDTABLESIZE,HTONS,HTONL,NTOHS,NTOHL,SEND,SENDTO,RECV,RECVFROM))"9$ CC/STANDARD=VAXC'CC_PREF'/NOMEMBER_ALIGN tftp_mn_server$ EXIT&*[SYSUTIL.DECW_LOGIN]DECW$ANNOUNCE.C;12+,.!/ 4S!-i0123KPWO"56w' 7 ' 89R GHJ>P/* DECW$ANNOUNCE - Displays our banner on the login screen. It will also display? the text of the welcome message at the bottom of the screen.+ Invoked by SYS$MANAGER:DECW$ANNOUNCE.COM Link with the commands:& $ LINK decw$announce,SYS$INPUT:/OPT! SYS$SHARE:DECW$XLIBSHR/SHARE SYS$SHARE:VAXCRTL/SHARE*/#include #include "DECW$INCLUDE:x.h"#include "DECW$INCLUDE:xlib.h"#include "DECW$INCLUDE:xutil.h"#define WINDOW_WIDTH 800 #define MESSAGE_WINDOW_WIDTH 800#define WINDOW_HEIGHT 250A#define WELCOME_LINES 32 /* Max number of lines in WELCOME.TXT */S#define WELCOME_FILE "$1$DUA34:[COMMON]WELCOME.TXT" /* Where the welcome file is */=#define LINE_HEIGHT 20 /* Each text line is 20 pixels high */(/* Our logo bitmap (Created by Paint) */#define HULOGO_width 100#define HULOGO_height 100#define HULOGO_x_hot 0#define HULOGO_y_hot 0static char HULOGO_bits[] = {J 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x0c,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,J 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x7c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x7c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x7c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xfc, 0x1c, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0x18, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x18, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,J 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,J 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,J 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0xe0, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0xe0, 0x00, 0x00, 0x80, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0xe0, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xe0, 0xff, 0x01, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xe0, 0xff, 0x01,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf0, 0xff,J 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf8,J 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00,J 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,J 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,J 0x00, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0xe0, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0xe0, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0xe0, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x80, 0x00, 0x00,J 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0xc0, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x80, 0xff, 0xff, 0x0f, 0x00, 0xe0,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff, 0x1f, 0x00,J 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff, 0x1f,J 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xe0, 0xff, 0xff,J 0x1f, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xe0, 0xff,J 0xff, 0x1f, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xf0,J 0xff, 0xff, 0x3f, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,J 0xf0, 0xff, 0xfe, 0x3f, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,J 0x00, 0xf8, 0xff, 0xfc, 0x3f, 0xc0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,J 0xe0, 0x00, 0xf8, 0x7f, 0xf8, 0x7f, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00,J 0x00, 0xe0, 0x00, 0xfc, 0x3f, 0xf8, 0x7f, 0xf0, 0x1f, 0x00, 0x00, 0x00,J 0x00, 0x00, 0xe0, 0x00, 0xfc, 0x3f, 0xf0, 0x7f, 0xf8, 0x0f, 0x00, 0x00,J 0x00, 0x00, 0x00, 0xe0, 0x00, 0xfe, 0x1f, 0xe0, 0xff, 0xfc, 0x07, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xfe, 0x0f, 0xe0, 0xff, 0xff, 0x03,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, 0x0f, 0xc0, 0xff, 0xff,J 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xff, 0x07, 0xc0, 0xff,J 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x80, 0xff, 0x03, 0x80,J 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x80, 0xff, 0x01,J 0x80, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc0, 0xff,J 0x01, 0x00, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xc0,J 0xff, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,J 0xc0, 0xff, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0xe0, 0xe0, 0x7f, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0xe0, 0xe0, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0xe0, 0xf0, 0x3f, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0xe0, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0x0f, 0x00, 0x00, 0xf8, 0x0f, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x0f,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0x07, 0x00, 0x00, 0xf0,J 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfc, 0x03, 0x00, 0x00,J 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xfe, 0x01, 0x00,J 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x01,J 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,J 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,J 0x7f, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x3c,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00,J 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00,J 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,J 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};Display *DisplayId;main(){ char line[1024];> int i, ByteOrder, BitOrder, /* So we know how to send data */@ yDisplayHeight, yDisplayWidth, /* Size of display in pixels */7 BLACKpixelValue, WhitePixelValue, /* Pixels values */9 RedPixel, BluePixel, GreenPixel, PinkPixel, BLACKpixel,% status; /* Function status code */0 Window WindowId, ParentWindow, MessageWindowId;/ XWMHints Hints; /* How to create the window */Q XSetWindowAttributes WindowAttributes; /* Window attributes when creating it */ XSizeHints SizeHints;8 XGCValues GCcontext; /* What graphic context we want */ GC GCid; Cursor CursorId; XEvent Event;+ XColor ExactColor, WhiteColor, BlackColor; Colormap DefaultColorMap; Font FontId; Pixmap LogoBitmap; int Return1[128], Return2[128];/* For the Welcome message */ int MessageWindowHeight, count;D char *p, WelcomeText[WELCOME_LINES][256]; /* Store here the text */ FILE *ifd;K sleep(10); /* Wait for the login program to show its face before we do */+/* OPen a channel to the display station *// if((DisplayId = XOpenDisplay(NULL)) == NULL) {* printf("Can't open display\n"); exit(1); }/ yDisplayHeight = XDisplayHeight(DisplayId, 0);- yDisplayWidth = XDisplayWidth(DisplayId, 0);- WhitePixelValue = XWhitePixel(DisplayId, 0);- BLACKpixelValue = XBlackPixel(DisplayId, 0);! GCid = XDefaultGC(DisplayId, 0);/* Create a window */. ParentWindow = XDefaultRootWindow(DisplayId);/* Set its attributes */) WindowAttributes.backing_store = Always;( WindowAttributes.override_redirect = 1;3 WindowId = XCreateWindow(DisplayId, ParentWindow, C (yDisplayWidth / 2) - (WINDOW_WIDTH / 2), 10, /* X, Y location */ WINDOW_WIDTH, WINDOW_HEIGHT, 1,. CopyFromParent, InputOutput, CopyFromParent,( (CWBackingStore | CWOverrideRedirect), &WindowAttributes);" XselectInput(DisplayId, WindowId,$ (ButtonPressMask | ExposureMask));/* Set its attributes */ Hints.flags = StateHint;# Hints.initial_state = NormalState;D status = XSetStandardProperties(DisplayId, WindowId, "Test Window",' "TestWindow", None, NULL, 0, &Hints); SizeHints.width = WINDOW_WIDTH;" SizeHints.height = WINDOW_HEIGHT; SizeHints.flags = PSize;2 XSetNormalHints(DisplayId, WindowId, &SizeHints);' XSetFunction(DisplayId, GCid, GXcopy);3 status = XSetWindowBackground(DisplayId, WindowId, GCid->values.background);) status = XSetBackground(DisplayId, GCid, GCid->values.background);) status = XSetForeground(DisplayId, GCid, GCid->values.foreground);& BLACKpixel = GCid->values.foreground;* status = XMapRaised(DisplayId, WindowId);2 DefaultColorMap = XDefaultColormap(DisplayId, 0);. XInstallColormap(DisplayId, DefaultColorMap);L FontId = XLoadFont(DisplayId, "-*-David-bold-*-Normal--*-240-*-iso8859-8");# XSetFont(DisplayId, GCid, FontId);, status = XClearWindow(DisplayId, WindowId);K XSetLineAttributes(DisplayId, GCid, 10, LineSolid, CapNotLast, JoinRound);. sprintf(line, " ");5 status = XDrawImageString(DisplayId, WindowId, GCid, 200, 30, /* X, Y */ line, strlen(line)); sprintf(line, " ");5 status = XDrawImageString(DisplayId, WindowId, GCid, 270, 70, /* X, Y */ line, strlen(line));L FontId = XLoadFont(DisplayId, "-*-David-bold-o-Normal--*-240-*-iso8859-8");# XSetFont(DisplayId, GCid, FontId); sprintf(line, "");5 status = XDrawImageString(DisplayId, WindowId, GCid, 350, 150, /* X, Y */ line, strlen(line));, sprintf(line, "HUJIVMS (VMS.Huji.Ac.Il)");5 status = XDrawImageString(DisplayId, WindowId, GCid, 220, 200, /* X, Y */ line, strlen(line));/* Draw the university logo */E LogoBitmap = XCreateBitmapFromData(DisplayId, WindowId, HULOGO_bits, HULOGO_width, HULOGO_height);8 XCopyPlane(DisplayId, LogoBitmap, WindowId, GCid, 0, 0,, HULOGO_width, HULOGO_height, 100, 100, 1); XFlush(DisplayId);#/* Now, draw the welcome message *//* First - read the file */B if((ifd = fopen(WELCOME_FILE, "r")) == NULL) /* No file - skip */ goto NoWelcome; count = 0;H while(fgets(WelcomeText[count], sizeof(WelcomeText[0]), ifd) != NULL) {? if((p = strchr(WelcomeText[count], '\n')) != NULL) *p = '\0'; count++; } fclose(ifd); /* Calculate the height of it */+ MessageWindowHeight = count * LINE_HEIGHT;) WindowAttributes.backing_store = Always;( WindowAttributes.override_redirect = 1;9 MessageWindowId = XCreateWindow(DisplayId, ParentWindow,; (yDisplayWidth / 2) - (MESSAGE_WINDOW_WIDTH / 2), /* X */1 (yDisplayHeight - MessageWindowHeight), /* Y *// MESSAGE_WINDOW_WIDTH, MessageWindowHeight, 1,. CopyFromParent, InputOutput, CopyFromParent,( (CWBackingStore | CWOverrideRedirect), &WindowAttributes);) XselectInput(DisplayId, MessageWindowId,$ (ButtonPressMask | ExposureMask));/* Set its attributes */ Hints.flags = StateHint;# Hints.initial_state = NormalState;N status = XSetStandardProperties(DisplayId, MessageWindowId, "Message Window",* "MessageWindow", None, NULL, 0, &Hints);: status = XSetWindowBackground(DisplayId, MessageWindowId, GCid->values.background);1 status = XMapRaised(DisplayId, MessageWindowId);C FontId = XLoadFont(DisplayId, "-*-courier-*-r-Normal--*-120-*-*");# XSetFont(DisplayId, GCid, FontId);3 status = XClearWindow(DisplayId, MessageWindowId); for(i = 0; i < count; i++) {= status = XDrawImageString(DisplayId, MessageWindowId, GCid, 10, (i + 1) * LINE_HEIGHT,+ WelcomeText[i], strlen(WelcomeText[i])); }$/* Now wait for event to go home. */ NoWelcome: for(;;) { XNextEvent(DisplayId, &Event); /* Do not exit on expose */5 if((Event.type != 12) && (Event.type != 14)) break; }0 XUninstallColormap(DisplayId, DefaultColorMap);/* Unmap the window */# XUnMapWindow(DisplayId, WindowId);/* Delete the window */% XDestroyWindow(DisplayId, WindowId);0/* Disconnect the link to the display station */ XCloseDisplay(DisplayId);} wait_button(){ XEvent Event; XFlush(DisplayId); for(;;) { XNextEvent(DisplayId, &Event);) printf("Event type: %d\n", Event.type); if(Event.type == 12) {3 printf("Expose: place: %d, %d; size: %d x %d\n",$ Event.xexpose.x, Event.xexpose.y,. Event.xexpose.width, Event.xexpose.height);D/* XDrawImageString(DisplayId, WindowId, GCid, 50, 50, "Test", 4);: XDrawLine(DisplayId, WindowId, GCid, 10,10, 50, 50); */ } if(Event.type == 4) break; }}'*[SYSUTIL.DECW_LOGIN]DECW$ANNOUNCE.OBJ;1+,v @. / 4  -i0123KPWO 56^o7{o89o^GHJ: DECW$ANNOUNCEV1.0 6-MAR-1994 11:52VAX C V3.2-044PPP*P7PDPQP<^P< kP<xP<P|P|P|PPPPPPP<P<PP>PP~P PPP!P$P.P1P;P>PHPKPUPXPbPePoPrP|PPPPPPPPPPPPPPPPPPPPPPPPPPP P PPPPP%P'P?,P2P4P??PAP?LPNP?YP[P?fPhP?sPuPPPPPPPPP?PPPPPPPPP?PP?PPPP!P)P.P6P;PCPHPPPUP]PbPjPoPwP|P?PP?P?P?PPPP~PP~PP<PPPPPPPP P~-P>:PGPSP`PmPzPPPPPpPxP8P8PPPCan't open display PTest Window PTestWindow+P-*-David-bold-*-Normal--*-240-*-iso8859-8UP qP ~P-*-David-bold-o-Normal--*-240-*-iso8859-8XSETSTANDARDPROPERTIESXSETNORMALHINTSXUNINSTALLCOLORMAPXSETWINDOWBACKGROUNDXSETLINEATTRIBUTES XSETFUNCTIONXSETFOREGROUNDXSETFONTXSETBACKGROUND XNEXTEVENT XMAPRAISEDXINSTALLCOLORMAPXFLUSHXDRAWIMAGESTRING XDISPLAYWIDTHXDISPLAYHEIGHTXDESTROYWINDOW XCOPYPLANE XCLOSEDISPLAY XCLEARWINDOWXDEFAULTCOLORMAP XWHITEPIXEL XBLACKPIXEL XDEFAULTGCXDEFAULTROOTWINDOWPPHUJIVMS (VMS.Huji.Ac.Il)P$1$DUA34:[COMMON]WELCOME.TXTPrPMessage WindowPMessageWindowP-*-courier-*-r-Normal--*-120-*-*%PEvent type: %d 5PExpose: place: %d, %d; size: %d x %d P^C$MAINVU SLEEP XOPENDISPLAYPefPRINTFEXITeXDISPLAYHEIGHTPne XDISPLAYWIDTHP[e XWHITEPIXELe XBLACKPIXELe XDEFAULTGCPWeXDEFAULTROOTWINDOWPʹ͜<@~~< ~ [RpR~ݮ0e XCREATEWINDOWPY<~Ye XSELECTINPUT|~ߦ ߦYeXSETSTANDARDPROPERTIES< `dTTYeXSETNORMALHINTSWe XSETFUNCTIONݧ YeXSETWINDOWBACKGROUNDPRݧ WeXSETBACKGROUNDPRݧWeXSETFOREGROUNDPRYe XMAPRAISEDPReXDEFAULTCOLORMAPPݮeXINSTALLCOLORMAPߦ+e XLOADFONTPZZWeXSETFONTYe XCLEARWINDOW|~ WeXSETLINEATTRIBUTESߦUSPRINTFTdSTRLENScP~WYeXDRAWIMAGESTRINGRbߦqdcPF~<~WYebߦ~e XLOADFONTPZZWeXSETFONTƨdcP~<^~WYebƮdcP~~WYebd~d~YeXCREATEBITMAPFROMDATAP\d~d~d~d~|~WY\e XCOPYPLANEeXFLUSHFOPENPS1aTS<~xTRBFGETSP7P xT\LSTRCHRP`TS<~xT\LFGETSPSFCLOSETRʹ͜<@~R< ~R ~[RpR~ݮ0e XCREATEWINDOWPX<~Xe XSELECTINPUT|~XeXSETSTANDARDPROPERTIESPRݧ XeXSETWINDOWBACKGROUNDPRXe XMAPRAISEDPRe XLOADFONTPZZWeXSETFONTXe XCLEARWINDOWST9PxS\L\lSTRLENPlSRR~ WXeXDRAWIMAGESTRINGRSSTʟe XNEXTEVENT ݮeXUNINSTALLCOLORMAPYe XUNMAPWINDOWYeXDESTROYWINDOWe XCLOSEDISPLAYPΜ^\R)R DECW$ANNOUNCE main wait_button^ Źx XCREATEWINDOWXCREATEBITMAPFROMDATA XLOADFONT XOPENDISPLAYSPRINTFPRINTFFGETSFCLOSEFOPEN XUNMAPWINDOWSTRCHRSTRLEN XSELECTINPUTEXIT SLEEP MAIN  WAIT_BUTTONC$MAIN$CODE$DATASTDINSTDOUTSTDERR DISPLAYID[$CHAR_STRING_CONSTANTS\XFLUSHb XNEXTEVENTݭ%PRINTFѭ ݭݭݭݭ5PRINTFѭ#*[SYSUTIL.DECW_LOGIN]DECW_LOGIN.C;79+,i.$/ 4f$$ -i0123KPWO%56@ 72 89`0vGHJ/* LOGIN.C V-1.3M | This program is used instead of DECW$STARTLOGIN untill there is a solutionH | for it; when there is a solution change XDMCP to run DECW$START_LOGINI | instead of this program. Note that the routine to read user's input is- | very simple, has no cursor or delete, etc.C | The information about the manageable displays is in SYS$MANAGER:> | XDISPLAYS.DAT; its format is described in TFTP_MN_SERVER.C;, | This login program will do the following:J | 1. Ask for username and password. Verify them, and if correct will keep | its window open and:M | 2. Submits a command procedure using the username of the user who wants toI | login. This procedure will run DECW$SESSION and exit after a while.E | 3. Exit, thus closing all connections to this display. The displayB | will restart XDM and a solution to it is described in XDMCP. |? | Compile with /DEFINE=DEBUG if debugging messages are needed. | Link with:& | $ LINK DECW_LOGIN,SYS$INPUT:/OPTION | SYS$SHARE:XLIBSHR/SHARE | SYS$SHARE:VAXCRTL/SHARE |C | To run it define it as foreign DCL command and then start it as:< | $ DECW_LOGIN Xdisplay-name Dotted-IP-address-of-display | for example:6 | $ DECW_LOGIN ROSH-PINA.CC.HUJI.AC.IL 132.64.254.20 |P | V1.1 (22/4/91) - Once a minute try creating a new connection to the terminal.N | If unsuccessfull then the terminal was probably switched off. Exit the& | program and free the terminal.I | V1.2 (23/4/91) - Once a minute try openning an TCPIP connection to theL | Xterminal's TELNET port. This connection should be refused. However,O | if we get timeout we conclude that the terminal was turned off and thusP | should be freed and be ready for a new XDM request. If we don't do it we4 | won't find that the terminal was turned off.L | V1.3 (17.9.92) - Modify it for Pericomm terminals. Do not close the loginK | window but instead shrink it to a minimal one. Closing it will drop | the session. */#include #include #include #include "DECW$INCLUDE:x.h"#include "DECW$INCLUDE:xlib.h"#include "DECW$INCLUDE:xutil.h":#include "multinet_root:[multinet.include.vms]inetiodef.h"6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"2#include "multinet_root:[multinet.include]netdb.h"!/* To be changed at each node: */@#define HOST "HUJIVMS" /* The server's name (for info only) */`#define COMMAND_FILE "UTIL$:DECW_LOGIN.COM" /* The procedure to submit upon successfull login */9#define QUEUE_NAME "SYS$BIG" /* Queue to submit it to */#define LINESIZE 256"/* The prompt window parameters */Display *DisplayId;Window WindowId, ParentWindow;GC GCid; Font FontId;#define WINDOW_X 200#define WINDOW_Y 350#define WINDOW_WIDTH 800#define WINDOW_HEIGHT 200%/* Flags for read: Echo or no echo */#define ECHO 0#define NO_ECHO 1/* String descriptor */ struct DESC {# short length, /* String length */! type; /* Its class and type *// char *address; /* The address of the string */};Qchar TopMessage[LINESIZE]; /* Print this message at the head of the dialog box */L/* For MultiNet to try once a minute to make a connection to the terminal to check whether it is alive. */Uchar InterNetAddress[LINESIZE]; /* InterNet address of the display (dotted format) */Nshort MnetChannel, iosb[4]; /* Channel (global due to use of AST routines) */9#define IPPORT 23 /* TELNET port - should be refused */<struct sockaddr_in { /* IP connection request structure */ short sa_family; /* family */* unsigned short sa_port; /* port number */. unsigned long sa_addr; /* Internet address */* char sa_zero[8]; /* unused, must be 0 */}; main(cc, vv) char **vv;{A char Username[LINESIZE], Password[LINESIZE], line[LINESIZE], *p,# DisplayName[LINESIZE], *HostName;C unsigned long EncryptedPassword[2], /* The password from SYSUAF */A UserEncryptedPassword[2], /* The user's given one encrypted */) PwdSalt, /* Salt used for password */0 EncryptionAlgorithm; /* The algorithm used */ int i, status;( struct DESC PasswordDesc, UsernameDesc; struct ITEM_LIST { short length, code; char *address, *ReturnAddress;. } ItemList[10]; /* For submitting the job */ Display *NewDisplayId; XEvent Event;/* Get the display name */ if(cc != 3) {5 printf("Only two parameters are legal\n"); exit(2); }2 strncpy(DisplayName, vv[1], sizeof(DisplayName));U DisplayName[LINESIZE - 1] = '\0'; /* Over paranoid to prevent access violation... */: strncpy(InterNetAddress, vv[2], sizeof(InterNetAddress));& InterNetAddress[LINESIZE - 1] = '\0';N/* Prepare the message to appear at the head of the login box. Try getting our; Internet name. If not found, use the pre-defined one. */5 if((HostName = getenv("ARPANET_HOST_NAME")) == NULL)2 if((HostName = getenv("UCX$INET_HOST")) == NULL) HostName = HOST;8 sprintf(TopMessage, "%s on %s", HostName, DisplayName);/* Init the window first */ if(init_window(NULL) != 1)' exit(4); /* Can't open the display */I init_timer(); /* A timer to check periodically the terminal's status */H/* Prompt for username, read it, then prompt for password and read it */ PromptAgain: sprintf(line, "Username: ");3 print_message(line); /* Write it on the screen */0 read_message(Username, sizeof(Username), ECHO);Q Username[LINESIZE - 1] = '\0'; /* Delimit it so we won't access violate on it */ print_message("Password: ");3 read_message(Password, sizeof(Password), NO_ECHO);Q Password[LINESIZE - 1] = '\0'; /* Delimit it so we won't access violate on it */I if((strlen(Username) == 0) || (strlen(Password) == 0)) goto PromptAgain;'/* Convert the username to uppercase */& for(p = Username; *p != '\0'; *p++) {+ if(*p == '\0') break; /* End of string */ if((*p >= 'a') && (*p <= 'z'))2 *p -= ' '; /* Convert uppercase to lowercase */ else if((*p < ' ') || (*p > 'z'))2 *p = ' '; /* Non-printable, convert to space */ }'/* Convert the Password to uppercase */& for(p = Password; *p != '\0'; *p++) {+ if(*p == '\0') break; /* End of string */ if((*p >= 'a') && (*p <= 'z'))2 *p -= ' '; /* Convert uppercase to lowercase */ else if((*p < ' ') || (*p > 'z'))2 *p = ' '; /* Non-printable, convert to space */ }'/* Get the user's entry from SYSUAF. */: if(get_user_record(Username, EncryptedPassword, &PwdSalt, &EncryptionAlgorithm) == 0) goto PromptAgain;H/* OK, we have this user. Now hash the given password and compare to the one in SYSUAF */I UsernameDesc.address = Username; UsernameDesc.length = strlen(Username);I PasswordDesc.address = Password; PasswordDesc.length = strlen(Password);+ PasswordDesc.type = UsernameDesc.type = 0;? status = sys$hash_password(&PasswordDesc, EncryptionAlgorithm,2 PwdSalt, &UsernameDesc, UserEncryptedPassword); if((status & 0x1) == 0) { #ifdef DEBUG7 printf("Can't encypt password, status=%d\n", status);#endif goto PromptAgain; }/* Verify passwords */9 if((UserEncryptedPassword[0] != EncryptedPassword[0]) ||7 (UserEncryptedPassword[1] != EncryptedPassword[1]))* goto PromptAgain; /* Illegal password */$/* OK, submit a job for this user */, ItemList[0].code = SJC$_FILE_SPECIFICATION;+ ItemList[0].length = strlen(COMMAND_FILE);$ ItemList[0].address = COMMAND_FILE; ItemList[0].ReturnAddress = 0; ItemList[1].code = SJC$_QUEUE;) ItemList[1].length = strlen(QUEUE_NAME);! ItemList[1].address= QUEUE_NAME; ItemList[1].ReturnAddress = 0;E/* The parameter of the job is the display name from XDISPLAYS.DAT */% ItemList[2].code = SJC$_PARAMETER_1;* ItemList[2].length = strlen(DisplayName);B ItemList[2].address = DisplayName; ItemList[2].ReturnAddress = 0;" ItemList[3].code = SJC$_USERNAME;' ItemList[3].length = strlen(Username);? ItemList[3].address = Username; ItemList[3].ReturnAddress = 0;"/* Have no logfile for this job */. ItemList[4].code = SJC$_NO_LOG_SPECIFICATION; ItemList[4].length = 0;? ItemList[4].address = Username; ItemList[4].ReturnAddress = 0;= ItemList[5].code = ItemList[5].length = 0; /* End of list */= status = sys$sndjbcw(0,SJC$_ENTER_FILE,0,ItemList,iosb,0,0);6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) { #ifdef DEBUG. printf("$SNDJBC: %d %d\n", status, iosb[0]);#endif exit(status); }./* Free the keyboard for other applications */) XUngrabKeyboard(DisplayId, CurrentTime);: XMoveResizeWindow(DisplayId, WindowId, 500, 1, 100, 100); print_message("Wait");)/* XUnmapWindow(DisplayId, WindowId); */ for(;;) { XNextEvent(DisplayId, &Event); if(Event.type == Expose) { print_message("Logout..."); } } exit(1); /* Normal exit */}/*M | Open a window on the given display. Paint our login box, grab the keyboard/ | and return, load the needed font and return. */init_window(DisplayName)char *DisplayName;{/ XWMHints Hints; /* How to create the window */Q XSetWindowAttributes WindowAttributes; /* Window attributes when creating it */ XSizeHints SizeHints;+/* OPen a channel to the display station */6 if((DisplayId = XOpenDisplay(DisplayName)) == NULL) {+ printf("Can't open display\n"); return 0; }G GCid = XDefaultGC(DisplayId, 0); /* Use the default Graphic Context *//* Create a window */. ParentWindow = XDefaultRootWindow(DisplayId);/* Set its attributes */) WindowAttributes.backing_store = Always;D WindowAttributes.override_redirect = 1; /* No window manager yet */2 WindowId = XCreateWindow(DisplayId, ParentWindow,9 (XDisplayWidth(DisplayId, 0) / 2) - (WINDOW_WIDTH / 2),+ WINDOW_Y, WINDOW_WIDTH, WINDOW_HEIGHT, 1,. CopyFromParent, InputOutput, CopyFromParent, (CWBackingStore), &WindowAttributes);" XselectInput(DisplayId, WindowId,3 (KeyPressMask | ButtonPressMask | ExposureMask));/* Set its attributes */ Hints.flags = StateHint;# Hints.initial_state = NormalState;< XSetStandardProperties(DisplayId, WindowId, "Login Window",( "LoginWindow", None, NULL, 0, &Hints);8/* Set background and foreground to display's default */' XSetFunction(DisplayId, GCid, GXcopy);D XSetWindowBackground(DisplayId, WindowId, GCid->values.background);: XSetBackground(DisplayId, GCid, GCid->values.background);: XSetForeground(DisplayId, GCid, GCid->values.foreground);! XMapRaised(DisplayId, WindowId); /* Load a Courier bolded font */T FontId = XLoadFont(DisplayId, "-*-courier-bold-r-normal--*-180-*-*-*-*-iso8859-1");# XSetFont(DisplayId, GCid, FontId);# XClearWindow(DisplayId, WindowId); XFlush(DisplayId);,/* Get all keyboard events pointing to us */D XGrabKeyboard(DisplayId, WindowId, 0, GrabModeAsync, GrabModeAsync, CurrentTime); return 1;}/*G | Write a message on the screen - clear it, write again the TopMessage- | and then the message we want to print now. */print_message(string){# XClearWindow(DisplayId, WindowId);4 XDrawImageString(DisplayId, WindowId, GCid, 10, 50," TopMessage, strlen(TopMessage));5 XDrawImageString(DisplayId, WindowId, GCid, 10, 150, string, strlen(string));' XFlush(DisplayId); /* To display it */}/*I | Read a message - Wait for a keyboard event. If it is KeyPress parse itM | and append to output string. If found in it then cut the string there | and return. */$read_message(String, size, EchoFlag)-char *String; /* Buffer to return data in */%int size, /* Size of that buffer */ EchoFlag;{ XEvent Event; int i, SizeRead; char *p; SizeRead = 0; for(;;) { XNextEvent(DisplayId, &Event); if(Event.type == KeyPress) {D if(SizeRead >= (size - 1)) { /* Overflow - return empty string */ *String = '\0'; return; }$/* Translate the KeyCode to ASCII */7 SizeRead += XLookupString(&Event, &String[SizeRead],! size - SizeRead, NULL, NULL);, String[SizeRead] = '\0'; /* For StrChr */? if((p = strchr(String, '\r')) != NULL) { /* End of string */ *p = '\0'; return; };/* If echo eas requested then draw this string somewhere */ if(EchoFlag == ECHO)/ XDrawImageString(DisplayId, WindowId, GCid, 200, 150, String, SizeRead); } }}/*F | Get the user's entry and return his encrypted password. If the userK | has more than one password return error as we allow only single password | accounts here.% | Return 1 if success, 0 otherwise. */Jget_user_record(Username, EncryptedPassword, PwdSalt, EncryptionAlgorithm)char *Username;<long *EncryptedPassword, /* Must point to QuadWord buffer */. *PwdSalt, /* the salt used for encryption */C *EncryptionAlgorithm; /* THe algorithm used to encrypt password */{f long i, status, SecondaryEncryptedPassword[2]; /* So we know whether there is a secondary password */ struct DESC UsernameDesc; struct ITEM_LIST { short length, code; char *address, *ReturnAddress; } ItemList[] = {' 8, UAI$_PWD, EncryptedPassword, NULL,1 8, UAI$_PWD2, SecondaryEncryptedPassword, NULL, 2, UAI$_SALT, PwdSalt, NULL,- 1, UAI$_ENCRYPT, EncryptionAlgorithm, NULL," 0, 0, 0, NULL /* End of list */ };/* Create a VMS descriptor */I UsernameDesc.address = Username; UsernameDesc.length = strlen(Username); UsernameDesc.type = 0;? *PwdSalt = 0; /* It is longword and only a word will be set */L status = sys$getuai(NULL, NULL, &UsernameDesc, ItemList, NULL, NULL, NULL); if((status & 0x1) == 0) { #ifdef DEBUG; printf("GET UAI status %d for '%s'\n", status, Username);#endif return 0; }2/* Check whether secondary password is not null */+ if((SecondaryEncryptedPassword[0] != 0) ||+ (SecondaryEncryptedPassword[1] != 0)) { #ifdef DEBUG< printf("Account '%s' has secondary password\n", Username);#endif return 0; } /* All ok */ return 1;}/*L | Set a timer to tick once every minute so we check whether the terminal is | still alive. */static long DeltaTime[2]; init_timer(){ long i, status, timer_ast();= struct DESC TimeDesc; /* The time descriptor for 1 second */5 char OneMinute[] = "0 00:01:00.00"; /* One Minute */ /* Convert the time to binary */C TimeDesc.address = OneMinute; TimeDesc.length = strlen(OneMinute); TimeDesc.type = 0;+ status = sys$bintim(&TimeDesc, DeltaTime); if((status & 0x1) == 0) {9 printf("VMS, Can't convert time, status=%d\n", status); exit(status); } /* Now queue the periodic AST */L status = sys$setimr((long)(0), DeltaTime, timer_ast, (long)(0), (long)(0)); if((status & 0x1) == 0) {? printf("VMS, Can't schedule timer AST, status=%d\n", status); exit(status); }}/*L | Check whether a new connection can be made to this terminal. If so, queueP | us to check at the next minute again. If we can't open it then it is probably= | turned off. Thus, exit the program and free this terminal.N | We must use "raw" TCP as using XOpenDisplay() will fail because the display- | is already opened for another XDM session. */ timer_ast(){, struct sockaddr_in MNsocket; /* MultiNet */4 char DevName[] = "INET0:"; /* MultiNet's device. */ struct { /* Descriptor */ short length; short filler; char *address; } Device;, long i, status, timer_ast(), connect_ast();"/* Assign a channel to MultiNet */; Device.address = DevName; Device.length = strlen(DevName); Device.filler = 0;0 if(((status = sys$assign(&Device, &MnetChannel,' (long)(0), (long)(0))) & 0x1) == 0) {; printf("Can't assign channel to %s: $ASSIGn status=%d\n", DevName, status);) exit(status); /* Multinet is down??? */ }/* Request a local socket */? status = sys$qiow((long)(0), MnetChannel, (short)(IO$_SOCKET), iosb, (long)(0), (long)(0),3 (int)(AF_INET), (int)(SOCK_STREAM), (long)(0),& (long)(0), (long)(0), (long)(0));6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {J printf("Requesting local socket error: $QIOW status=d^%d, errno=d^%d\n", status, iosb[0]);1 sys$dassgn(MnetChannel); /* Deassign channel */ if((status & 0x1) == 0) exit(status); else exit(iosb[0]);g } /* Remote socket */ MNsocket.sa_family = AF_INET;, MNsocket.sa_port = ((IPPORT & 0xff) << 8) | ((IPPORT >> 8) & 0xff);G9 MNsocket.sa_addr = internet_to_integer(InterNetAddress);a? status = sys$qio((long)(0), MnetChannel, (short)(IO$_CONNECT), iosb, connect_ast, 0,e5 &MNsocket, sizeof(struct sockaddr_in), (long)(0),D% (long)(0), (long)(0), (long)(0));S if((status & 0x1) == 0) {K printf("Requesting remote socket error: address(%s), $QIO status=d^%d\n",  InterNetAddress, status);1 sys$dassgn(MnetChannel); /* Deassign channel */c exit(status);s }#/* Now re-queue the periodic AST */iL status = sys$setimr((long)(0), DeltaTime, timer_ast, (long)(0), (long)(0)); if((status & 0x1) == 0) {A printf("VMS, Can't reschedule timer AST, status=%d\n", status);o exit(status);b }}D/*L | This AST is fired when the connection is done or fails. If the IP code isK | 61 then the terminal refused us and we know it is alive. All others will/ | cause us to think it is dead and to drop it.f */t connect_ast() {m long i;8 i = ((iosb[0] & 0x7fff) / 8); /* Get the "Unix" code */: sys$dassgn(MnetChannel); /* We have to close it anyway */. if(i != 61) { /* The screen is dead - exit */ exit(4); }:/* In all other cases the screen is alive so do nothing */}f/*J | Convert a string of 4 dotted decimal numbers into an integer, reversing) | the bytes order, as the EXOS requires. ' | If illegal numbers found - return 0.n */n$internet_to_integer(InterNetAddress)char *InterNetAddress;{  long A,B,C,D, status;A status = sscanf(InterNetAddress, "%d.%d.%d.%d", &A, &B, &C, &D);a+ if(status < 4) return 0; /* Some error */y. return((D << 24) + (C << 16) + (B << 8) + A);} won't find that the terminal was turned off.L | V1.3 (17.9.92) - Modify it for Pericomm terminals. Do not close the loginK | window but instead shrink it to a minimal one. Closing it will drop | the session. */#include $ WAIT 00:00:02 ! Wait 2 seconds for window manager to start.2$ INFORM_XDMCP_LOGIN :== $UTIL$:INFORM_XDMCP_LOGIN$ INFORM_XDMCP_LOGIN 'P1'$ RUN SYS$SYSTEM:DECW$SESSION$ SET DISPLAY/DELETE$ exit)*[SYSUTIL.DECW_LOGIN]INFORM_TFTP_LOGIN.C;2+,0!./ 4LX-i0123KPWO567F7-u89@øFwGHJ B/* INFORM_TFTP_LOGIN - Inform TFTP server to start a login window. */#include #include #include #include :#include "multinet_root:[multinet.include.vms]inetiodef.h"6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"2#include "multinet_root:[multinet.include]netdb.h"#define LINESIZE 256##define MAILBOX_NAME "YNCD_MAILBOX" struct DESC { short length, type; char *address;};main(){# char RemoteNodeName[LINESIZE], *p, *TTname = "TT:"; int length, channel, status; struct DESC TT; struct { short length, code; char *address, *ReturnLength; } GetDviList[] = { sizeof RemoteNodeName,/ DVI$_TT_ACCPORNAM, RemoteNodeName, &length, 0, 0, NULL, NULL };C/* Assign a channel to the terminal and get the remote port name */1 TT.address = TTname; TT.length = strlen(TTname); TT.type = 0;( if(((status = sys$assign(&TT, &channel,' (long)(0), (long)(0))) & 0x1) == 0) {/ printf("Can't assign channel to terminal\n"); exit(status); }'/* Get the MBAnnn: device name of it */= status = sys$getdviw(0, channel, 0, GetDviList, 0, 0, 0, 0); if((status & 0x1) == 0) { printf("Can't get port\n"); exit(status); } RemoteNodeName[length] = '\0';4 sys$dassgn(channel); /* We don;t need it anymore */D/* If it is a DECnet name it includes also the username - drop it */9 if((p = strchr(RemoteNodeName, ':')) != NULL) *p = '\0';/ printf("Remote node: '%s'\n", RemoteNodeName); send_tftp(RemoteNodeName);}send_tftp(RemoteNodeName)char *RemoteNodeName;{ struct DESC MailBoxDesc; int status; short chan, iosb[4];$ MailBoxDesc.address = MAILBOX_NAME;+ MailBoxDesc.length = strlen(MAILBOX_NAME); MailBoxDesc.type = 0;@ status = sys$assign(&MailBoxDesc, &chan, (long)(0), (long)(0)); if((status & 0x1) == 0) {# printf("No server is running\n"); exit(status); }# status = sys$qiow((long)(0), chan, (short)(IO$_WRITEVBLK), iosb, (long)(0), (long)(0),L RemoteNodeName, strlen(RemoteNodeName) + 1, /* +1 to send the null also */ (long)(0),# (long)(0), (long)(0), (long)(0));6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {' printf("server is not responding\n"); exit(status); } sys$dassgn(chan);}**[SYSUTIL.DECW_LOGIN]INFORM_XDMCP_LOGIN.C;1+, ./ 4K-i0123KPWO56tu7)Yu89@øFwGHJ/* INFORM_XDMCP_LOGIN V1.0H | Inform the XDMCP that a session was initiated successfully and it canK | init the data structures for this display for the next session after the | next boot. */#include #include #include #include :#include "multinet_root:[multinet.include.vms]inetiodef.h"6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"2#include "multinet_root:[multinet.include]netdb.h"#define LINESIZE 256%#define MAILBOX_NAME "YXDMCP_MAILBOX" struct DESC { short length, type; char *address;}; main(cc, vv) char **vv;{'/* The parameter is the display name */ if(cc != 2)$ printf("No display name given\n"); else send_xdmcp(vv[1]);}send_xdmcp(DisplayName)char *DisplayName;{ struct DESC MailBoxDesc; int status; short chan, iosb[4];$ MailBoxDesc.address = MAILBOX_NAME;+ MailBoxDesc.length = strlen(MAILBOX_NAME); MailBoxDesc.type = 0;@ status = sys$assign(&MailBoxDesc, &chan, (long)(0), (long)(0)); if((status & 0x1) == 0) {# printf("No server is running\n"); exit(status); }# status = sys$qiow((long)(0), chan, (short)(IO$_WRITEVBLK), iosb, (long)(0), (long)(0),F DisplayName, strlen(DisplayName) + 1, /* +1 to send the null also */ (long)(0),# (long)(0), (long)(0), (long)(0));6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {' printf("server is not responding\n"); exit(status); } sys$dassgn(chan);},*[SYSUTIL.DECW_LOGIN]INFORM_XDMCP_LOGIN.OBJ;1+,t X./ 4 -i0123KPWO56io7@o89o^GHJ?INFORM_XDMCP_LOGINV1.0 6-MAR-1994 11:52VAX C V3.2-044RINFORM_XDMCP_LOGIN main44 send_xdmcp h $(PRINTF SEND_XDMCP SYS$DASSGNSYS$QIOWEXIT SYS$ASSIGNSTRLEN MAIN 4 SEND_XDMCP C$MAIN_ARGS$CODE$DATASTDINSTDOUTSTDERRH_ERRNOH_NERR H_ERRLISTe$CHAR_STRING_CONSTANTSPNo display name given PYXDMCP_MAILBOX&PYXDMCP_MAILBOX5PNo server is running KPserver is not responding P^ C$MAIN_ARGSѬPRINTFЬPݠ SEND_XDMCP2P ^Sޣߣ&STRLENP괭|~? SYS$ASSIGNPRPߣ5PRINTFREXIT|~|~ݬSTRLENPPݬ|~߭02~ SYS$QIOWPRPߣKPRINTFREXIT2~ SYS$DASSGN*[SYSUTIL.DECW_LOGIN]TEST.COM;2+,./ 4\-i0123KPWO56KI>"7k>"89)cGHJ$ CC_PREF :== "/PREFIX=(ALL,EXCEPT=(SOCKET,CONNECT,BIND,LISTEN,SOCKET_READ,SOCKET_WRITE,SOCKET_CLOSE,SELECT,ACCEPT,BCMP,BCOPY,BZERO,GETHOSTBYNAME,"s$ CC_PREF = CC_PREF + "GETHOSTBYADDR,GETPEERNAME,GETDTABLESIZE,HTONS,HTONL,NTOHS,NTOHL,SEND,SENDTO,RECV,RECVFROM))"F$ CC/STANDARD=VAXC'CC_PREF'/NOMEMBER_ALIGN tftp_mn_server/define=debug$ EXIT(*[SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.C;109+,.3/ 4\32-i0123KPWO456Roi7K%i89 GGHJ/* TFTP_MN_SERVER.C V1.3S | This program is intended to download NCD X11 terminals and start a login sessionI | on them. All files are either relative to TFTP_DIRECTORY or must be in | SYS$COMMON:[SYSFONT.DECW...].L | The program accesses for read two trees: One is headed by the directoryN | specified in TFTP_DIRECTORY definition (later in the program) and the other | is SYS$COMMON:[SYSFONT.DECW].N | When a request arrives from the NCDLOGIN username it'll fire a STARTLOGINB | session for the specified terminal (if listed in our database).L | This program runs with SYSNAM privilege in order to access the privilegedN | port and define YNCD_MAILBOX in system's table. It needs CMKRNL in order to! | run the DECW$STARTLOGIN image.K | When starting a station we have a small problem: The WS device createdJ | must not be deleted before the user finishes login. This can be done byH | creating the WS in EXEC mode; this will leave us such devices hangingG | around. The solution is to do it in SUPERVISOR mode, and letting theJ | subprocess which created it to live for 2 minutes. If the user does notK | login during these two minutes he has to reset the terminal or use otherH | way to login. This program must be run with CLI mapped in order to be | able to spawn processes.E | Recommnded way to run it: Crea a file TFTP.COM with the command: | $ RUN TFTP_MN_SERVER' | and then launch it with the command:J | $ RUN/DETACH/INPUT=TFTP.COM/OUTPUT=NL:/ERROR=NL:/SUBPROCESS_LIMIT=10 -5 | /PROCESS_NAME="TFTP_server" SYS$SYSTEM:LOGINOUT |N | Note: The command procedure to create the login banner should be created inL | a place which is pointed by a system wide logical name. The name TEMP$ is | used here. |I | All stations which are allowed to boot and get a login banner from us4 | should be registered in SYS$MANAGER:XDISPLAYS.DATL | The format of this file is (each line which starts with * is a comment):J | IP-address (dotted format) Name Transport for DECW$STARTLOGIN | For example:5 | 128.139.4.100 TEST1.HUJI.AC.IL DECNET4 | 128.139.4.101 TEST2.HUJI.AC.IL TCPIP |O | XDMCP accepts one more optional argument. If there is a 4th argument it willO | run our own login command instead of DEC's one. It is intended for terminals% | that do not accept DEC's loginout. |I | V1.1 - MOve the list of stations allowed from an internal structure to# | SYS$MANAGER:XDISPLAYS.DATT | V1.2 - Add VMS sepcific parameters to the open() command to make the read faster.Q | V1.3 - Do not tie the connection to the station structure but use a connectionL | to IP/port translation. This allows the same terminal to open more. | than one TFTP downloads in parallel. */#include #include #include #include #include #include /* #include */:#include "multinet_root:[multinet.include.vms]inetiodef.h"6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"2#include "multinet_root:[multinet.include]netdb.h"#define LINESIZE 256;#define MAX_DISPLAYS 128 /* Maximum stattions we support */J/* The root of the directory tree used for TFTP access. This should be one; level directory with no traling dot or right bracket. */(#define TFTP_DIRECTORY "$3$dKA200:[TFTP"##define MAILBOX_NAME "YNCD_MAILBOX"H/* The terminals we allow to get the login banner from us. Each containsF two names: The station's name and the protocol (TCPIP or DECNET) */struct ALLOWED_TERMINALS {8 unsigned long InterNetAddress; /* Address of station */6 char name[64]; /* It's name (InterNet or DECnet) */5 char DECwindowsMechanism[64]; /* DECNET or TCPIP */" } AllowedTerminals[MAX_DISPLAYS];=/* Hold the opened TFTP connections and their descriptors. */struct ACTIVE_CONNECTIONS {8 unsigned long InterNetAddress; /* Address of station */B unsigned short InternetPort; /* The IP port at the other side */. int fd, /* File opened for current load */* BlockNum; /* Last block number sent *// int SendSize; /* Size of last buffer sent */= time_t TimeStarted; /* When this connection was started */3 unsigned char buffer[1024]; /* The data itself */# } ActiveConnections[MAX_DISPLAYS];struct sockaddr_in { short sa_family; /* family */* unsigned short sa_port; /* port number */. unsigned long sa_addr; /* Internet address */* char sa_zero[8]; /* unused, must be 0 */};&struct DESC { /* String descriptor */ short length, type; char *address;};#/* For the mailbox AST routines: */short MailBoxChan;C#define SWAP_SHORT(xxx) (((xxx >> 8) & 0xff) | ((xxx & 0xff) << 8))%#define RRQ 1 /* File read request */0#define WRQ 2 /* File write request - Ignored */*#define DATA 3 /* REad next data packet */%#define ACK 4 /* Ack for data read */#define ERROR 5main(){ time_t time(); FILE *fd;B unsigned char buf[1024]; /* set network buffer to be 1K bytes */, char *p, FileName[LINESIZE], *TftpFileName,P Address[LINESIZE], Name[LINESIZE], /* For reading SYS$MANAGER:XDISPLAYS.DAT */ DECwindows[LINESIZE];7 unsigned int A, B, C, D; /* To get IP address parts */ unsigned char OutBuf[1024]; int i, size, request,L CurrentStation; /* Index into ActiveConnections for the current request */= unsigned long StationAddress; /* The address in our order */' unsigned short temp, channel, iosb[4]; char DevName[16]; struct { /* Descriptor */ short length; short filler; char *address; } Device; long status; struct sockaddr_in Socket;/* First - Read our info */= if((fd = fopen("SYS$MANAGER:XDISPLAYS.DAT", "r")) == NULL) {: printf("Can't open SYS$MANAGER:XDISPLAYS.DAT"); exit(1); } i = 0;, while(fgets(buf, sizeof buf, fd) != NULL) { if(i >= MAX_DISPLAYS) {7 printf("MAX_DISPLAYS too low. Raise it\n"); exit(1); }0 if((p = strchr(buf, '\n')) != NULL) *p = '\0';) if(*buf == '*') continue; /* Comment */N if(sscanf(buf, "%s %s %s", Address, Name, DECwindows) == 3) /* Legal line */< if(sscanf(Address, "%d.%d.%d.%d", &A, &B, &C, &D) == 4) {) AllowedTerminals[i].InterNetAddress = (((A << 24) & 0xff000000) | ((B << 16) & 0xff0000) | ((C << 8) & 0xff00) | (D & 0xff));+ strcpy(AllowedTerminals[i].name, Name);3 strcpy(AllowedTerminals[i].DECwindowsMechanism, DECwindows); i++; } } fclose(fd);; AllowedTerminals[i].InterNetAddress = 0; /* End of 0ܨS~ TFTP_XDM.BCKi([SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.C;109\3list */!/* Clear the connections array */$ for(i = 0; i < MAX_DISPLAYS; i++) {+ ActiveConnections[i].InterNetAddress = 0;( ActiveConnections[i].InternetPort = 0;0 ActiveConnections[i].TimeStarted = time(NULL);; ActiveConnections[i].fd = ActiveConnections[i].BlockNum =% ActiveConnections[i].SendSize = 0;& *ActiveConnections[i].buffer = '\0'; } /* Assign a channel to device */ strcpy(DevName, "INET0:");; Device.address = DevName; Device.length = strlen(DevName); channel = 0;, if(((status = sys$assign(&Device, &channel,' (long)(0), (long)(0))) & 0x1) == 0) { sprintf(buf,; "TFTP: Can't assign channel to %s: $ASSIGn status=%d\n", DevName, status); send_opcom(buf); exit(1); } /* Request a local socket */; status = sys$qiow((long)(0), channel, (short)(IO$_SOCKET), iosb, (long)(0), (long)(0),2 (int)(AF_INET), (int)(SOCK_DGRAM), (long)(0),& (long)(0), (long)(0), (long)(0));8 if(((status & 0x1) == 0) || (((iosb)[0] & 0x1) == 0)) { sprintf(buf,/ "TFTP: Requesting local socket error: $QIOW\status=d^%d, errno=d^%d\n", status, (iosb)[0], (((iosb)[0] & 0x7fff) / 8)); send_opcom(buf);- sys$dassgn(channel); /* Deassign channel */ exit(1); } /* Bind a name to it */ Socket.sa_family = AF_INET;! Socket.sa_port = SWAP_SHORT(69);( Socket.sa_addr = 0; /* Local machine */9 status = sys$qiow((long)(0), channel, (short)(IO$_BIND), iosb, (long)(0), (long)(0),) &Socket, sizeof(struct sockaddr_in),/ (long)(0), (long)(0), (long)(0), (long)(0));8 if(((status & 0x1) == 0) || (((iosb)[0] & 0x1) == 0)) { sprintf(buf, "TFTP: Can't bind; $QIOW\status=d^%d, errno=d^%d\n", status, (iosb)[0], (((iosb)[0] & 0x7fff) / 8)); send_opcom(buf);- sys$dassgn(channel); /* Deassign channel */ exit(1); }M init_command_mailbox(); /* Init our receiving mailbox for login requests */ for(;;) {: status = sys$qiow(0, channel, IO$_READVBLK, &iosb, 0, 0,2 buf, sizeof buf, 0, &Socket, sizeof Socket, 0);: if ((status != SS$_NORMAL) || (iosb[0] != SS$_NORMAL)) {3 sprintf(OutBuf, "TFTP: status=x^%x, iosb=x^%x", status, iosb[0]); send_opcom(OutBuf); exit(1); /* EXOS inactive */ };2/* Form the address of sender in our byte order */ StationAddress = % ((Socket.sa_addr & 0xff) << 24) |& ((Socket.sa_addr & 0xff00) << 8) |( ((Socket.sa_addr & 0xff0000) >> 8) |* ((Socket.sa_addr & 0xff000000) >> 24);J/* Get the station address and check whether it is allowed to be served */ for(i = 0;4 AllowedTerminals[i].InterNetAddress != 0; i++) if(StationAddress ==1 AllowedTerminals[i].InterNetAddress) break;V if(AllowedTerminals[i].InterNetAddress == 0) { /* Loop ended and no station found */ #ifdef DEBUG= printf("TFTP load request from unauthorized station %x\n", StationAddress);#endif continue; } #ifdef DEBUG: printf("Current station is %d %x\n", i, StationAddress);#endif, request = (short)(buf[1] + (buf[0] << 8)); switch(request) {) case RRQ: /* Request a file to read */4 buf[80] = '\0'; /* To disable access violation */ #ifdef DEBUG5 printf("Host %x requested loading of file '%s'\n", StationAddress, &buf[2]);#endifP/* For NCD - if the name starts with /usr/lib/X11/ncd then use its subdirectory./ Replace /usr/lib/X11/ncd with TFTP_DIRECTRY.N If it is the fonts directory then route it to the system's fonts directory.*/7 if(strncmp(&buf[2], "/usr/lib/X11/ncd/", 17) == 0) {< if(strncmp(&buf[2], "/usr/lib/X11/ncd/fonts/", 23) == 0) sprintf(FileName, "%s.%s",! "SYS$COMMON:[SYSFONT.DECW", &buf[25]); else/ sprintf(FileName, "%s.%s", TFTP_DIRECTORY, &buf[19]);8 /* Now change the last / to ] and all other / to . */6 if((p = strrchr(FileName, '/')) != NULL) *p = ']';2 else /* The filename is directly under ncd/ */5 if((p = strchr(FileName, '.')) != NULL) *p = ']';. while((p = strchr(FileName, '/')) != NULL) *p = '.'; }4/* Not /...; Check whether it is SYS$COMMON:[...: */ else? if(strncmp(&buf[2], "SYS$COMMON:[SYSFONT.DECW.", 25) == 0) {. strcpy(FileName, &buf[2]); /* Use as-is *//* Remove / if exists - HDS */. while((p = strchr(FileName, '/')) != NULL) *p = ' '; }9/* Check whether it already starts with our TFTP root: */ else. if(compare_p(&buf[2], TFTP_DIRECTORY) == 0). strcpy(FileName, &buf[2]); /* Use as-is */:/* For all other cases - Take the name after the last / */ else {1 if((p = strrchr(&buf[2], '/')) != NULL) *p++; else p = &buf[2];2 sprintf(FileName, "%s]%s", TFTP_DIRECTORY, p); }/* Get a descriptor for it */4 CurrentStation = get_next_free_fd(StationAddress, Socket.sa_port);P/* Check that there are no - in the filename as this allow the user to walk over SYS$COMMON tree. */- while((p = strchr(FileName, '-')) != NULL)) *p = '_'; /* Replace to underscore */8 ActiveConnections[CurrentStation].fd = open(FileName,/ O_RDONLY, "rfm=fix", "ctx=bin", "rop=RAH");1 if(ActiveConnections[CurrentStation].fd < 0) {- ActiveConnections[CurrentStation].fd = 0; #ifdef DEBUG sprintf(buf,2 "TFTP: Can't open %s (Requested from %x)\n", FileName, StationAddress); send_opcom(buf);#endif% OutBuf[0] = 0; OutBuf[1] = ERROR;6 OutBuf[2] = 0; OutBuf[3] = 1; /* File not found */9 strcpy(&OutBuf[4], "File not found or illegal name");< size = strlen(&OutBuf[4]) + 5; /* 1 for the last null */3 ActiveConnections[CurrentStation].BlockNum = 1;4 memcpy(ActiveConnections[CurrentStation].buffer,* OutBuf, size); /* Save last buffer */6 ActiveConnections[CurrentStation].SendSize = size; goto SEND; } else { #ifdef DEBUG1 sprintf(buf, "TFTP server: Read request for \file: '%s' from node: %x\n", FileName, StationAddress); send_opcom(buf);#endif3 ActiveConnections[CurrentStation].BlockNum = 1; goto SendFirstBlock; } case WRQ:( continue; /* Ignore write requests */* case ACK: /* Send the next data block */* CurrentStation = get_fd(StationAddress, Socket.sa_port);# temp = ((buf[2] << 8) + buf[3]);; if(ActiveConnections[CurrentStation].BlockNum != temp) {A if((ActiveConnections[CurrentStation].BlockNum -1) == temp) {7 size = ActiveConnections[CurrentStation].SendSize; memcpy(OutBuf,/ ActiveConnections[CurrentStation].buffer, size); goto SEND; } #ifdef DEBUG5 printf("Illegal ACK sequence number received\n");\ printf("expecting %d, received %d\n", ActiveConnections[CurrentStation].BlockNum, temp);#endif break; }0 ActiveConnections[CurrentStation].BlockNum++; #ifdef DEBUG= printf("%d ", ActiveConnections[CurrentStation].BlockNum);#endif1SendFirstBlock: OutBuf[0] = 0; OutBuf[1] = DATA;H OutBuf[2] = (ActiveConnections[CurrentStation].BlockNum >> 8) & 0xff;M OutBuf[3] = (ActiveConnections[CurrentStation].BlockNum & 0xff); size = 4;Y if(ActiveConnections[CurrentStation].fd != 0) { /* NCD tries to read one block more */S if((size = read(ActiveConnections[CurrentStation].fd, &OutBuf[4], 512)) <= 0) { size = 0;2 close(ActiveConnections[CurrentStation].fd );. ActiveConnections[CurrentStation].fd = 0; #ifdef DEBUG printf("End of file\n");#endifO/* if the last block was not full, then the sender knows it was the last block.K If it was full then we must send now an empty block to show end of file.6 THe second sentence in the IF is for empty files...*/= if((ActiveConnections[CurrentStation].SendSize < 512) &&9 (ActiveConnections[CurrentStation].SendSize > 0))( continue; /* Nothing to send... */ } }( else continue; /* Ignore final ACK */ #ifdef DEBUG+ printf("Sending %d characters\n", size);#endif size += 4;3 memcpy(ActiveConnections[CurrentStation].buffer,) OutBuf, size); /* Save last buffer */5 ActiveConnections[CurrentStation].SendSize = size; goto SEND; case ERROR: #ifdef DEBUG7 printf("TFTP server: error reply: '%s'\n", &buf[4]);#endif continue; default: continue; } SEND:; status = sys$qiow(0, channel, IO$_WRITEVBLK, &iosb, 0, 0,/ OutBuf, size, 0, &Socket, sizeof Socket, 0);< /* We do not check the write result as we don;t care... */ } sys$dassgn(channel); return (2);}/*P | Given station's address and port, get the next free file descriptor. If there) | is already an ent(ry for it - reuse it. */-get_next_free_fd(StationAddress, StationPort)3unsigned int StationAddress; /* Internet address */;unsigned short StationPort; /* The station's port number */{ int i; time_t CurrentTime, time();- CurrentTime = time(NULL); /* Current time */H/* Before looking for an empty slot clear the ones that are more than 10 minutes old */$ for(i = 0; i < MAX_DISPLAYS; i++) {@ if(((CurrentTime - ActiveConnections[i].TimeStarted) > 600) &&% (ActiveConnections[i].fd > 0)) {# close(ActiveConnections[i].fd ); ActiveConnections[i].fd = 0; } }/* Look for an empty slot. */$ for(i = 0; i < MAX_DISPLAYS; i++) {? if(ActiveConnections[i].fd == 0) break; /* Found one empty */@ if((ActiveConnections[i].InterNetAddress == StationAddress) &&8 (ActiveConnections[i].InternetPort == StationPort)) break; /* Found it */ }+ if(i == MAX_DISPLAYS) { /* NOt found... */. send_opcom("No free space for new station"); return 0; }7 ActiveConnections[i].InterNetAddress = StationAddress;t1 ActiveConnections[i].InternetPort = StationPort;i, ActiveConnections[i].TimeStarted = time(0);4 ActiveConnections[i].fd = -1; /* Mark it as busy */C ActiveConnections[i].BlockNum = ActiveConnections[i].SendSize = 0; % *ActiveConnections[i].buffer = '\0';d return i;}O/*I | Look in our array for the given station and return its index if found.. */ #get_fd(StationAddress, StationPort)O3unsigned int StationAddress; /* Internet address */t;unsigned short StationPort; /* The station's port number */r{a int i;t char line[LINESIZE];r" for(i = 0; i < MAX_DISPLAYS; i++)@ if((ActiveConnections[i].InterNetAddress == StationAddress) &&8 (ActiveConnections[i].InternetPort == StationPort)) break; /* Found it */+ if(i == MAX_DISPLAYS) { /* NOt found... */e7 sprintf(line, "TFTP: Station not found: %d.%d.%d.%d", * ((StationAddress & 0xff000000) >> 24),( ((StationAddress & 0xff0000) >> 16),% ((StationAddress & 0xff00) >> 8),O ((StationAddress & 0xff)));r send_opcom(line);t return 0;2 } return i;} /* | Send a message to operator. */esend_opcom(message)mchar *message;{! struct { /* String descriptor */b short length;p short filler;e char *address; } command_desc;R char line[1024];n long status;e #ifdef DEBUG printf("%s\n", message);N#elseNC sprintf(line, "%c%c%c%c0000%s\r\n", 3, 0xff, 0xff, 0xff, message);IA command_desc.address = line; command_desc.length = strlen(line);O command_desc.filler = 0;$? line[4] = line[5] = line[6] = 0; line[7] = 1; /* Request #1 */e sys$sndopr(&command_desc, 0);#endif}aD/*======================== MAILBOX section =======================*//*F | Init the operatore's communication mailbox and queue an AST for it.I | the mailbxo created is accessible by everyone. The emulator checks who , | is the sender in order to protect itself.N | The mailbox is temporary and it's name is defined in the system table. This? | helps us getting rid of the mailbox when the emulator crash.. */Ainit_command_mailbox(){14 long status, mailbox_ast(), /* The AST function */E CrelnmFlags = LNM$M_TERMINAL; /* FLags for logical name creation */t static long Length;( short iosb[4]; /* IOSB for QIO call */> char DeviceName[64], /* To get the name of mailbox device */4 ErrorMessage[256], /* Write here error messages */ NameTable[] = "LNM$SYSTEM";  struct DESC MbxDesc,L, NameTableDesc = { (sizeof NameTable) - 1, 0, NameTable }; struct {  short length, code;  char *address, *ReturnLength;i } GetDviList[] = {8 sizeof DeviceName, DVI$_DEVNAM, DeviceName, &Length, 0, 0, NULL, NULL },e LogicalName[] = {o= sizeof(CrelnmFlags), LNM$_ATTRIBUTES, &CrelnmFlags, NULL,u% 0, LNM$_STRING, DeviceName, NULL,c 0, 0, NULL, NULL };<(/* Create the logical name descriptor */H MbxDesc.address = MAILBOX_NAME; MbxDesc.length = strlen(MAILBOX_NAME); MbxDesc.type = 0;+/* Create the mailbox as a temporary one */"A status = sys$crembx((unsigned char)(0), &MailBoxChan, (long)(0),r1 (long)(0), (long)(0), /* Allow access to all */2& (long)(3), /* Access mode is user */ &MbxDesc); if((status & 0x1) == 0) { sprintf(ErrorMessage,f4 "TFTP, Can't create command mailbox, status=%d.", status); send_opcom(ErrorMessage); exit(status);C }'/* Get the MBAnnn: device name of it */NA status = sys$getdviw(0, MailBoxChan, 0, GetDviList, 0, 0, 0, 0);r if((status & 0x1) == 0) {L sprintf(ErrorMessage, "TFTP, Can't get device name of mailbox, status=%d", status);{ send_opcom(ErrorMessage);e exit(status);  } DeviceName[Length] = '\0';I LogicalName[1].length = Length;L/* Define the logical name poiting to the MBAnnn: device in system table. */C status = sys$crelnm(0, &NameTableDesc, &MbxDesc, 0, &LogicalName);r if((status & 0x1) == 0) { sprintf(ErrorMessage,II "TFTP, Can't decalare mailboxes's name in System's table.status=%d", status);t send_opcom(ErrorMessage);  exit(status);f }!/* Set the write attention AST */ * status = sys$qiow((long)(0), MailBoxChan,, (short)(IO$_SETMODE | IO$M_WRTATTN), iosb,9 (long)(0), (long)(0), /* This is NOT the AST we want */r$ mailbox_ast, (long)(0), (long)(0),# (long)(0), (long)(0), (long)(0));6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) { sprintf(ErrorMessage,pC "TFTP, Can't queue AST for command mailbox, status=%d, iosb=%d",/ status, iosb[0]); send_opcom(ErrorMessage); exit(status);  }}d/*N | This routine is called in AST mode when there is something to read from the8 | mailbox. It reads it, and re-queue the attention AST. */> mailbox_ast()({x long i, status; FILE *Ofd; ? static unsigned char line[LINESIZE]; /* Buffer for reading */ 3 static unsigned short iosb[4]; /* IOSB for QIO *//5 char ErrorMessage[256]; /* To send error messages */ #/* Read the message from mailbox */F* status = sys$qiow((long)(0), MailBoxChan, (short)(IO$_READVBLK), iosb, (long)(0), (long)(0),S' line, (long)(sizeof line), (long)(0),,# (long)(0), (long)(0), (long)(0));A6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {G sprintf(ErrorMessage, "TFTP, Can't read mailbox, status=%d, iosb=%d",[ status, (int)(iosb[0]));, send_opcom(ErrorMessage);i+ } /* We ignore this un-readable message */  else {e2 line[iosb[1]] = '\0'; /* Delimit the username */A/* The message is the station's name. Look for it in our table */s4 for(i = 0; *AllowedTerminals[i].name != '\0'; i++): if(compare(line, AllowedTerminals[i].name) == 0) break;: if(*AllowedTerminals[i].name == '\0') { /* None found */I sprintf(ErrorMessage, "TFTP, Station '%s' not registered in database",a line); send_opcom(ErrorMessage); } else { /* Serve it */f2/* Create a file and execute it as a subprocess */: if((Ofd = fopen("TEMP$:NCD_LOGIN.COM", "w")) != NULL) {0 fprintf(Ofd, "$ SET PROCESS/PRIV=CMKRNL\n");? fprintf(Ofd, "$ SET DISPLAY/CREATE/NODE=%s/TRANSPORT=%s\n",f AllowedTerminals[i].name,. AllowedTerminals[i].DECwindowsMechanism);7 fprintf(Ofd, "$ RUN SYS$SYSTEM:DECW$STARTLOGIN\n");G/* Get the filename of this procedure (including the version number) */)@ fprintf(Ofd, "$ PROC = F$ENVIRONMENT(\042PROCEDURE\042)\n");& fprintf(Ofd, "$ WAIT 00:05:00\n");-/* Delete this specific procedure instance */e, fprintf(Ofd, "$ DELETE/NOLOG 'PROC'\n"); fprintf(Ofd, "$ EXIT\n");l fclose(Ofd);& spawn_process("@TEMP$:NCD_LOGIN"); } } } /* Re-queue the attention AST */* status = sys$qiow((long)(0), MailBoxChan,, (short)(IO$_SETMODE | IO$M_WRTATTN), iosb,9 (long)(0), (long)(0), /* This is NOT the AST we want */T$ mailbox_ast, (long)(0), (long)(0),# (long)(0), (long)(0), (long)(0));B6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) { sprintf(ErrorMessage,rG "TFTP, Can't requeue AST for command mailbox, status=%d, iosb=%d\n",: status, iosb[0]); send_opcom(ErrorMessage);r }}N/*M | Case insensitive strings comparisons. Return 0 only if they have the same( | length.=*/@#define TO_UPPER(c) (((c >= 'a') && (c <= 'z')) ? (c - ' ') : c) compare(a, b) char *a, *b;{s char *p, *q;m p = a; q = b;- for(; TO_UPPER(*p) == TO_UPPER(*q); p++,q++) ) if((*p == '\0') || (*q == '\0')) break;CA if((*p == '\0') && (*q == '\0')) /* Both strings done = Equal */S return 0;l/* Not equal */g% return(TO_UPPER(*p) - TO_UPPER(*q));t}&/*L | Case insensitive strings comparisons. Return 0 only if the second one is( | equal or shorter than the first one.*/@#define TO_UPPER(c) (((c >= 'a') && (c <= 'z')) ? (c - ' ') : c)compare_p(a, b); char *a, *b;{a char *p, *q;i p = a; q = b;- for(; TO_UPPER(*p) == TO_UPPER(*q); p++,q++)a) if((*p == '\0') || (*q == '\0')) break;SE if((*q == '\0')) /* Second string is a (sub)part of the first one */( return 0;n/* Not equal */N% return(TO_UPPER(*p) - TO_UPPER(*q));} /*- | Spawn a subprocess with the given command.n */,spawn_process(string) char *string;&{1 struct {( short length;  short filler;t) char *address; } command_desc, NLdesc;s long status;% char NL[] = "NL:";o/* The command line */ command_desc.address = string;f command_desc.filler = 0;/& command_desc.length = strlen(string);'/* Create a descriptor for NL device */e( NLdesc.address = NL; NLdesc.filler = 0; NLdesc.length = strlen(NL);F status = lib$spawn(&command_desc,&NLdesc,&NLdesc,&1,0,0,0,0,0,0,0,0); if((status & 0x1) == 0)< printf("Can't spawn: status=%d, length=%d, string='%s'\n",( status, command_desc.length, string);) printf("\r\n"); /* Move to next line */O}u; exit(1); /* EXOS inactive */ };2/* Form the address of sender in our byte order */ StationAddress = % ((Socket.sa_addr & 0xff) << 24) |& ((Socket.sa_addr & 0xff00) << 8) |( ((Socket.sa_addr & 0xff0000) >> 8) |* ((Socket.sa_addr & 0xff000000) >> 24);J/* Get the station address and check whether it (*[SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.EXE;1+,.$/ 4$%-i0123 KPWO%56bN"7lN"89)cGHJ0h(M"90@$L0oM"TFTP_MN_SERVERV1.0A10-62$ $ $$ $P $J$( 8,  DECC$SHR_0014 LIBRTL_0014" LIBOTS_001@^6SYS$PUBLIC_VECTORS_0010 @H00  0P p)0@  @@ LNM$SYST N0| ' 00' 0P   &&p&`'p00 0 "P NL:`0`0` rINET0:%s.%s%s.%s%s]%srfm=fixctx=binrop=RAH%d %s w$ EXIT SYS$MANAGER:XDISPLAYS.DATCan't open SYS$MANAGER:XDISPLAYS.DATMAX_DISPLAYS too low. Raise it %s %s %s%d.%d.%d.%dTFTP: Can't assign channel to %s: $ASSIGn status=%d TFTP: Can't bind; $QIOWstatus=d^%d, errno=d^%d TFTP: status=x^%x, iosb=x^%xTFTP load request from unauthorized station %x Current station is %d %x Host %x requested loading of file '%s' /usr/lib/X11/ncd//usr/lib/X11/ncd/fonts/SYS$COMMON:[SYSFONT.DECW$3$dKA200:[TFTPSYS$COMMON:[SYSFONT.DECW.$3$dKA200:[TFTP$3$dKA200:[TFTPTFTP: Can't open %s (Requested from %x) File not found or illegal nameTFTP server: Read request for file: '%s' from node: %x Illegal ACK sequence number received expecting %d, received %d End of file Sending %d characters TFTP server: error reply: '%s' No free space for new stationTFTP: Station not found: %d.%d.%d.%dYNCD_MAILBOXYNCD_MAILBOXTFTP, Can't create command mailbox, status=%d.TFTP, Can't get device name of mailbox, status=%dTFTP, Can't queue AST for command mailbox, status=%d, iosb=%dTFTP, Can't read mailbox, status=%d, iosb=%dTFTP, Station '%s' not registered in databaseTEMP$:NCD_LOGIN.COM$ SET PROCESS/PRIV=CMKRNL $ SET DISPLAY/CREATE/NODE=%s/TRANSPORT=%s $ RUN SYS$SYSTEM:DECW$STARTLOGIN $ PROC = F$ENVIRONMENT("PROCEDURE") $ WAIT 00:05:00 $ DELETE/NOLOG 'PROC' @TEMP$:NCD_LOGINCan't spawn: status=%d, length=%d, string='%s' TFTP: Requesting local socket error: $QIOWstatus=d^%d, errno=d^%d TFTP, Can't decalare mailboxes's name in System's table.status=%dTFTP, Can't requeue AST for command mailbox, status=%d, iosb=%d #4G~^ ^(GG# B  = > (blZkhb# @ӠB4GbGZZkG] ](0#kG@#TG~P ^X ^` ~h p x ޴  > ^ ~ GG#8bhBpb c #"GBZk4GG (B0b "|Zk4G4G8B@bYZk¤_%G 4GB GJ!%%_BP"b?"GtGOTZk4GQA (B0bH"|Zk4G4G8B@bYZk(BP"0bTGTGyZk.PJ>P=.P"G=Jh#"XEF_BbP]"P}"P"UZkGxDBx#"bP"L]"H}"D"@" UZkTGDHL=D=0J!#H@]1!J8BC@bCC!?H0J1V J0DF_F2FH"P="hZkTG8BD"@bP="hZk0@!ÈBGb4GMZk'HE@x@@$G $ q .qKBGb4GPJF>G~lZk.$ PJ>"pFd`G"/G. ' G"X KWJ?> U/p@F5/" .@ ,UKY 5KP J@H>:GG 0}"pbG(4GGGGH~ZkG0-8D#"IP" G8@ED0=,GhBpb=HG{ZkTG(B"0bP="{Zk4G4G8B@bHXZk }G,,*V`I$`Ilq`I+I*AI$H+aI C CH EcIHE H E ED G C 0E p 0@A"`E`" 0@A6@IW_AB@"GTG(B0bzZk(B@"0bGGtGzZkP,Q}-Q]!HjI%H eA+fIfI<5`A `A<`A-G.R (BG0bGPJ>`"tGzZk4GtGBb#"GxZkGtGCBb#"GxZk#"C"i}"G#"C"c}"hBP"pbGn{ZkGTGXB`bP"yZk G`-a@I /(BP"0bGTGwZkG`-aHK`I aE`=(BP"0bGTGwZk GGR%,pEI(BG0bTGA%H0D%SrJr>pbP"P]"GGzZkTG(B0b"P="yZkGTGQ,Q]!aH8BS"@b@ HR"D X#"P.GTJP>R.VJ>mfZk4GXB`bGxZk D!p@E0*HB@Pb"P="GtGGZk pD2 hBx#"pbP"P]"GGxzZkTG(B0b"P="yZk pD. %UG =. ]"G@b#2J@ GR]-$WaIS.%`IkA@a!@%@AR! e. E.LIS=" "J,ItJR TJASFC*v JGGGF'71@F%/E#/%"PbP":KX KHBGCGGtGGZk(B"0b4GayZktG %.  -"(BG J0bL IECTyZkxG !pE0@ ,(B"0bTGHyZk$WaIP].kA+`Ie@ dA @  A - K-R]JS}"IJ @I ,Q" LE K- CP]>ES.uJI+ TJHF>Q.tGxJJ AIWJ EF>R]/R=#{I@EZYKC[GY?GBT="bG_"tG WZk4GG! . ,GBJD HbDC#GZk4G-K! ,"(BLID H<0b=xZk,,K!HE HDC!(B"0bGTGxZktGHB@Pb "P="GGZk pD8=P""hB0}"!v HGG GpbG(GGG{ZkG(B "0bT="TGxZk{. KP JF>qFpFQsHRTJBSFqQ HS tJrFqq@Fp@FvWKTJBFӢ WKV JFӲ qDpD*pHA1H B0D * HP JF q@Ep@E%p1IA1H B0D% 1IP JF qDpD aH@HBD* HA 0H D* qDpD a0I@HBD* 0IA 0H D* qEpE a0J@HBD* 0JA 0H D* qDpDdHLI@ E HD HDlG#4G~^^~ (0޴8@HGGG8B@b$v JGhZk¤G&  !_ 'X_"4G1@2B@(B0bAFZk @&&G 1"G_." r.2#JS uJtFC ҢF/KR GG@R"QB0@D BbTG`'"GwZkG4G(WH!H@g@(@@@":0.rH8B4G@bQ0J2F0>hG>hZk,, ( D HFH<<H,h,AHC aHbD h p`D%@C.h"(#p GTJ>"pF)#7GG]]} (0ݤ8@HP#k.W JF0. HQ 0J2F0>q`Dp`D0rSHQ3J`B2FP0 SHR SJQFPqFpFբwH(#p GVJCFղ HW J#Fq Gp GzdK[fK@dGz KD HD#1v J~^^~ (GGG8 $ ! @"PF@.J,GF @0`@pD4J@3J(B VJ0b2J3aJ4H FCJbJJ"GG xZkTGBb"="JwZkGGG]]} (0#ku.S uJtFG#G~TG^ [0({G/wZkG] #k#G~^^~޴GG#@BB"|Zk_&R"? X]#b4G(X`=h 8b Pb"2FEM_"2F`=TGH]0}="8@=L]HB48} =TuZkGtGGP`HR="hBP}"0JpbFPR].GRQJQ>~GGGzZktGG0D XB`b $""GwZkTGBX" b="vZk4G(BG0bTZk%.%JB1&J0}"b&JGGGGGh}ZktGG0D XB`bP$""GwZkTGBX" b="vZk4G(BG0bSZkc ,P]"xB"afHb@HCDH="Gi}ZktGG0D`XB$"`b"GYwZkTGB bX"="vZk4G(B0bGSZk%.%J=¤1&JXB}"`b&J޴G#_"GG G(yZkG0`D,H0D}."XB$"`bGSpJ"fJG'wZkTGBX" b="QvZk4G(BG0bSZkG]]}ݤ#k,F HDue,C eHqDà#~^^~ (0޴8@H>PGG#b#.#J`01&JPB4GXb&J ""GGG G(G.yZk,G0DHmd"0Dj D.¦GSJ.@"2/Jv#Y2K2? G"G@;/{#0B;K_!J WBBB'".!tGJ" PBD"XbGvZk`"K TGPBXb!8("G|ZkTG GE B(b("GhtZkG B(b8("G"Dg"G`tZkTG B(bh("GZtZkTG B(b("GTtZkTG B(b("GNtZkTG B(b("GHtZkTG B(b@("GBtZk4GpBxbGFZk"b#@@G "PBGXbGp GGfvZk"B="bTGuZk#.#J9`"1&JPBGXb&J>#_"GGG G(xZkd, 0DdH 0`D "PBGXbG GG;vZkTGBbp"="euZkG]]} (0ݤ8@H=P`#k,@ HD-#-I #I1E,0 AH'HA" @3$@GQ. R@JGJ2   4DBGGtF@G0,0H< Q.QJ9`." 1"TJJ4 T" 3B@G,1 AH'HA" @5$@GGuF@ ,"P"1"RHGJr""`!DBGG. UJJu""`2BGG2D_,"q.1"PHSqJJgJG`kG""S0I~ TFTP_XDM.BCKi([SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.EXE;1$^ !BGS"3" dB@  @kG  @kG,0 AH'HA" @3$@GQ. R@JGJ2   4DBGGtF@G0,0H< Q.QJ9`." 1"TJJ4 T" 3B@G,1 AH'HA" @5$@GGuF@ ,"P"1"RHGJr""`!DBGG. UJJu""`2BGG2D_,1"QHG'J kp."SpJgJ""!dBGQ" @0$B 0@kG 0@kG#4G~ ^(^0~8@GG# BG"b=.Q0J0>}GAsZk4G`HB]"="b0JF"}.SrJr>=1sZkGGG`H0B="8b]"0J(b"F" (lZkGp0D" ].G`BGhbRPJGFJtZk`BH"hb4GtZkG ](]0}8@P#kTThH `0P 0@P`p0`p @DECC$SHR@LIBRTL@LIBOTS@SYS$PUBLIC_VECTORS+TFTP_MN_SERVERDEC C V1.3-000TRANSFER$BREAK$GOmain k k                                         H E      ; 6           ) $                                   ) ) ) . . 3 8 : : ; : : ; : : = I K S S U U U U U U X X h$ h i h i h i j j h h h i i l m o o o  T    <      xget_next_free_fd            < < ; b     4  8   < 8get_fds            $   send_opcom*        @!init_command_mailbox          # $ # # $ ' 8 9 4 A B < < ; ; ;d ? M N O O O [ \( 4,     mailbox_ast \ e e e j q q q q s u u u p { { k( v      4 e(   `compare`$    P@  compare_p@ $    \" spawn_process"                &     D"`__main  @@%x# B   N(*[SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.OBJ;2+,.N/ 4NN -i0123KPWOO56:$oA"77L"89)cGHJJJTFTP_MN_SERVERV1.017-MAR-1994 13:30DEC C V1.3-000  $READONLY$$BSS$ $DATA$@$LINK$% $LITERAL$ix#$CODE$ $ABS$DECC$GA_STDERR DECC$GA_STDINDECC$GA_STDOUT DECC$FCLOSE DECC$FOPEN DECC$GFPRINTF DECC$GPRINTF DECC$GSPRINTF DECC$GSSCANF DECC$FGETSH_ERRNOH_NERR H_ERRLIST  BALLOWEDTERMINALS8ALLOWEDTERMINALS  ACTIVECONNECTIONS8ACTIVECONNECTIONS  MAILBOXCHAN0 MAILBOXCHAN(JMAIN DECC$TIME DECC$EXIT DECC$STRCHR DECC$STRCPY DECC$STRLEN SYS$ASSIGN0J SEND_OPCOMSYS$QIOW SYS$DASSGN8JINIT_COMMAND_MAILBOX DECC$STRNCMP DECC$STRRCHR0J@  COMPARE_P8JxGET_NEXT_FREE_FD DECC$OPEN DECC$MEMCPY(J8GET_FD DECC$READ DECC$CLOSE0J MAILBOX_AST SYS$CREMBX SYS$GETDVIW SYS$CRELNM(J`COMPARE0J" SPAWN_PROCESS LIB$SPAWN(J__MAIN DECC$MAIN DECC$EXITOTS$MOVE =r=INET0:=%s.%s=%s.%s =%s]%s(=(rfm=fixctx=binrop=RAH%d H=%s P=wX= $ EXIT h=(SYS$MANAGER:XDISPLAYS.DAT=0%Can't open SYS$MANAGER:XDISPLAYS.DAT=8)MAX_DISPLAYS too low. Raise it %s %s %s= %d.%d.%d.%d=@5TFTP: Can't assign channel to %s: $ASSIGn status=%d (=XMTFTP: Can't bind; $QIOWstatus=d^%d, errno=d^%d TFTP: status=x^%x, iosb=x^%xx=XJTFTP load request from unauthorized station %x Current station is %d %x =H:Host %x requested loading of file '%s' /usr/lib/X11/ncd/=@1/usr/lib/X11/ncd/fonts/SYS$COMMON:[SYSFONT.DECW@=8*$3$dKA200:[TFTPSYS$COMMON:[SYSFONT.DECW.p=XI$3$dKA200:[TFTP$3$dKA200:[TFTPTFTP: Can't open %s (Requested from %x) =(File not found or illegal name=h^TFTP server: Read request for file: '%s' from node: %x Illegal ACK sequence number received @=(expecting %d, received %d `= End of file p= Sending %d characters =H>TFTP server: error reply: '%s' No free space for new station=0%TFTP: Station not found: %d.%d.%d.%d= YNCD_MAILBOX= YNCD_MAILBOX=8/TFTP, Can't create command mailbox, status=%d.@=@2TFTP, Can't get device name of mailbox, status=%dx=H>TFTP, Can't queue AST for command mailbox, status=%d, iosb=%d=8-TFTP, Can't read mailbox, status=%d, iosb=%d=8.TFTP, Station '%s' not registered in database= TEMP$:NCD_LOGIN.COM0=($ SET PROCESS/PRIV=CMKRNL P=8+$ SET DISPLAY/CREATE/NODE=%s/TRANSPORT=%s =0"$ RUN SYS$SYSTEM:DECW$STARTLOGIN =0%$ PROC = F$ENVIRONMENT("PROCEDURE") = $ WAIT 00:05:00 = $ DELETE/NOLOG 'PROC' = @TEMP$:NCD_LOGIN=sCan't spawn: status=%d, length=%d, string='%s' TFTP: Requesting local socket error: $QIOWstatus=d^%d, errno=d^%d =PBTFTP, Can't decalare mailboxes's name in System's table.status=%d=IATFTP, Can't requeue AST for command mailbox, status=%d, iosb=%d  =0;=  DECC$GPRINTFH;=0;=0 ` DECC$GSPRINTF7ACTIVECONNECTIONS=0;=P  DECC$CLOSE DECC$TIME=0@ ; SYS$GETDVIW;;=@ LNM$SYST7 MAILBOXCHAN=0;=| 0 DECC$EXIT;8OTS$MOVE DECC$STRLENSYS$QIOW SYS$CREMBX SYS$CRELNM SYS$ASSIGN DECC$READ DECC$FGETS SYS$DASSGN DECC$GSSCANF! DECC$STRNCMP7ALLOWEDTERMINALS=0P ;=   # DECC$STRCHR% DECC$STRCPY' DECC$MEMCPY) DECC$STRRCHR+ DECC$FOPEN- DECC$OPEN/ DECC$FCLOSE=0;=0 1 DECC$MAIN=0 ";=(P NL:3 LIB$SPAWN=0`;=0;=` 5 DECC$GFPRINTFE E=-% =#4G~^ ^(GG# B  = > (b@Zkhb# @ӠB4GbG@ZkG] ](0#kG@#TG~P ^X ^` ~h p x ޴  > ^ ~ GG#8bhBpb c #"G@Zk4GG (B0b "@Zk4G4G8B@b@Zk¤_%G 4GB GJ!%%_BP"b?"GtG@Zk4GQA (B0bH"@Zk4G4G8B@b@Zk(BP"0bTGTG@Zk.PJ>P=.P"G=Jh#"XEF_BbP]"P}"P"@ZkGxDBx#"bP"L]"H}"D"@"@ZkTGDHL=D=0J!#H@]1!J8BC@bCC!?H0J1V J0DF_F2FH"P="@ZkTG8BD"@bP="@Zk0@!ÈBGb4G@Zk'HE@x@@$G $ q .qKBGb4GPJF>G@Zk.$ PJ>"pFd`G"/G. ' G"X KWJ?> U/p@F5/" .@ ,UKY 5KP J@H>:GG 0}"pbG(4GGGG@ZkG0-8D#"IP" G8@ED0=,GhBpb=HG@ZkTG(B"0bP="@Zk4G4G8B@b@Zk }G,,*V`I$`Ilq`I+I*AI$H+aI C CH EcIHE H E ED G C 0E p 0@A"`E`" 0@A6@IW_AB@"GTG(B0b@Zk(B@"0bGGtG@ZkP,Q}-Q]!HjI%H eA+fIfI<5`A `A<`A-G.R (BG0bGPJ>`"tG@Zk4GtGBb#"G@ZkGtGCBb#"G@Zk#"C"i}"G#"C"c}"hBP"pbG@ZkGTGXB`bP"@Zk G`-a@I /(BP"0bGTG@ZkG`-aHK`I aE`=(BP"0bGTG@Zk GGR%,pEI(BG0bTGA%H0D%SrJr>pbP"P]"GG@ZkTG(B0b"P="@ZkGTGQ,Q]!aH8BS"@b@ HR"D X#"P.GTJP>R.VJ>@Zk4GXB`bG@Zk D!p@E0*HB@Pb"P="GtG@Zk pD2 hBx#"pbP"P]"GG@ZkTG(B0b"P="@Zk pD. %UG =. ]"G@b#2J@ GR]-$WaIS.%`IkA@a!@%@AR! e. E.LIS=" "J,ItJR TJASFC*v JGGGF'71@F%/E#/%"PbP":KX KHBGCGGtG@Zk(B"0b4G@ZktG %.  -"(BG J0bL IEC@ZkxG !pE0@ ,(B"0bTG@Zk$WaIP].kA+`Ie@ dA @  A - K-R]JS}"IJ @I ,Q" LE K- CP]>ES.uJI+ TJHF>Q.tGxJJ AIWJ EF>R]/R=#{I@EZYKC[GY?GBT="bG_"tG@Zk4GG! . ,GBJD HbDC@Zk4G-K! ,"(BLID H<0b=@Zk,,K!HE H =DC!(B"0bGTG@ZktGHB@Pb "P="G@Zk pD8=P""hB0}"!v HGG GpbG(GGG@ZkG(B "0bT="TG@Zk{. KP JF>qFpFQsHRTJBSFqQ HS tJrFqq@Fp@FvWKTJBFӢ WKV JFӲ qDpD*pHA1H B0D * HP JF q@Ep@E%p1IA1H B0D% 1IP JF qDpD aH@HBD* HA 0H D* qDpD a0I@HBD* 0IA 0H D* qEpE a0J@HBD* 0JA 0H D* qDpDdHLI@ E HD HDlG#4G~^^~ (0޴8@HGGG8B@b$v JG@Zk¤G&  !_ 'X_"4G1@2B@(B0b@Zk @&&G 1"G_." r.2#JS uJtFC ҢF/KR GG@R"QB0@D BbTG`'"G@ZkG4G(WH!H@g@(@@@":0.rH8B4G@bQ0J2F0>hG@Zk,, ( D HFH<<H,h,AHC aHbD h p`D%@C.h"(#p GTJ>"pF)#7GG]]} (0ݤ8@HP#k.W JF0. HQ 0J2F0>q`Dp`D0rSHQ3J`B2FP0 SHR SJQFPqFpFբwH(#p GVJCFղ HW J#Fq Gp GzdK[fK@dGz KD HD#1v J~^^~ (GGG8 $ ! @"PF@.J,GF @0`@pD4J@3J(B VJ0b2J3aJ4H FCJbJJ"GG@ZkTGBb"="@ZkGGG]]} (0#ku.S uJtFG#G~TG^ [0({G@ZkG] #k#G~^^~޴GG#@BB"@Zk_&R"? X]#b4G(X`=h 8b Pb"2FEM_"2F`=TGH]0}="8@=L]HB48} =T@ZkGtGGP`HR="hBP}"0JpbFPR].GRQJQ>~GGG@ZktGG0D XB`b $""G@ZkTGBX" b="@Zk4G(BG0b@Zk%.%JB1&J0}"b&JGGGGG@ZktGG0D XB`bP$""G@ZkTGBX" b="@Zk4G(BG0b@Zkc ,P]"xB"afHb@HCDH="G@ZktGG0D`XB$"`b"G@ZkTGB bX"="@Zk4G(B0bG@Zk%.%J=¤1&JXB}"`b&J޴G#_"GG G(@ZkG0`D,H0D}."XB$"`bGSpJ"fJG@ZkTGBX" b="@Zk4G(BG0b@ZkG]]}ݤ#k,F HDue,C eHqDà#~^^~ (0޴8@H>PGG#b#.#J`01&JPB4GXb&J ""GGG G(G@Zk,G0DHmd"0Dj D.¦GSJ.@"2/Jv#Y2K2? G"G@;/{#0B;K_!J WBBB'".!tGJ" PBD"XbG@Zk`"K TGPBXb!8("G@ZkTG GE B(b("G@ZkG B(b8("G"Dg"G@ZkTG B(bh ("G@ZkTG B(b("G@ZkTG B(b("G@ZkTG B(b("G@ZkTG B(b@("G@Zk4GpBxbG@Zk"b#@@G "PBGXbGp GG@Zk"B="bTG@Zk#.#J9`"1&JPBGXb&J>#_"GGG G(@Zkd, 0DdH 0`D "PBGXbG GG@ZkTGBbp"="@ZkG]]} (0ݤ8@H=P`#k,@ HD-#-I #I1E,0 AH'HA" @3$@GQ. R@JGJ2   4DBGGtF@G0,0H< Q.QJ9`." 1"TJJ4 T" 3B@G,1 AH'HA" @5$@GGuF@ ,"P"1"RHGJr""`!DBGG. UJJu""`2B =GG2D_,"q.1"PHSqJJgJG`kG""!BGS"3" dB@  @kG  @kG,0 AH'HA" @3$@GQ. R@JGJ2   4DBGGtF@G0,0H< Q.QJ9`." 1"TJJ4 T" 3B@G,1 AH'HA" @5$@GGuF@ ,"P"1"RHGJr""`!DBGG. UJJu""`2BGG2D_,1"QHG'J kp."SpJgJ""!dBGQ" @0$B 0@kG 0@kG#4G~ ^(^0~8@GG# BG"b=.Q0J0>}G@Zk4G`HB]"="b0JF"}.SrJr>=@ZkGGG`H0B="8b]"0J(b"F" (@ZkGp0D" ].G`BGhbRPJGFJ@Zk`BH"hb4G@ZkG ](]0}8@P#k41$GH DECC$MAIN42<b# DECC$MAIN41D@H DECC$MAIN4 PGd DECC$EXIT4 Xb# DECC$EXIT4 `@d DECC$EXIT4+G DECC$FOPEN4,b# DECC$FOPEN4+@ DECC$FOPEN4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4  G DECC$EXIT4 b# DECC$EXIT4 @ DECC$EXIT4@G\ DECC$FGETS4Hb# DECC$FGETS4X@\ DECC$FGETS4lG| DECC$GPRINTF4pb# DECC$GPRINTF4x@| DECC$GPRINTF4 G DECC$EXIT4 b# DECC$EXIT4 @ DECC$EXIT4# "G DECC$STRCHR4$b# DECC$STRCHR4#@ DECC$STRCHR4G DECC$GSSCANF4 b# DECC$GSSCANF4@ DECC$GSSCANF4G DECC$GSSCANF4 b# DECC$GSSCANF4@ DECC$GSSCANF4%DG DECC$STRCPY4&Lb# DECC$STRCPY4%@ DECC$STRCPY4%G DECC$STRCPY4&b# DECC$STRCPY4%@ DECC$STRCPY4/G DECC$FCLOSE40b# DECC$FCLOSE4/@ DECC$FCLOSE4G DECC$TIME4b# DECC$TIME4@ DECC$TIME4%G DECC$STRCPY4&b# DECC$STRCPY4%@ DECC$STRCPY4G DECC$STRLEN4b# DECC$STRLEN4@ DECC$STRLEN4G SYS$ASSIGN4b# SYS$ASSIGN4@ SYS$ASSIGN4$G@ DECC$GSPRINTF4(b# DECC$GSPRINTF4<@@ DECC$GSPRINTF4DGX DECC$GPRINTF4Hb# DECC$GPRINTF 4T@X DECC$GPRINTF4 `Gl DECC$EXIT4 db# DECC$EXIT4 h@l DECC$EXIT4tGSYS$QIOW4b#SYS$QIOW4@SYS$QIOW4G DECC$GSPRINTF4b# DECC$GSPRINTF4@ DECC$GSPRINTF4G0 DECC$GPRINTF4 b# DECC$GPRINTF4,@0 DECC$GPRINTF48GL SYS$DASSGN4<b# SYS$DASSGN4H@L SYS$DASSGN4 TG` DECC$EXIT4 Xb# DECC$EXIT4 \@` DECC$EXIT4lGSYS$QIOW4tb#SYS$QIOW4@SYS$QIOW4GH DECC$GSPRINTF4b# DECC$GSPRINTF4D@H DECC$GSPRINTF4LG` DECC$GPRINTF4Pb# DECC$GPRINTF4\@` DECC$GPRINTF4hG| SYS$DASSGN4lb# SYS$DASSGN4x@| SYS$DASSGN4 G DECC$EXIT4 b# DECC$EXIT4 @ DECC$EXIT4GSYS$QIOW4b#SYS$QIOW4@SYS$QIOW4 G4 DECC$GSPRINTF4$b# DECC$GSPRINTF40@4 DECC$GSPRINTF48GL DECC$GPRINTF4@b# DECC$GPRINTF4H@L DECC$GPRINTF4 TG` DECC$EXIT4 Xb# DECC$EXIT4 \@` DECC$EXIT4G$ DECC$GPRINTF4b# DECC$GPRINTF4 @$ DECC$GPRINTF4(GD DECC$GPRINTF40b# DECC$GPRINTF4@@D DECC$GPRINTF4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4!G DECC$STRNCMP4"b# DECC$STRNCMP4!@ DECC$STRNCMP4!G DECC$STRNCMP4"b# DECC$STRNCMP4!@ DECC$STRNCMP4 G( DECC$GSPRINTF4 b# DECC$GSPRINTF4$ @( DECC$GSPRINTF4)0 G@ DECC$STRRCHR4*4 b# DECC$STRRCHR4)< @@ DECC$STRRCHR4#X Gp DECC$STRCHR4$` b# DECC$STRCHR4#l @p DECC$STRCHR4# G DECC$STRCHR4$ b# DECC$STRCHR4# @ DECC$STRCHR4# G DECC$STRCHR4$ b# DECC$STRCHR4# @ DECC$STRCHR4! G DECC$STRNCMP4" b# DECC$STRNCMP 4! @ DECC$STRNCMP4% G DECC$STRCPY4& b# DECC$STRCPY4% @ DECC$STRCPY4#( G8 DECC$STRCHR4$0 b# DECC$STRCHR4#4 @8 DECC$STRCHR4#P Gt DECC$STRCHR4$X b# DECC$STRCHR4#p @t DECC$STRCHR4% G DECC$STRCPY4& b# DECC$STRCPY4% @ DECC$STRCPY4) G DECC$STRRCHR4* b# DECC$STRRCHR4) @ DECC$STRRCHR4 G DECC$GSPRINTF4 b# DECC$GSPRINTF4 @ DECC$GSPRINTF4# G0 DECC$STRCHR4$ b# DECC$STRCHR4#, @0 DECC$STRCHR4#H Gl DECC$STRCHR4$P b# DECC$STRCHR4#h @l DECC$STRCHR4-x G DECC$OPEN4. b# DECC$OPEN4- @ DECC$OPEN4 G DECC$GSPRINTF4 b# DECC$GSPRINTF4 @ DECC$GSPRINTF4 G DECC$GPRINTF4 b# DECC$GPRINTF4 @ DECC$GPRINTF4%0 G DECC$STRCPY4&8 b# DECC$STRCPY4% @ DECC$STRCPY4 G DECC$STRLEN4 b# DECC$STRLEN4 @ DECC$STRLEN4' G DECC$MEMCPY4( b# DECC$MEMCPY4' @ DECC$MEMCPY4 G DECC$GSPRINTF4 b#`0k~ TFTP_XDM.BCKi([SYSUTIL.DECW_LOGIN]TFTP_MN_SERVER.OBJ;2Np:2 DECC$GSPRINTF4 @ DECC$GSPRINTF4 G DECC$GPRINTF4 b# DECC$GPRINTF4 @ DECC$GPRINTF4( b# DECC$MEMCPY4' G DECC$MEMCPY4'@ DECC$MEMCPY4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF40GP DECC$GPRINTF4<b# DECC$GPRINTF4L@P DECC$GPRINTF4lG DECC$GPRINTF4tb# DECC$GPRINTF4|@ DECC$GPRINTF4@G\ DECC$READ4Hb# DECC$READ4X@\ DECC$READ4xG DECC$CLOSE4b# DECC$CLOSE4@ DECC$CLOSE4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4'G$ DECC$MEMCPY4(b# DECC$MEMCPY4' @$ DECC$MEMCPY4DGSYS$QIOW4lb#SYS$QIOW 4@SYS$QIOW4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4G DECC$TIME4b#x DECC$TIME4@ DECC$TIME4G DECC$CLOSE4b#x DECC$CLOSE4@ DECC$CLOSE4G DECC$GPRINTF4b#x DECC$GPRINTF4@ DECC$GPRINTF4G DECC$TIME4b#x DECC$TIME4@ DECC$TIME4$G` DECC$GSPRINTF4,b#8 DECC$GSPRINTF4\@` DECC$GSPRINTF4dGx DECC$GPRINTF4hb#8 DECC$GPRINTF4t@x DECC$GPRINTF4G DECC$GPRINTF4{# DECC$GPRINTF4@ DECC$GPRINTF4 ,G<OTS$MOVE4 8@<OTS$MOVE4pb# DECC$STRLEN4G DECC$STRLEN4@ DECC$STRLEN4G SYS$CREMBX4b# SYS$CREMBX4@ SYS$CREMBX4,GD DECC$GSPRINTF40b# DECC$GSPRINTF4@@D DECC$GSPRINTF4HG\ DECC$GPRINTF4Pb# DECC$GPRINTF4X@\ DECC$GPRINTF4 `Gp DECC$EXIT4 hb# DECC$EXIT4 l@p DECC$EXIT4 |G SYS$GETDVIW4 b# SYS$GETDVIW4 @ SYS$GETDVIW4G DECC$GSPRINTF4b# DECC$GSPRINTF4@ DECC$GSPRINTF4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4 G DECC$EXIT4 b# DECC$EXIT4 @ DECC$EXIT4GT SYS$CRELNM4 b# SYS$CRELNM4P@T SYS$CRELNM4dG| DECC$GSPRINTF4lb# DECC$GSPRINTF4x@| DECC$GSPRINTF4G DECC$GPRINTF4b# DECC$GPRINTF4@ DECC$GPRINTF4 G DECC$EXIT4 b# DECC$EXIT4 @ DECC$EXIT4GSYS$QIOW4b#SYS$QIOW4@SYS$QIOW4 GD DECC$GSPRINTF4(b# DECC$GSPRINTF4@@D DECC$GSPRINTF4HG\ DECC$GPRINTF4Pb# DECC$GPRINTF4X@\ DECC$GPRINTF4 `Gp DECC$EXIT4 hb# DECC$EXIT4 l@p DECC$EXIT 4 GXSYS$QIOW4b#SYS$QIOW4T@XSYS$QIOW4G DECC$GSPRINTF4 b# DECC$GSPRINTF4@ DECC$GSPRINTF4+(G@ DECC$FOPEN4,,b# DECC$FOPEN4+<@@ DECC$FOPEN45LG` DECC$GFPRINTF46Pb# DECC$GFPRINTF45\@` DECC$GFPRINTF45dG DECC$GFPRINTF46hb# DECC$GFPRINTF45|@ DECC$GFPRINTF45G DECC$GFPRINTF46b# DECC$GFPRINTF45@ DECC$GFPRINTF45G DECC$GFPRINTF46b# DECC$GFPRINTF45@ DECC$GFPRINTF45G DECC$GFPRINTF46b# DECC$GFPRINTF45@ DECC$GFPRINTF45G DECC$GFPRINTF46b# DECC$GFPRINTF45@ DECC$GFPRINTF45G DECC$GFPRINTF46b# DECC$GFPRINTF45@ DECC$GFPRINTF4/G  DECC$FCLOSE40b# DECC$FCLOSE4/@  DECC$FCLOSE4(GH DECC$GSPRINTF40b# DECC$GSPRINTF4D@H DECC$GSPRINTF4LG` DECC$GPRINTF4Tb# DECC$GPRINTF4\@` DECC$GPRINTF4tGSYS$QIOW4|b#SYS$QIOW4@SYS$QIOW4G DECC$GSPRINTF4b# DECC$GSPRINTF4@ DECC$GSPRINTF4G  DECC$GPRINTF4b# DECC$GPRINTF4@  DECC$GPRINTF4H"Gt" DECC$STRLEN4T"b# DECC$STRLEN4p"@t" DECC$STRLEN4"G" DECC$STRLEN4"b# DECC$STRLEN4"@" DECC$STRLEN43"G# LIB$SPAWN44"b# LIB$SPAWN43#@# LIB$SPAWN4(#GD# DECC$GPRINTF40#b# DECC$GPRINTF4@#@D# DECC$GPRINTF4D#GX# DECC$GPRINTF4L#b# DECC$GPRINTF4T#@X# DECC$GPRINTFD D=4,+TFTP_MN_SERVERDEC C V1.3-000? ?= 4=TRANSFER$BREAK$GO = 44= main4= k k                                         H E      ; 6           ) $                                   ) ) ) . . 3 8 : : ; : : ; : : = I K S S U U U U U U X X h$ h i h i h i j j h h h i i l m o o o  T    <$ $= 4. .=  4=  = . .=  4=  = . .=  4=  = G. .=  4=  = O. .=  4=  = . .=  4=  =  = W W= 4x4=get_next_free_fd4=            < < ; b     4  8   #include #include #include #include #include :#include "multinet_root:[multinet.include.vms]inetiodef.h"6#include "multinet_root:[multinet.include.sys]types.h"7#include "multinet_root:[multinet.include.sys]socket.h"2#include "multinet_root:[multinet.include]netdb.h"struct sockaddr_in { short sa_family; /* family */* unsigned short sa_port; /* port number */. unsigned long sa_addr; /* Internet address */* char sa_zero[8]; /* unused, must be 0 */};C#define SWAP_SHORT(xxx) (((xxx >> 8) & 0xff) | ((xxx & 0xff) << 8))J#define SWAP_LONG(xxx) (((xxx >> 24) & 0xff) | ((xxx & 0xff0000) >> 8) | \1 ((xxx & 0xff00) << 8) | ((xxx & 0xff) << 24))/* XDM-CP opcodes: */#define BroadcastQuery 1#define Query 2#define IndirectQuery 3#define ForwardQuery 4#define Willing 5#define Unwilling 6#define Request 7#define Accept 8#define Decline 9#define Manage 10#define Refuse 11#define Failed 12#define Alive 13#define KeepAlive 14 /* The header of the packets: */struct HEADER {2 short Version, /* Version number (1 currently) */ Opcode,2 Length; /* Length of remaining data in bytes */ }; unsigned short channel, iosb[4];struct sockaddr_in Socket;#define MAX_DISPLAYS 128./* Hold the state of each station we manage */struct {1 int Address; /* The IP address of the display */C int Started; /* 1 when the display already started. 0 otherwise */% char Name[64], /* Name of machine */> Transport[64]; /* What transport to use (DECnet or TCPIP) */= int WhichLoginProgram; /* Shall we use DEC's one or ours? */! } ManagedDisplays[MAX_DISPLAYS];/* The login programs type */;#define DECW_LOGINOUT 0 /* Digital's supplied STARTLOGIN */P#define HUJI_LOGINOUT 1 /* Our program on problematic displays (like Pericom) */Nshort MailBoxChan; /* For the AST mailbox to inform about successfull login */%#define MAILBOX_NAME "YXDMCP_MAILBOX"main(){B unsigned char buf[1024], /* set network buffer to be 1K bytes */5 OutBuf[1024]; /* For temporary usage and output */ char *p, DevName[16]; struct { /* Descriptor */ short length; short filler; char *address; } Device;@ struct HEADER *Header; /* To parse the header of the packets */,/* For parsing SYS$MANAGER:XDISPLAYS.DAT: */- long i, A, B, C, D, size, status, NumParams;@ char Address[256], Name[256], DECwindows[256], WhichLogin[256]; FILE *fd;L/* Read the information about the displays we will to manage or TFTP load */= if((fd = fopen("SYS$MANAGER:XDISPLAYS.DAT", "r")) == NULL) {: printf("Can't open SYS$MANAGER:XDISPLAYS.DAT"); exit(1); } i = 0;, while(fgets(buf, sizeof buf, fd) != NULL) { if(i >= MAX_DISPLAYS) {7 pri ntf("MAX_DISPLAYS too low. Raise it\n"); exit(1); }0 if((p = strchr(buf, '\n')) != NULL) *p = '\0';) if(*buf == '*') continue; /* Comment */; if((NumParams = sscanf(buf, "%s %s %s %s", Address, Name,C DECwindows, WhichLogin)) >= 3) /* Legal line */< if(sscanf(Address, "%d.%d.%d.%d", &A, &B, &C, &D) == 4) { ManagedDisplays[i].Address = (((A << 24) & 0xff000000) | ((B << 16) & 0xff0000) | ((C << 8) & 0xff00) | (D & 0xff));# ManagedDisplays[i].Started = 0;* strcpy(ManagedDisplays[i].Name, Name);5 strcpy(ManagedDisplays[i].Transport, DECwindows);7 if(NumParams == 3) /* No login program specified */+ ManagedDisplays[i].WhichLoginProgram = DECW_LOGINOUT; else+ ManagedDisplays[i].WhichLoginProgram = HUJI_LOGINOUT; i++; } } fclose(fd);2 ManagedDisplays[i].Address = 0; /* End of list */Z init_command_mailbox(); /* So we receive messages about successfull session initiation */(/* Assign a channel to network device */ strcpy(DevName, "INET0:");; Device.address = DevName; Device.length = strlen(DevName); channel = 0;F/*================== Assign the datagram socket ====================*/, if(((status = sys$assign(&Device, &channel,' (long)(0), (long)(0))) & 0x1) == 0) { sprintf(buf,> "VMS_TCP, Can't assign channel to %s: $ASSIGn status=%d\n", DevName, status); send_opcom(buf); exit(1); } /* Request a local socket */; status = sys$qiow((long)(0),  channel, (short)(IO$_SOCKET), iosb, (long)(0), (long)(0),2 (int)(AF_INET), (int)(SOCK_DGRAM), (long)(0),& (long)(0), (long)(0), (long)(0));8 if(((status & 0x1) == 0) || (((iosb)[0] & 0x1) == 0)) { sprintf(buf,2 "VMS_TCP, Requesting local socket error: $QIOW\status=d^%d, errno=d^%d\n", status, (iosb)[0], (((iosb)[0] & 0x7fff) / 8)); send_opcom(buf);- sys$dassgn(channel); /* Deassign channel */ exit(1); } /* Bind a name to it */ Socket.sa_family = AF_INET;" Socket.sa_port = SWAP_SHORT(177);( Socket.sa_addr = 0; /* Local machine */9 status = sys$qiow((long)(0), channel, (short)(IO$_BIND), iosb, (long)(0), (long)(0),) &Socket, sizeof(struct sockaddr_in),/ (long)(0), (long)(0), (long)(0), (long)(0));8 if(((status & 0x1) == 0) || (((iosb)[0] & 0x1) == 0)) { sprintf(buf, "VMS_TCP, Can't bind; $QIOW\status=d^%d, errno=d^%d\n", status, (iosb)[0], (((iosb)[0] & 0x7fff) / 8)); send_opcom(buf);- sys$dassgn(channel); /* Deassign channel */ exit(1); } /* Read the datagrams */ for(;;) {: status = sys$qiow(0, channel, IO$_READVBLK, &iosb, 0, 0,2 buf, sizeof buf, 0, &Socket, sizeof Socket, 0);: if ((status != SS$_NORMAL) || (iosb[0] != SS$_NORMAL)) {3 sprintf(OutBuf, "TFTP: status=x^%x, iosb=x^%x", status, iosb[0]); send_opcom(OutBuf); exit(1); /* EXOS inactive */ }; Header = (struct HEADER *)buf; #ifdef DEBUGQ printf("Received message: Version=%d, OPcode=%d, Length=%d, total length=%d\n",; SWAP_SHORT(Header->Version), SWAP_SHORT(Header->Opcode), SWAP_SHORT(Header->Length), iosb[1]);#endifI/* See what actions we have to do. Usually the action is simply to ACK itI except from the last one which is the Manage request in which we start$ DECW$STARTLOGIN or DECW_LOGIN. */& switch(SWAP_SHORT(Header->Opcode)) { case Query: case BroadcastQuery: case IndirectQuery: handle_query(buf); break; case ForwardQuery: handle_forward_query(buf); break; case Request: handle_request(buf); break; case Manage: handle_manage(); break; case KeepAlive: case Alive: handle_keepalive(buf); break; default: #ifdef DEBUG0 printf("Illegal message code received: %d\n", SWAP_SHORT(Header->Opcode));#endif ; } continue; } sys$dassgn(channel); return (2);}/*F | The remore server queries us for service. Ack it if it is listed in' | our database. If not, send him home. */handle_query(buf)unsigned char *buf;{@ struct HEADER *Header; /* To parse the header of the packets */ Header = (struct HEADER *)buf;2/* We do not support an authentication protocol */' if((SWAP_SHORT(Header->Length)) > 1) { #ifdef DEBUG; printf("We do not support any autentication protocol\n");#endif? send_willing(0, "Your autentication protocol is unsported."); return; /* Ignore it */ }/* Do we want to serve it? */ if(allow_station() < 0) { #ifdef DEBUG, printf("Unsupported station rejected.\n");#endif@ send_willing(0, "You are not registered in HUJIVMS database"); return; /* Ignore it */ } #ifdef DEBUG+ printf("Willing to serve some machine\n");#endif- send_willing(1, "HUJI XDM server manager.");}/*H | A request was received from another XDM manager to manage an XdisplayG | terminal (probably the other host ran the chooser). Get the client's' | address and send the willing to him. */handle_forward_query(buf)unsigned char *buf;{4 unsigned char *p, OutBuf[1024]; /* Output buffer */ unsigned short *Pshort; int i, size;I/* Socket structure now holds the parameter of the other XDM who sent the: request. Modify it now to have the Xterminal address */ Socket.sa_family = AF_INET;1 memset(Socket.sa_zero, 0, 8); /* Zero 8 bytes */1 Pshort = (short *)&(buf[sizeof(struct HEADER)]);E size = SWAP_SHORT(*Pshort); /* Size of the IP address of terminal */( *Pshort++; p = (unsigned char *)Pshort;; Pshort = (short *)(p + size); /* Advnance to next field */H/* the address we receive is in the name order of the network we need */ if(size > 4) { #ifdef DEBUG9 printf("Address size %d is greater than 4...\n", size);#endif* size = 4; /* That's the Internet size */ }# memmove(&Socket.sa_addr, p, size);/* The port number */ size = SWAP_SHORT(*Pshort); *Pshort++; p = (char *)Pshort; if(size > 2) { #ifdef DEBUG6 printf("Port size %d is greater than 2...\n", size);#endif& size = 2; /* That's the port size */ }# memmove(&Socket.sa_port, p, size); #ifdef DEBUG9 printf("Got forward request for statiosn %x, port %x\n"," Socket.sa_addr, Socket.sa_port);#endif/* Do we want to serve it? */ if(allow_station() < 0) { #ifdef DEBUG; printf("Unsupported station (from chooser) rejected.\n");#endif@ send_willing(0, "You are not registered in HUJIVMS database"); return; /* Ignore it */ } #ifdef DEBUG+ printf("Willing to serve some machine\n");#endif+ send_willing(1, "HUJIVMS yXDM server...");} /*F | Reply to Request message. WillingFlag tells whether we will or not. */"send_willing(WillingFlag, message)2int WillingFlag; /* 0 = Unwilling, 1 = Willing */char *message;{@ struct HEADER *Header; /* To parse the header of the packets */4 unsigned char *p, OutBuf[1024]; /* Output buffer */ unsigned short *Pshort; int size;" Header = (struct HEADER *)OutBuf;! Header->Version = SWAP_SHORT(1); if(WillingFlag == 0)) Header->Opcode = SWAP_SHORT(Unwilling); else' Header->Opcode = SWAP_SHORT(Willing);(/* Now, fill the rest of the database */+ Pshort = &(OutBuf[sizeof(struct HEADER)]);- *Pshort++ = 0; /* No autentication string */F *Pshort++ = SWAP_SHORT(strlen(HOSTNAME)); /* Now we place our name */ p = (char *)Pshort;' memcpy(p, HOSTNAME, strlen(HOSTNAME)); p += strlen(HOSTNAME); Pshort = (short *)p;E *Pshort++ = SWAP_SHORT(strlen(message)); /* Place the message now */ p = (char *)Pshort;+ strcpy(p, message); p += strlen(message);-/* Now, fill the size and send the message */- size = (p - OutBuf) - sizeof(struct HEADER);# Header->Length = SWAP_SHORT(size);$ send_message(OutBuf, (p - OutBuf));}/*I | Another step in the protocol: After we afreed to talk to it it asks usI | whether we will handle the future managing request. If it is listed in | our database, ack it. */handle_request(buf)unsigned char *buf;{ int i, count, size; unsigned short *Pshort; unsigned char *p;( Pshort = &(buf[sizeof(struct HEADER)]);/* Do we want to serve it? */ if(allow_station() < 0) { #ifdef DEBUG, printf("Unsupported station rejected.\n");#endif* accept_session(0); /* Will reject him */ return; /* Ignore it */ }//* We do not support server different than 0 */ if(*Pshort++ != 0) { #ifdef DEBUGN printf("Requested server #%d. We support only 0.\n", SWAP_SHORT(*--Pshort));#endif( accept_session(0); /* 0 = reject it */ return; }&/* Accept it with no further checks */ accept_session(1);}/*+ | Allow or Deny the other side to continue */accept_session(Flag)&int Flag; /* 0 = reject, 1 = accept */{@ struct HEADER *Header; /* To parse the header of the packets */4 unsigned char *p, OutBuf[1024]; /* Output buffer */ unsigned short *Pshort; int size;" Header = (struct HEADER *)OutBuf;! Header->Version = SWAP_SHORT(1); if(Flag == 0)' Header->Opcode = SWAP_SHORT(Decline); else& Header->Opcode = SWAP_SHORT(Accept);(/* Now, fill the rest of the database */+ Pshort = &(OutBuf[sizeof(struct HEADER)]);/* In case of accept: */ if(Flag == 1) {1 /* Asign all sessions a cardinal number of 1 */+ *Pshort++ = 0; *Pshort++ = SWAP_SHORT(1); p = (char *)Pshort;' /* All authentication data is zero */) *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0;) *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; } else { /* Reject it */' p = &(OutBuf[sizeof(struct HEADER)]); *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; *p++ = 0; }-/* Now, fill the size and send the message */- size = (p - OutBuf) - sizeof(struct HEADER);# Header->Length = SWAP_SHORT(size);$ send_message(OutBuf, (p - OutBuf));}/*F | Here is the real action: The other side wants us to start the loginF | session. We do it only if it is not started already. There are suchJ | "false alarm" after the login window closed and before the real session | windows are opened. */handle_manage(){ int i; FILE *fd;5 if((i = allow_station()) < 0) { /* Not authorized */ #ifdef DEBUG> printf("Request to manage from non-authroized station %x\n", Socket.sa_addr);#endif return; /* Ignore it */ }& if(ManagedDisplays[i].Started != 0) { #ifdef DEBUG? printf("Already managed... (%s)\n", ManagedDisplays[i].Name);#endif; return; /* Alreayd launched. He should wait patiently */ } ManagedDisplays[i].Started = 1;(/* Create a file to spawn and execute */2 if((fd = fopen("TEMP$:TEMP.COM", "w")) == NULL) { #ifdef DEBUG" printf("Can't open TEMP.COM\n");#endif return; } fprintf(fd, "$ SET VERIFY\n");9 fprintf(fd, "$ SET NOON\n"); /* Continue after errors */_ fprintf(fd, "$ PROCESS_NAME = F$EXTRACT(0, 15, \042%s\042) ! Set process name to node name\n", ManagedDisplays[i].Name);4 fprintf(fd, "$ SET PROCESS/NAME='PROCESS_NAME'\n");) fprintf(fd, "$ SET PROCESS/PRIV=ALL\n");E fprintf(fd, "$ SET DISPLAY/CREATE/NODE=%s/TRANSPORT=%s/PERMANENT\n",9 ManagedDisplays[i].Name, ManagedDisplays[i].Transport);P if(ManagedDisplays[i].WhichLoginProgram == DECW_LOGINOUT) { /* Use DEC's one */4 fprintf(fd, "$ RUN SYS$SYSTEM:DECW$STARTLOGIN\n");# fprintf(fd, "$ WAIT 00:05:00\n");Q fprintf(fd, "$ INFORM_XDMCP_LOGIN :== $%sINFORM_XDMCP_LOGIN\n", ETC_DIRECTORY);D fprintf(fd, "$ INFORM_XDMCP_LOGIN %s\n", ManagedDisplays[i].Name); } else { /* Use ours */T fprintf(fd, "$ SPAWN/NOWAIT/INPUT=NL:/OUTPUT=NL: RUN SYS$SYSTEM:DECW$ANNOUNCE\n");A fprintf(fd, "$ DECW_LOGIN :== $%sDECW_LOGIN\n", ETC_DIRECTORY);Q fpri@v~ TFTP_XDM.BCK+i[SYSUTIL.DECW_LOGIN]XDMCP.C;114_3}!ntf(fd, "$ INFORM_XDMCP_LOGIN :== $%sINFORM_XDMCP_LOGIN\n", ETC_DIRECTORY); G fprintf(fd, "$ DECW_LOGIN %s %d.%d.%d.%d\n", ManagedDisplays[i].Name,Y/ ((ManagedDisplays[i].Address >> 24) & 0xff),E/ ((ManagedDisplays[i].Address >> 16) & 0xff),|. ((ManagedDisplays[i].Address >> 8) & 0xff),) (ManagedDisplays[i].Address & 0xff));nL/* If we couldn't make a connection (error status) then free this display */# fprintf(fd, "$ wait 00:00:30\n");A* fprintf(fd, "$ INFORM_XDMCP_LOGIN %s\n", ManagedDisplays[i].Name); }G/* Get the filename of this procedure (including the version number) */c< fprintf(fd, "$ PROC = F$ENVIRONMENT(\042PROCEDURE\042)\n");-/* Delete this specific procedure instance */|( fprintf(fd, "$ DELETE/NOLOG 'PROC'\n"); fprintf(fd, "$ EXIT\n");D fclose(fd); #ifdef DEBUGJ printf("\r\nStarting login process for %s\n\n", ManagedDisplays[i].Name);#endif# spawn_command("$@TEMP$:TEMP.COM");_}Ihandle_keepalive(buf)gunsigned char *buf;e{e@ struct HEADER *Header; /* To parse the header of the packets */4 unsigned char *p, OutBuf[1024]; /* Output buffer */ unsigned short *Pshort; unsigned int *Pint, SessionId; int size;!printf("Answering Keep-alive\n");e( Pint = &buf[sizeof(struct HEADER)] + 2; SessionId = *Pint; " Header = (struct HEADER *)OutBuf;! Header->Version = SWAP_SHORT(1);L$ Header->Opcode = SWAP_SHORT(Alive);(/* Now, fill the rest of the database */& p = &(OutBuf[sizeof(struct HEADER)]); *p++ = 1; /* Session active */ Pint = p; *Pint++ = SessionId;n p = Pint;- size = (p - OutBuf) - sizeof(struct HEADER);V# Header->Length = SWAP_SHORT(size);t$ send_message(OutBuf, (p - OutBuf));}o/*- | Spawn a subprocess with the given command./ */rspawn_command(string)c char *string;{c struct {f short length;o short filler;<) char *address; } command_desc, NLdesc;< long status;u char NL[] = "NL:";l/* The command line */ command_desc.address = string;l command_desc.filler = 0;& command_desc.length = strlen(string);'/* Create a descriptor for NL device */m( NLdesc.address = NL; NLdesc.filler = 0; NLdesc.length = strlen(NL);F status = lib$spawn(&command_desc,&NLdesc,&NLdesc,&1,0,0,0,0,0,0,0,0); if((status & 0x1) == 0)< printf("Can't spawn: status=%d, length=%d, string='%s'\n",( status, command_desc.length, string);}&/*2 | Send a message via UDP to the server's station. */xsend_message(Buffer, size) char *Buffer;0 int size;({  short iosb[4]; int status;9 status = sys$qiow(0, channel, IO$_WRITEVBLK, iosb, 0, 0,n. Buffer, size, 0, &Socket, sizeof Socket, 0);8 if(((status & 0x1) == 0) || (((iosb)[0] & 0x1) == 0)) { sprintf(Buffer,$ "VMS_TCP, UDP write error: $QIOW\status=d^%d, errno=d^%d\n",  status, (iosb)[0],v (((iosb)[0] & 0x7fff) / 8)); send_opcom(Buffer);e }}/*I | Check whether the station is listed in our database. If so, return its 1 | index in ManagedDisplays, otherwise return -1;} */allow_station()a{l int i;;1 for(i = 0; ManagedDisplays[i].Address != 0; i++)17 if(ManagedDisplays[i].Address == 0) { /* Not found */t #ifdef DEBUG? printf("Request to manage from non-authroized station %x\n",  Socket.sa_addr);#endif return -1; /* Ignore it */  }m elsecF if(ManagedDisplays[i].Address == (SWAP_LONG(Socket.sa_addr))) break; return i;}P/*> | Send a message to be broadcasted to the operator terminals. */Ysend_opcom(message)pchar *message;{d! struct { /* String descriptor */s short length;N short filler;I char *address; } command_desc;a char line[1024];P long status;h #ifdef DEBUG printf("Opcom: %s\n", message);#elseuC sprintf(line, "%c%c%c%c0000%s\r\n", 3, 0xff, 0xff, 0xff, message);)A command_desc.address = line; command_desc.length = strlen(line);e command_desc.filler = 0;o? line[4] = line[5] = line[6] = 0; line[7] = 1; /* Request #1 */  sys$sndopr(&command_desc, 0);#endif}hB/*======================== MAILBOX section =======================G | This section is used to receive a message from a sucecssfull sessionAI | initiation. We then clear the Started flag for this station as we know5@ | that the next ManageRequest will be after this session death. */ /*F | Init the operatore's communication mailbox and queue an AST for it.I | the mailbxo created is accessible by everyone. The emulator checks whop, | is the sender in order to protect itself.N | The mailbox is temporary and it's name is defined in the system table. This? | helps us getting rid of the mailbox when the emulator crash. */finit_command_mailbox(){ 4 long status, mailbox_ast(), /* The AST function */E CrelnmFlags = LNM$M_TERMINAL; /* FLags for logical name creation */  static long Length;( short iosb[4]; /* IOSB for QIO call */> char DeviceName[64], /* To get the name of mailbox device */4 ErrorMessage[256], /* Write here error messages */ NameTable[] = "LNM$SYSTEM";)" struct { /* String descriptor */ short length, type;x char *address; } MbxDesc,, NameTableDesc = { (sizeof NameTable) - 1, 0, NameTable }; struct {a short length, code;d char *address, *ReturnLength;l } GetDviList[] = {8 sizeof DeviceName, DVI$_DEVNAM, DeviceName, &Length, 0, 0, NULL, NULL }, LogicalName[] = {.= sizeof(CrelnmFlags), LNM$_ATTRIBUTES, &CrelnmFlags, NULL,% 0, LNM$_STRING, DeviceName, NULL,s 0, 0, NULL, NULL };(/* Create the logical name descriptor */H MbxDesc.address = MAILBOX_NAME; MbxDesc.length = strlen(MAILBOX_NAME); MbxDesc.type = 0;+/* Create the mailbox as a temporary one */ A status = sys$crembx((unsigned char)(0), &MailBoxChan, (long)(0),=1 (long)(0), (long)(0), /* Allow access to all */=& (long)(3), /* Access mode is user */ &MbxDesc); if((status & 0x1) == 0) { sprintf(ErrorMessage,i5 "XDMCP, Can't create command mailbox, status=%d.",I status); send_opcom(ErrorMessage);e exit(status);  }'/* Get the MBAnnn: device name of it */A status = sys$getdviw(0, MailBoxChan, 0, GetDviList, 0, 0, 0, 0);i if((status & 0x1) == 0) {M sprintf(ErrorMessage, "XDMCP, Can't get device name of mailbox, status=%d",( status);i send_opcom(ErrorMessage);( exit(status);= } DeviceName[Length] = '\0';C LogicalName[1].length = Length;L/* Define the logical name poiting to the MBAnnn: device in system table. */C status = sys$crelnm(0, &NameTableDesc, &MbxDesc, 0, &LogicalName);n if((status & 0x1) == 0) { sprintf(ErrorMessage,/J "XDMCP, Can't decalare ma .ilboxes's name in System's table.status=%d", status);/ send_opcom(ErrorMessage);  exit(status);) }!/* Set the write attention AST */,* status = sys$qiow((long)(0), MailBoxChan,, (short)(IO$_SETMODE | IO$M_WRTATTN), iosb,9 (long)(0), (long)(0), /* This is NOT the AST we want */($ mailbox_ast, (long)(0), (long)(0),# (long)(0), (long)(0), (long)(0));6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) { sprintf(ErrorMessage, D "XDMCP, Can't queue AST for command mailbox, status=%d, iosb=%d", status, iosb[0]); send_opcom(ErrorMessage); exit(status);t }}s/*N | This routine is called in AST mode when there is something to read from the8 | mailbox. It reads it, and re-queue the attention AST. */Llong mailbox_ast()B{  long i, status; FILE *Ofd;: static unsigned char line[256]; /* Buffer for reading */3 static unsigned short iosb[4]; /* IOSB for QIO */H5 char ErrorMessage[256]; /* To send error messages */ #/* Read the message from mailbox */ * status = sys$qiow((long)(0), MailBoxChan, (short)(IO$_READVBLK), iosb, (long)(0), (long)(0),e' line, (long)(sizeof line), (long)(0),a# (long)(0), (long)(0), (long)(0));a6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) {H sprintf(ErrorMessage, "XDMCP, Can't read mailbox, status=%d, iosb=%d", status, (int)(iosb[0]));R send_opcom(ErrorMessage);Q+ } /* We ignore this un-readable message */c else { 2 line[iosb[1]] = '\0'; /* Delimit the username */A/* The message is the station's name. Look for it in our table */ 2 for(i = 0; ManagedDisplays[i].Address != 0; i++)9 if(compare(line, ManagedDisplays[i].Name) == 0) break;e8 if(ManagedDisplays[i].Address == 0) { /* None found */J sprintf(ErrorMessage, "XDMCP, Station '%s' not registered in database", line); send_opcom(ErrorMessage); } else { /* Serve it */s7 ManagedDisplays[i].Started = 0; /* We init it now */m }e } /* Re-queue the attention AST */* status = sys$qiow((long)(0), MailBoxChan,, (short)(IO$_SETMODE | IO$M_WRTATTN), iosb,9 (long)(0), (long)(0), /* This is NOT the AST we want */ $ mailbox_ast, (long)(0), (long)(0),# (long)(0), (long)(0), (long)(0));s6 if(((status & 0x1) == 0) || ((iosb[0] & 0x1) == 0)) { sprintf(ErrorMessage,iH "XDMCP, Can't requeue AST for command mailbox, status=%d, iosb=%d\n", status, iosb[0]); send_opcom(ErrorMessage);c }}n/*M | Case insensitive strings comparisons. Return 0 only if they have the samel | length. */@#define TO_UPPER(c) (((c >= 'a') && (c <= 'z')) ? (c - ' ') : c) compare(a, b)l char *a, *b;{n char *p, *q;n p = a; q = b;- for(; TO_UPPER(*p) == TO_UPPER(*q); p++,q++)G) if((*p == '\0') || (*q == '\0')) break;)A if((*p == '\0') && (*q == '\0')) /* Both strings done = Equal */* return 0;t/* Not equal */a% return(TO_UPPER(*p) - TO_UPPER(*q));y}|erminal (probably the other host ran the chooser). Get the client's' | address and send the willing to him. */handle_forward_query(buf)unsigned*[SYSUTIL.DECW_LOGIN]XDMCP.OBJ;1+,r H./ 4P -i0123KPWO56uo7Go89o^GHJ,2XDMCPV1.0 6-MAR-1994 11:51VAX C V3.2-044 PSYS$MANAGER:XDISPLAYS.DAT Pr PCan't open SYS$MANAGER:XDISPLAYS.DAT APMAX_DISPLAYS too low. Raise it  aP%s %s %s %s mP%d.%d.%d.%d yPINET0: PVMS_TCP, Can't assign channel to %s: $ASSIGn status=%d  PVMS_TCP, Requesting local socket error: $QIOWstatus=d^%d, errno=d^%d  PVMS_TCP, Can't bind; $QIOWstatus=d^%d, errno=d^%d  1PTFTP: status=x^%x, iosb=x^%x NPYour autentication protocol is unsported. xPYou are not registered in HUJIVMS database PHUJI XDM server manager. PYou are not registered in HUJIVMS database PHUJIVMS yXDM server... PHUJIVMS PHUJIVMS PHUJIVMS PHUJIVMS PHUJIVMS &PTEMP$:TEMP.COM 5Pw 7P$ SET VERIFY  EP$ SET NOON  QP$ PROCESS_NAME = F$EXTRACT(0, 15, "%s") ! Set process name to node name  P$ SET PROCESS/NAME='PROCESS_NAME'  P$ SET PROCESS/PRIV=ALL  P$ SET DISPLAY/CREATE/NODE=%s/TRANSPORT=%s/PERMANENT  P$ RUN SYS$SYSTEM:DECW$STARTLOGIN  ,P$ WAIT 00:05:00  =P$ INFORM_XDMCP_LOGIN :== $%sINFORM_XDMCP_LOGIN  mPUTIL$: tP$ INFORM_XDMCP_LOGIN %s  P$ SPAWN/NOWAIT/INPUT=NL:/OUTPUT=NL: RUN SYS$SYSTEM:DECW$ANNOUNCE  P$ DECW_LOGIN :== $%sDECW_LOGIN  PUTIL$: P$ INFORM_XDMCP_LOGIN :== $%sINFORM_XDMCP_LOGIN  &PUTIL$: -P$ DECW_LOGIN %s %d.%d.%d.%d  JP$ wait 00:00:30  [P$ INFORM_XDMCP_LOGIN %s  tP$ PROC = F$ENVIRONMENT("PROCEDURE")  P$ DELETE/NOLOG 'PROC'  P$ EXIT  P$@TEMP$:TEMP.COM PAnswering Keep-alive  PNL: PCan't spawn: status=%d, length=%d, string='%s'  PVMS_TCP, UDP write error: $QIOWstatus=d^%d, errno=d^%d  KP%c%c%c%c0000%s  \PLNM$SYSTEM gPYXDMCP_MAILBOX vPYXDMCP_MAILBOX PXDMCP, Can't create command mailbox, status=%d. PXDMCP, Can't get device name of mailbox, status=%d PXDMCP, Can't decalare mailboxes's name in System's table.status=%d +PXDMCP, Can't queue AST for command mailbox, status=%d, iosb=%d jPXDMCP, Can't read mailbox, status=%d, iosb=%d PXDMCP, Station '%s' not registered in database PXDMC MAILBOX_AST SEND_OPCOMSPRINTFPRINTFFPRINTFSSCANFFGETSFCLOSEFOPENHANDLE_KEEPALIVE HANDLE_MANAGEHANDLE_REQUESTHANDLE_FORWARD_QUERY HANDLE_QUERY SYS$DASSGNSYS$QIOW SEND_OPCOM SYS$ASSIGNSTRLENINIT_COMMAND_MAILBOXSTRCPYSTRCHREXIT ALLOW_STATION SEND_WILLING SEND_WILLING ALLOW_STATIONMEMMOVEMEMSET SEND_MESSAGESTRCPYMEMCPYP, Can't requeue AST for command mailbox, status=%d, iosb=%d KPΤ^C$MAIN U S [ ZߥeFOPENPYߥPRINTFEXITVY<~FGETSP1 SSCANFXSTRCPYWPVߥAPRINTFEXIT STRCHRP`\\*1ߥahPTT1߭߭߭߭ߥmhP{ŏVRBcQxPʏPx\ʏ\\Px\ʥ\\Pˏ\P\aB\lBgBHgT BÈ\l BÈRbVY<~FGETSP1YFCLOSEŏV\LcRbINIT_COMMAND_MAILBOXߥySTRCPYSTRLENP|~? SYS$ASSIGNPtPŀSPRINTF~~~KSPRINTFSTRLENP SYS$SNDOPREXIT|~|~|~j2<~ SYS$QIOWPVV 0: Nhi1MEwOIL?pU|/F}y'w'r!{Z"~%-C"H.si/|Y9n*45$&v Z0Hm:W}@,pqsP FT&,]oh? y 7F}%8Ta>$wjw^7[Gm 7VZVv% U"[2m*S851mJ[w $ <7; f~@ 8qyN>б7,]%RHdeno"e6)cBXWwv!-u&4!8t/Y{^!$U=Z##yEUNGo)2h?;maQBB"0 NHd+T$%=j!b4/#c6n<Kj=",/`?gAZ#}~!#$ J0DAw_:1O/G G:HBx,nj 펐WaO]C ~vD;k"0e[ElG m*q/5#-֨*q|G K:"PfQTa9P(7#!Uaevd^D F 3.LSMW1J >GL/CK<]-U^BP>e36[[F[J:tS*p,ZFQP[k-I.Y&)\$ ]\_2-OkY KRqM&p3h?&X  !][=\, ,6?.qDjd<THPC+ L E/%&w(D@NV Ctc|_ ! y6GaG`Bqas,CL=Qv_Yj+r1!(!:ox!@1fn2 AH\DDmWrid+lLR~RAr*&()'BAe, k(B[ "i TT~mrAt~+ G@vzMCo3zz%i\"3kA&+^,}|dupQ%Z\!C jFsLMo E(E)3= bIB"w{m;\EHhN A xWvTz7{ !|L^'=UB{5@ P[` 6 @C>'dMlG4o`' c$?&L RQ CP*6jF:Z_Q_ViOpesg~X U7aGO8-l$GHUx"LKwbnfRg3JH t 6p51DFWapFD'8(5O^C2sE&:`0VWpzj{?T:T"I'9LHV7^'x_ZPH Y0 T [HJbtn>3 pWG}V@B{eB5'9o GZ;ZC %q Ntu!!:_)`v+Al;r16- \&9vbbI{oB{  W5tVRIpI52S^'Vj B 1kyV;N`g-1 Q$&\1/iD%yr#5U7[ `g|o[A_5P @X $8hAcaHP)<"]&sxtb2 f'h|p;'eG ,YcRcl0jXza d,+2<=enJ @P}xd yNXq7JK\XG^mUKId9/5Uvp~j *@mx[GgGAWLA V\S+"Mk;_T AZd*m.+2s%MH}5(%J AlL *"zZ?B ]HCr_YgJ FJU~n4MMAAq WSV81*WcX|-4XkTOGOB[ HXDbqg A rHL>N |XS!54T\mRc&y_-lUy48 h&B7(M:*`Cb V>:[eXc@rt!8h&@bKs*a]k%tes=gɁ;?'/?`?DJRVp+ĕX=h Q[\Gt+IqvYIy33hM[FaW`wU*FuDA]F:qJI x1W RJ'Wp]X5>PWX!e@vdJKE{^q>(}{2MB&23C?VAvՎSTHL[z]yTUqP#_L ~h`hb#e:73d.WsjpKg[:gSMOl TR2_QY"&2Q]]jn\OrXe 4Q3 ,GPlvW;N9E-_ppn>B\Z z:D9d5FU0 !?c9a;g'LoOU#Y=DCӬc ;cW~/W2f.L-AqY%wf5[#/j&NZoKVipc.(e^dFehEic(zOO l /aXpM|Iѵ=<&E T#G^H )6!8;3'Du t\x#=FB{ :}s^uyN|9"vFY~m+6Wd.Nv)s>2-vPwTIlzXXfn./E%[yE]fJ)]u> ILPz`qsCw-Ux#U"4&G'/4N` Yw=eТ-CpyTK2vKBaDWrG5$.g2|o;aKe\!}.sC@O\p,JYHA 8;Ub0u^MP R[Z1 VCU4"WY}-*Yq/h"@*3[y5GUlG:s>vqbCDh>dea^`)kXM4_UF c":vwm8{+;euV ?Sev ~HdS.o#UDevOHj>&7~RiYoPF\"{`֌}VJJ 1{PnDTd xZM%*dv6|$kuzD2Y_0FKdVHVR}j .=6 TLSJ|wU 6 d*NT>tmG (.>?ilI9`W}.^C3R* =@YA/?4 5*.^(R Y?mv\R+w5 l3)t"YOU.f2k 6l4U@ #7P$(5s5EmBkIJd`JI}$/$ *pR%D>2!fOQ+ huq~; %1/g%_xU B+{D|2u>Fbr8y[6 }]p\q\U2 5>A1[%>m3 <.fIT&SzuC=hhny4QE>Jy+9{wpi8V}hptF(_W+JoDi#<OZCk9T<~}Cxdwo stH%aNEFTXzk^(;DGZq;OHy'cgw+sl;| 8h"$$(*S5=:_9C [C@ITZRlg<X]UN-F7/}Y3uGnr-F.|g%ELQbW6:2 !<(S"cx0$D2&6@v}^a.T<"5[1R$Tp<pD1 2 _jQ5 ebXA(\l FzgS6q,yg?r&GLOzk>jz=+(3o1-aY_JYj"3,C.v=[u - PD/PwgMqP .hUxu#5&=$En#k<(2\(8 KmPL%:WM%Nu+B,8pH)Rv"[X1dKv&kt[y34:+ Tdo0U]\QqRLVF^S>x -1Z;k< 1E~kC_yA~IO͛/=GC&6~\Gm0]-Z.Vk\W2KMJ FiyMxFNa:%+2bzMd3n~:>cgLg _iQzhcdX@sqx 9<,H .)G$txw j1rsI^Tt QTm{Ujrvd <.I4g5Rc\tT!C+'Q-XpvL@9pW5Ta\~0!4 &# <.TH0V|GH%<zJe0,hIX Q76 ${}&zYk5 ?O &zxo=[*|uPam!AWr&.g/_,\WD?.QL^U~\SON 4]HWt%[x!` 7`d5h #Vo-$+N )&IUI78*Qszg Naz4S)Gus@HS (IFD\yu_SAR@!X_e8+X9I,z(TV6Aa _+O_y"J^mW qY?8V YN-HJHX6wb;}(LFU6`WQ:'bn *@,{^eN '.n2]ZE*;U46lF_ZlHa|:;}h`h{0WQ2lH}N^9ltWEm&Wy)>0%.@79`nALKmy]i=/aSjbBh^]M%|>zMI@{QvqFlEClpNOnd_\^]P8xI3 d;83uxFvz37-t) 7=# x"a(41U6n*/&lv~{ 4w#!tr,*~ MEYuH@BcEL}IRWI|k/ea[xFq3<Lg&y-O4+=`|CM6zg-0* l`CGJ8?&P j?QS/$Uk:*^(*Di)L8*ewFRSHq-I 8pO<576>kRUc`x{BRJzs=8dg-H')s}Uo!-Sv7(wL#FN[ YWe 3^wZ>"#;g|z0tn;i2`su++zPO)aV(glXb+%NRu 1F7}o>5uNh;J4 5wfgesfhJyR 9e/T,?Lpg{gqwuL_QhFv$p>u bO;g;)>Ky] gUfbpw* (v1[1vI<3/ k~qqXip>~T;\OM"=J'2 GsiVz@% H ISceg$$)zV~V"eKeNZEo2E$-AO-M1n9" G/ M[s.M  !v)@q\<.p's }? 'U?=yGfc= xg,Df1JeJ'Lpawa @e3j2]d fE'\[&[+N=izwkY^=!2M$0/jZ9zpnfIQ0=w7s.kXNcDsNLl50 ^!"^`DLDDmm?\,9;WrLhb,>0s(^`|(M|KVph +y7 F k 9Dzi7:%0Cx =}Z|X{)vF[mKdJ]X-n:arh)q <>> C-ByC,8fhRF#)UhJbe5:mCue 4 asz{r62 mcpP;P`:V@[MNJ09"Jt!)JlT {SWPMJqkc!:/#;>]Y/s^%#qi5m r/au6%(w1z#ub C/nu=[cM/=KF_v[A!p d_0o"ogwYfCJw|`aSVD}BMB?{ym]QP VMO3kbT4(:YS@QOcC l1yXett2aA8-}0e 5wCEE5 %O\!L NbW cV!ob*2RH/UGj_br-~P1lE #GjbPFL `$Bc C3bP#q|y9 zhoBlsbj; -;mSac j:Y2hu58%sF_*-l OwNc<H+;LAQ]XK\^e&`fNR"R@}kdY0\n-y|h"Gx\l GU$ghefJy1!<\q%%AV=U[[&s:~CC- :=72app9UadnP MR<Ux; j2JcEEm:PK I(YZ)@;NGh?Bw<S4y$FAA9 ~N]v3F%K[B%&e Pmx|GK.x{1xCܤ?W^q(Jp{ucAt#a9 vdH;}\%6g1BGA ffI`\CNO3 fJY`2c'%óK$WGRq (1DŽ0*BQ.*'^gPJ2sv4pF)Pa((eSK@?i]A d>qOS|?O}zo}xpj9{k`"^{-{Q>J541~V1nj~>Cu>E4}l`oEG%OL:*Fk1m"k,vjy9_( W{#&>B}GL!MKr5!?C4b{.#J?"42A};m"92&4Ex=Ah! i8 .H8}JvvXDu_BC%MVN~AeL'?=_n|_Y判3h!@L2eqV??&k '($z?<\!lz &_^o< >\Y(}ĥtbM1>cB|yBF@B  Dddu)^uy)NO`?g_lPr8*Uz7wz1G׵ R:'Z6ys{ LvE~oRW:+C{}Hq-i$)`Kz%0g6}e- gV;5|Oo6@^`zs'7%'QIAig9-L ~3b9%W`(v$.M| DvyY OT6}_M`v7+y&3}4Ik$FZa (4 vpU)ewYBhEjvbAg U&y/Y.-y a@3IVbLh}-TWi4._KQE|*3&9!M)cP`DTb{D)M9wL|qI'"*9[ tu+D*j2s~h@e68+y)w"J^"[Yyi %5Q\%bHHjzc}5],7`}v2V[or#ZcF)Pm:!`8Rv:*{;yW[@F/ %Ha$qCa !$By$6g&3RhL#fS_ tFIR -'4)VruAA}x0{`= 89`*"Blny)a5(1Jx2IDOTq]%ueک~b4w"W#i{-@vE;8xe3 l8U;'hLB?יQ?`R@/do-96n=QA#0+xV dRUb!F0L{[mn >ƊyFP Psg_=bEe)N&82;Y_U1V'Wqc7:f_N^|=+a`]`/ T^[f#d {vblBDTEQ_e`#&VVQUR(O8t |WrUdL9S.xU+D'4vYI?A";ng,>17mG;e$5io4.r=:q+9X,`x+D8H}"5{X]`G[lh:t:T]l$_:,EYy[ <9YNl5Y]=J : [G#Q+$ (Rh[PÓD@@[:CjYZ#ZDGqM6bU~X`m]j#i/CB7?3|oFUgL[}Y_]8e}(d+"EEAOJOT!Dt{RvoH@\L%(+@ O9Q1OS)x$Toh]bR*yR]Q g&m}1i.fN^"UJN[p#D&"Oo c: KgT=wh1^\q~Mhtu~e ,J@SWSL@aJiqeP %9J=a}Egl"QZS0I Tm slQ0{`c#-*#b|)~wjA^ S'8#HT)A-Z6%=}U:xk `ŎQI(yFe8yry$xʯ:%@!P.2uO,g!MB@'5d{9Yڱ<ބj!`dL)s&1G %\T\]zJ_y<7twa|uu|p6 E;6=X-}`Ĉ##{|h,n'Ʉ>t|.dysfI CQoP=̼ P{+yVjɋW-7Q`F2r8ÊCa^1s\BC%IQ Yo8Jt ֏ V:#/ob*ىdXgGO06h<G:$[^mecPTH燛})f5i8ZP{G )@*=zgne]$17=]c /a-EX 8jGQ wzvf]qv E{3y`NT:+>g4QM] "K3J`5tGÞ Sk` biBo[tݧpX}_~9j\<գ#˪'Ńg9i_#b$MyS@1R8ܮДTs,O(BXXFؗ25:s%Wܭ',2@r`@12 h~d &6 9auu/׉o(Y$Rg$}H`,☍ BrR^3Wm19V@]et&s)Lٔ6r:bVbpҢ&&|Q"<]s98'(Rvٌol`* yR/.nͬ7BP?LkŌe,P5y?DJ3T=GĐ__2/@&w+ͼu~W,& A<:hQW)zSզ7o&- <+M HNz21&zދ#(q"37oCeyxwPf<&n[=ć+a!DfPQ686FK;Q0E.5+` T~7qp2/͌Iv3D$2i/J<5Veg"#Dpغ׎'Iat(Z/}?a' ɶnۑVԐԜ5J7aRQzzQ6J=]Atnx5ؘ#ﰬn:93[]cz{TD*!X5&/dn)Xى}oIFp=9~з:XB+ a·ʝߛ< /}ã%PY{vZ&9[mms;Qdlp@ђs?67mܷN*KcJJ(0}h T :e&Kvj&x 37m?io<<{VZSF)zDQ #obVHE]h( dS:pπ'_1z{I8fmfNGxIM0?J6~"3 / /\I{[ \JjIȺ}@F&o#gu#!l!/%sS7钽ruۈ6>-$޲aR|vviPk%%o= {w HaG݀gWFc[:ݭ+4 #[w8"8o`^:ٙb!dK>;gٞhEoe_eF2_'=8gP&_w2hӄGF $*,6GyZY;ct{90뎕)! \erw2P)1$Oh*#cTMعAԍ)5>5vg?.-.kſykWMqeMi U;cUGrK?W$El| X-m $+JiYR]읉 TOC?\̜ A9GOnGOXbs&K._()k#rPH 6}3X[1{#_NuvnU Y|5US cH@{4U1QwnwN*@̧'SK>M "9w*Zo7Ui/OE}e GvQ'Q@=SCq0~XdYs㈓0x aN/OZ,p tpsܔ`}s4~ugBc\[l*+8+ @ܲEL6f̸YD.LTWafmHNN"' &SlzZӦUb:qc %XS_!NZr/=BcˋIK D GO?VEk񣹋%a9"g[/Z ,&} _QSk*=Ѹ lVnRֳ\4&b)g+esEZį2S&\ֶ2$+ G. 'G,>{UX"3t{\(pU$?D6[Xit"'OD,4]t. U' S4'Ye@P-8Md±\+5 *yFGCw?:G*?\|$?99( ]p=VP-nF||LyDi* T0zA2 <] HFb}1-yL_\c5g &75$1vl] ^^YA aUGI18+C){$lr#_om7@`q=ff]2L`\RtI3'l &Xr|f; >|қ8d>3k>z Ov.! XkG#ToК4 L v8XZU) fi<wl'Yn"[s1kN"o!Miϙ=@_چ42c&MuB[}l[Dz @d(~춻%V*4w\:Y6(\3o|䧻́=n0"t(tw&*{X>]Eï68 Thhk4zx39{IWn)G}F=+;}rsS ~z% q76؁C!UQm֣?3e% FڒQSqxA{d}./-&5%-9#,f9o&3}Foa61bjac/W;; ͯgED} uuk S D# ~mNq;m$`0ۆzHYE+kBnnR/ɇ/l;e cMkc_('YK&aK=E?މ*Wm}ĸK%J&;;w!Tu(,ѦGr" P` $wמ)Á،p8bGsJ&iy>#78^ ΗiX,4k929w@_3 .}+2kC}{wr>2Ż[R0WǾg!VlJ]nP0e41>F$B'-Ձ%zDiyr pY$tEht iH_4` RAb9t4ݦٶqm!Y08r_I#Lgo΂bKٶ x/fS؎ 哋ۏ"LCk#s V"P;AOn]z|$,v$/H>>M9\U,/HPy:V@f=qǒ|KCn!JXmVJʀaQΩna*%aq Xe+ē(F}@1ȮQ^ֈRZoG3;Μ,od1yvq:MJ&Pt[z$DS&-]a*'Cڎd1Y9{v\䱬>Pcd;8k?r'L œ򭧩ӘL9 R;jEU >‰LJ 30o3pt;Dz,<WS \$4nz4JWnO"7LY Gc31Gxҫo ex_=stF}C+]&b8>XL4Ƹf wp+GJyX"K٭oS\\[]| Z^Qu0i~sӞ_|%O>{eQTxBp!󔄖lS8GjQ,7f_!Gy'}מTJJ`Mj ՀK65eǰXIoH5SL |]AHi5 ЎZ? }jȏ'Z '1UD%;M6Z֡ i`S)ٲ(xUy"`# A9 ΎvMe5J@55<{uH_=RrtC!CW TX]Ό'^ -ʅ 2z^_ 2mµt}-A |~[`9b"~_I [}>;'#"OZEKP#3v-m2S#YILa ^Y' K4alêa%DxIjC7:KbnCB&?Dr2ڏ&ԏĚ5*+9`/69g\By&X,- Y^ۊ [:HJT 娦$4@t4BqeEw]uY` L4rk.G1~Llvj)TzJ9sRƪ =7EKbk Eಾfp(WlLQHg4>e>>fR,k%WEm&1xqY+ uEvG[D2z3 kuDOZnʷ 1 J8x@5YGw1 aps J)6@XG5cw84rUnBy4XBixw-^: /ǰ]t8 ESn&&C:lY}P &W[bnÉ"p[ Z^_p^4'XbwSZ]~ Fl!jL (\y 9TqUPT+`Kwz"w̩WZ5`,H:iِonبƠ=Y ضap787%&ޠ[-I,ODAĺ:.wV|5=` cfz!Iz1p[0.sT0ùP-Agnv~"/q~'IgiqU@@kCآTMa@B(A*33ξ^! fCҎɲl 9ŷۏ59<ݞPbK?Ve΂DLʈ+f@xBV3"+}}` 3VCd#Ѳԇ@`j1d(up&6e7&֙;ѶGhUۆFA=La-9M$H^@m=LMum7c<,)U! kn}4&pp\-0„6;jhqq`d=C7:c-r!*n.1bC:{9 id}èby,2;qAx>#i/WB^cfȎPJ㦛1~3Õg_!i_װ7](K6 yjHx#>eKYda 9scIQ3,PGSi[(KP(W. jP5`I11zO9W6@,!'S!fTR5 |0W|ֺuUOJEvsR+x Maa#"9a-7@J!SՇA7mF6z)=,b6+&,bLsE}5FKQ-%OI`` H#eFL) gj2( JKV 8D({je|1+s \E1Pv_KJ'$:%jELpЫfWC GlG3RqI w@_#R?QF>pG/nE;vJXK8Xi >]z=-Hȴ 4ڄ|-B߇n*>Aknf CdO)ov3?'(j|`v3XY7EEcJ"[4v?X)FA7Y( ^MG*M7yCxOC#qR#, ԡ9cER= p>ȴ]Gv:A,^ D2 U<!!cI>)Wp@yƗ۽1 #_(K`|]*Ӿ9m͗@|-l 8Va&v ٬D*G2h-U}“OeET'P-"=Gơm8]ٻokM/+$O6)hxd޵.8Fw:@p#$pޡzolpP 5\J {7sb%dHh 3bn-'"gzl4v$Vd]$)(_FU1A%,EEjp|ExOHQ7#"08uWXw{0Y,t)"N C0wgC%xsm(>$iJn))R}sel,4ff( F V_N_u,bX u^_I[e̎ U[ =-Agkj,Ks CET%CFe\lagrsR@P[Bk] l4;%K9f={ekcǷzeO`l,AR@-_=WS_kE ]4 ) &pJ:YdN92czmxiC =5@y#a$in&` _m2m >A&(yKp@+\ D xbI]^6}_0{A}/+Q8&G &g4rw,ZX|YGCV){f:3p" z %zy@#{W~?]PP~Q@ ;0rGdo| $mb&*P$\+(.<~HTPZ"Td9vg _Gt,zxbS3(\{gL-vYi|>&4|lshX"R9[j{e#5J$eee(S@fq|DowqvCJ* Q52og?3|2e]}hSWpYIm`$X~!i*(MFEu|Pbt95fTe[S}H DZwh=&^TYIShqhv9,>b,xckti[0o! 3*"cwi)g{(D`N4m< Pq@i,oB@I5&sAM}H1w|COgB ({d1n*CSk]Z!3pD_9yo_@vi Cubp2B[Oqy_`{{|1c4X'I/5 P:^9$- 3Q#nd@uDJnvnoy 97em,+PW*cUNz/T}3 pvTkr  [DSB}] T~l@? IZCV;!Zy|{Ij ttWi.obdG5 Z 8(,D BJO|05\e l;H,csHQMT4ATy!QRUydm7oKx7>̶33rJFYIa7,5i+=NqZKEA;.&}w^sa4y,a~$"lpweB(#*OUxH>,}nhv] y~5,$-8-~aH_R"*gOt4^EV| Y?6?>/vk]`stu,S|ns+MX0@^VotRcVDq*,MlKQttzOHNf8k *\g/u/pQWjmtCirJ9%|5Tn~!V6^0Қ2PrblE- k!6O#Un-s=hT7R ~ZGnqS=Tf]S9r=&UC]=Hb (vvcRq\\ 4sa?3m<=)M oix]w8*''9{1g*aLY$`4eu(|$;zCck a~WXvnlp@ K:[,#kZq6ZbwkRd#wz lv.tvwGg|/8F8mCSMM5pQZh"xXm)+_;v4ɗO,ʀ4&$ .a& ?7pK!CMe>7j_f7vQ6ڕfHbyT<ڗFF"tLg3 ~olH=,pՏmEm5*Ptnd U,K8 +a*&d65MsD?94-v50!/5 SA)b$M߽sydi~|=%3-hV#9C&AzYT*WAMV(@AvnB!+k 4o'ue.`$=hTAW"nCP`8y1 6e5IP ?k@;]oH 4 0(lɔ@ j4)TKz1֝B"b8_8myѼs+!Eq@Uʒ,^s[GwvVeMFn9oJq7&- # FA+.ꂛ=xhS# Pz L;|vaʡMa.['C Ynb9mOMr&ur 7CBeT'CT9:3*e(%-_"̳5t*y9J VC_ s)2HZ.t3 Ja\y*nxl`Dlf ЅW~˃t$,i_#oǿ_fik.&:lihՅ"7>y\>ecMt}bmsJA6z&'] J(o'ZĺL3x16TSM&;^Sx ə$?,7٣97ܫCޕ̢1 n\sMj'$d* dO=D6pR`z))( _!H&`M`=lMl"Z)@PDyWx&At iP+ݎ![*}=o/V(|BtZ^$ɍҿM!dWs|pB 킍%³̻TPɁXJC i]s}lyEC T,d*O7:)S3jM?78ֹ,UI1Pc.@zb%e>w(t57Q mm^J,FzЛ֊NRV$B .U L^{k /K1) _\{}Kۻշ<] f|1._Fb @J_Dg{~k+ô qEBvM͎[W!H?|ڂ+/L?Ty~UZ/s+ 3gL6Ka/_N*2,3E xTB`IB<[yDXdD6|y/AF@eJL氢 YZt iR0PODv @J&Ν>o0\ݜJʅj9 Uaq}&@)2BtKq&ǕU/v0d,(VzhHlh捥T1EF.nIeP HyNg%V㦥 ?x0ڬUc k$|8rZ=565bdeMe9;'1wnm ,+-OP4&D] * qWxc:ɥ2Du#og(B2iTx ^b-ry/S(BBu7 *y:~ 0cUud_5#F\(Ui-3>SBE1_vrJR o~q_%r!5k" zA1j|ofwQNSQ;2$fG5f4orA2 PG59dcYu=6* 5I HE 8hwo ZvַV @n|ewpqH0Vu?_jl,}+!3a o$kPu>pm bCW:R {hE+P]9_U3d6 kf5'8PVVr{K$ ApchG@dKeTE,i|c+OGMe*&?isL8gTe},:G2XL1HE\nz7}d#Rj)CH#&O(IWddKһȪR!#w wjד1 `тAհ'\Us`Srfk#dPji`[iPk3vivuec9Tf b,\vOG_+zNe>Xk#]LGS]qtAq`(xK,n/~j(1j))eL{,q:N<} Xy! "\ |}Kcx%\kb}.^vo~(gOQYy"13Fh!&LLO,/-u6sNPYřwTKe 85Z54f "t,- p~ѶmtmfG=jRnibNg_-nmT4BZ6Sq>h\aXx+# \~,I™W ~& 0~-I Uy˽&s]U#c]VRx\q: V4K{0e&WWRJjhHvxz$\Cju&CB]|/CM?WpkF4)3׿K&#jok ]\Y Kiy_lʔ݋/{3B>ًrP^wvqMEGG})@}vI&$J;X0.,"^#`DnL%Z2"D~GҘdl!KQ`MȔ|P|xa?0xS3c"\XC?@TV[-, =#sOvr *",'=` eEMzT tqE^M.ZJleVAj~SgrujwuZ>l/[5<&/"7/p;FFX, eeKawf ɴ|Ս<5ZGFE0cJCGͳ[GR?{uKq r9 +eߥX{N dO=%nh_dOEtvC Ȫ7MM=q0mn *9,((;-O/݄__Xbqt~Ϫ~{K1u6(%V&$I~u 3U08Ԉ#sDVL PFHDETF#1R;.RܺO\Zjc)bܧHešrP]V Qy d%ʾ3B\4;Ogla$dr+Yz:N*Vi"QXohdG)`p Q|]o`lxN|(VZ3Q;N62FcSPGЪjfKYUAx5 B_ T,wezSS:5_XXH*q.TGp{d{q#5OApM@_HBTs*5 EZ6NKq WB1B?Xi1mG>QB6y 8v[ K@KQJ3LK鲪UO^Y-W|mFt;sO?MFIOmYgfis$ndB5.{78I N^y2ENr`V `{(CѤ8<>y3gn#O 4IGWv;;U-ZB/e6!SeH]?e ; p:@UGtQ)=H-+E>O):#~-g-?T8+_` q`N 9L$bcݥ{kH ̈HreкYTZoA-YSDkbr}_LFDt%=L]O,tD/fg-mn&z1>d!r؅ x uCǩ >mjRk_@)HڅsΘ?r^Jar˥/Cx^tvX RTV@3SꧢQs0cUK0W{p5@n) RGaga}15I!^eIl'/XD!dPPM +B٣\ QVRWV/W1yGJDڼn(,cPG`?/N GgF4nhQ8,X,5w#+ho2Nx@(%:o2g.M:vPFDai\ϖ:$^DrT4 0e]8BH lSobH &Mdu5#hG6zZV& ?Ujz sG< 6FD[!Z臣=Ѥf iqkq7Bcy~ Lʖ A 9\U6hvVf>f=-Q [s;>~)x\P #찰BHXC߰"4+A7<[KAz@+)+Dd+{W 2ӻT, 5.iwq7)2k7Ve1bQ!H;#ϰ<?&Y1Qm]9pIxP),[`,bn4;!& I}$,$FbJ<^H'" 1 8,,6%$~dn< !(aOtNFWW T2FB?AgC+._ ]xI8Nj}CS[cQjneR[)f'r4Z(f?CIJP$hV0"zTJ5Lxߥs1=Zc[W*Vv]y A&_@8^A*t1fmC%6"1l#k#np]'k)TR}AH~3iTjoW0eBFbi)G}T&wAM@/"#rP/jRk O0'@ BD p>Q~N~oQ5SvcJU zZJ~U2\^uHxK`F3TQ\ ]RAE)'>3562rv@8I=Y A_2 @Ptěb@u5< Nlx)j:L2pAo Wܞ"eQ=^0ny)\VSRJZ;+;}Sb5aa >:dDm;) -AɝXc 5f l{7!'R!CVmq__w B9Y'Mtz"=G~|,]&!V+r-QS4rT]n Z~^MgM.D!(W2j03biVFAkVol~Y5iGYӄk0vr$=Qw(=rak!OȿcٖOJ ??G** LJ6 $b|y< w^Y^J_p63=QGBܤ OR,~V'k>KBC<h|JYE2ggٰ7hr7dGy!m/z@mqAbk<.*MajXvNk5ѱ!9uzu(.Iޯ.H[ (6Y{PZf3hG 'A* c6 kG"5Q-Ew .&q롆sQf.#D*Tv"$>Gv+F2W2fnjkTjFSK~EJ\2$"Wga1!" '55D { 15&  $=s;,p5pG'Ran{gu'+ XuL})UDA-#A]=x9sqkEL#?ȔP\/^rB #**A[wB ,e~y9Lo& nEOikR6Ng 'nl{g}(]haIer_522ghqo!#M^;qw*3ExW% `تGx vEV ~TE̷+kea0 | ih[RB -eDR~Je'~q'iDO*[vj\M8}Owz^]1~@{["V00^(G YԄn[Cu#F WhYh}dCHhrr[06VT_g|,y*[]F p^ S.mƛjMk.@_"JJ]Ze^TahI~dL7Ke3! r#^hZ[j;! Vg@$p*`onjIt K* )~5[N1E-i)bn-{ iH?2#UN] Zp dDY'5gX3yxT2 v@TO=$z&JhfWb.0\)^dh '67)-e'n."Pn;M8k B_H;2xZ>&{%>}1EY\M py%  FY^T]Ho }al)}EZE*N]POHSTE TFF._)u)_8l V_T  fom`opSCZa<  9R  :.N%EBO:A FHetal)e ;y=LLOWED#  A/I4@71& N#CNMM |ig`dhed*-GN'@Ug(i})~`G _voy }"|)], )F SM@TU. ALF@wwdw  Sg)~InterNetAddress = 0; /* End of 0