/*---------------------------------------------------------------------------*/
/* ...socketDemo\server.sas */
/* */
/* A socket server written in Base SAS(r). */
/* */
/* It will run specific SAS programs based on the client commands: */
/* LAUNCH RUNTHIS */
/* LAUNCH RUNTHAT */
/* */
/* It will return specific files based on the client commands: */
/* QUERY READTHIS */
/* QUERY READTHAT */
/* */
/* It will stop the loop based on the client command: */
/* BYE */
/* */
/* NOTE: This code is informational only. It is not supported. It has */
/* not underdone a security audit and should not be used without */
/* review and enhancement by qualified technical staff. */
/* */
/* */
/* Copyright (C) 2003 Dymond and Associates, LLC, All rights reserved. */
/*---------------------------------------------------------------------------*/
options source notes noxwait;
filename _ALL_ CLEAR;
proc printto log = log; run; /* reset SAS log file */
%global launch loop thisroot;
/*** change 'thisroot' to match your directory ***/
%let thisroot = c:\datasets\code\socketDemo; [note 1]
/*** The socket server runs on 'localhost' port 5100 ***/
filename srvsoc SOCKET 'localhost:5100' SERVER reconn=0 ; [note 2]
/*** Files to query (client can request they be returned from the server) ***/
%let READTHIS = &thisroot.\readthisfile.txt;
%let READTHAT = &thisroot.\readthatfile.txt;
filename READTHIS "&READTHIS";
filename READTHAT "&READTHAT";
/* Only these files can be requested from the server */
%let querylist = *READTHIS*READTHAT*;
/*** Programs that can be run on the server. ***/
%let RUNTHIS = &thisroot.\runthisprogram.sas;
%let RUNTHAT = &thisroot.\runthatprogram.sas;
/* Only these sas programs can be run (launched) from the server */
%let launchlist = *RUNTHIS*RUNTHAT*;
/* In the 'query' section of the data step files can be selected for return */
/* from the server. Only allow files that physically exist. */
%macro goodfiles;
%if %sysfunc(fexist(READTHIS)) %then
if argument='READTHIS' then infile READTHIS end=lastrow %str(;);
%if %sysfunc(fexist(READTHAT)) %then
if argument='READTHAT' then infile READTHAT end=lastrow %str(;);
%mend goodfiles;
/*-----------------------------------------------------------------------------*/
/* The macro loop will run as long as &loop>0. The data step inside the loop */
/* will allow one new connection that will exist only within the scope of the */
/* step. Ending the data step disconnects the client socket. */
/* The data step waits at the line 'input' until a line is provided by the */
/* client socket. */
/*-----------------------------------------------------------------------------*/
%macro sassrv;
%do %while(&loop); [note 3]
%put STARTING SAS SOCKET SERVER LOOP;
%let launch=;
/*------------------------------------------------------------------------*/
/* Send log to server log file. */
/*------------------------------------------------------------------------*/
/*proc printto log = "&srvlog"; run; */
/*------------------------------------------------------------------------*/
/* Wait for client to connect, then read one line. Parse the line and */
/* bind 'command' and 'argument' variables. */
/*------------------------------------------------------------------------*/
data _null_;
length linein command argument $ 256;
infile srvsoc; [note 4] /* point to server as input file */
input; [note 5] /* wait here to read one line from client */
linein=left(_infile_);
linein=substr(linein,1,length(linein)-1); /* trailing crud character */
put linein=;
if upcase(linein)=:'BYE' then do;
command='BYE';
end;
else if upcase(linein)=:'QUERY' then do;
arg= trim(left(substr(linein,6)));
command='QUERY';
argument=trim(arg);
end;
else if upcase(linein)=:'LAUNCH' then do;
arg= trim(left(substr(linein,7)));
command='LAUNCH';
argument=trim(arg);
end;
else do;
file log;
put 'Cannot parse command.';
file srvsoc;
put 'Cannot parse command.';
end;
file log;
put command=;
put argument=;
/*------------------------------------------------------------------------*/
/* BYE: Shutdown server if requested. [note 6] */
/*------------------------------------------------------------------------*/
if command='BYE' then do;
file log;
put 'Server stop is being requested by client.'; /* send to sas log */
file srvsoc;
put 'Server stop is being requested by client.'; /* send to client */
call symput('loop','0'); /* stop loop on next pass */
end;
/*------------------------------------------------------------------------*/
/* QUERY: Write a predefined file to the client. */
/*------------------------------------------------------------------------*/
if command='QUERY' then do;
if NOT index("&querylist",'*'||trim(argument)||'*') then do;
file log;
put 'This file cannot be queried';
file srvsoc;
put 'This file cannot be queried';
end;
else if NOT fexist(argument) then do;
file log;
put 'The file does not exist';
file srvsoc;
put 'The file does not exist';
end;
else do;
file log;
put 'Ready to read a file';
file srvsoc;
put 'Ready to read a file';
%goodfiles; [note 7] /* select the infile */
do until(lastrow);
input;
put _infile_;
end;
end;
end;
/*------------------------------------------------------------------------*/
/* LAUNCH: Run a predefined program. */
/*------------------------------------------------------------------------*/
if command='LAUNCH' then do;
if NOT index("&launchlist",'*'||trim(argument)||'*') then do;
file log;
put 'This file cannot be run';
file srvsoc;
put 'This file cannot be run';
end;
else do;
file log;
put 'Launching program ' argument;
file srvsoc;
put 'Launching program ' argument;
call symput('launch',trim(argument));
end;
end;
stop;
run;
/*---------------------------------------------------------------------------*/
/* RUN SAS PROGRAM: use %include to start a sas program. [note 8] */
/*---------------------------------------------------------------------------*/
%put launch=***&launch***;
%if &launch^= %then %do;
%include "&&&launch";
%end;
/*---------------------------------------------------------------------------*/
/* Release the SAS log. */
/*---------------------------------------------------------------------------*/
proc printto log=log; run;
%end;
%mend sassrv;
%let loop=1;
%sassrv;
|