/* CGIBIN.C (c)Copyright Jan Jaeger, 2002-2006 */
/* HTTP cgi-bin routines */
/* This file contains all cgi routines that may be executed on the */
/* server (ie under control of a hercules thread) */
/* */
/* */
/* All cgi-bin routines are identified in the directory at the end */
/* of this file */
/* */
/* */
/* The cgi-bin routines may call the following HTTP service routines */
/* */
/* char *cgi_variable(WEBBLK *webblk, char *name); */
/* This call returns a pointer to the cgi variable requested */
/* or a NULL pointer if the variable is not found */
/* */
/* char *cgi_cookie(WEBBLK *webblk, char *name); */
/* This call returns a pointer to the cookie requested */
/* or a NULL pointer if the cookie is not found */
/* */
/* char *cgi_username(WEBBLK *webblk); */
/* Returns the username for which the user has been authenticated */
/* or NULL if not authenticated (refer to auth/noauth parameter */
/* on the HTTPPORT configuration statement) */
/* */
/* char *cgi_baseurl(WEBBLK *webblk); */
/* Returns the url as requested by the user */
/* */
/* */
/* void html_header(WEBBLK *webblk); */
/* Sets up the standard html header, and includes the */
/* html/header.htmlpart file. */
/* */
/* void html_footer(WEBBLK *webblk); */
/* Sets up the standard html footer, and includes the */
/* html/footer.htmlpart file. */
/* */
/* int html_include(WEBBLK *webblk, char *filename); */
/* Includes an html file */
/* */
/* */
/* Jan Jaeger - 28/03/2002 */
#include "hstdinc.h"
#define _CGIBIN_C_
#define _HENGINE_DLL_
#include "hercules.h"
#include "devtype.h"
#include "opcode.h"
#include "httpmisc.h"
#if defined(OPTION_HTTP_SERVER)
void cgibin_reg_control(WEBBLK *webblk)
{
int i;
REGS *regs;
regs = sysblk.regs[sysblk.pcpu];
if (!regs) regs = &sysblk.dummyregs;
html_header(webblk);
hprintf(webblk->sock, "
Control Registers
\n");
hprintf(webblk->sock, "\n");
if(regs->arch_mode != ARCH_900)
for (i = 0; i < 16; i++)
hprintf(webblk->sock, "CR%2.2d=%8.8X%s", i, regs->CR_L(i),
((i & 0x03) == 0x03) ? "\n" : "\t");
else
for (i = 0; i < 16; i++)
hprintf(webblk->sock, "CR%1.1X=%16.16" I64_FMT "X%s", i,
(U64)regs->CR_G(i), ((i & 0x03) == 0x03) ? "\n" : " ");
hprintf(webblk->sock, "\n");
html_footer(webblk);
}
void cgibin_reg_general(WEBBLK *webblk)
{
int i;
REGS *regs;
regs = sysblk.regs[sysblk.pcpu];
if (!regs) regs = &sysblk.dummyregs;
html_header(webblk);
hprintf(webblk->sock, "General Registers
\n");
hprintf(webblk->sock, "\n");
if(regs->arch_mode != ARCH_900)
for (i = 0; i < 16; i++)
hprintf(webblk->sock, "GR%2.2d=%8.8X%s", i, regs->GR_L(i),
((i & 0x03) == 0x03) ? "\n" : "\t");
else
for (i = 0; i < 16; i++)
hprintf(webblk->sock, "GR%1.1X=%16.16" I64_FMT "X%s", i,
(U64)regs->GR_G(i), ((i & 0x03) == 0x03) ? "\n" : " ");
hprintf(webblk->sock, "\n");
html_footer(webblk);
}
// void copy_psw (REGS *regs, BYTE *addr);
void cgibin_psw(WEBBLK *webblk)
{
REGS *regs;
QWORD qword; /* quadword work area */
char *value;
int autorefresh=0;
int refresh_interval=5;
regs = sysblk.regs[sysblk.pcpu];
if (!regs) regs = &sysblk.dummyregs;
html_header(webblk);
if (cgi_variable(webblk,"autorefresh"))
autorefresh = 1;
else if (cgi_variable(webblk,"norefresh"))
autorefresh = 0;
else if (cgi_variable(webblk,"refresh"))
autorefresh = 1;
if ((value = cgi_variable(webblk,"refresh_interval")))
refresh_interval = atoi(value);
hprintf(webblk->sock, "Program Status Word
\n");
hprintf(webblk->sock, "\n");
hprintf(webblk->sock, "\n");
if( regs->arch_mode != ARCH_900 )
{
copy_psw (regs, qword);
hprintf(webblk->sock, "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X\n",
qword[0], qword[1], qword[2], qword[3],
qword[4], qword[5], qword[6], qword[7]);
}
else
{
copy_psw (regs, qword);
hprintf(webblk->sock, "PSW=%2.2X%2.2X%2.2X%2.2X %2.2X%2.2X%2.2X%2.2X "
"%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X\n",
qword[0], qword[1], qword[2], qword[3],
qword[4], qword[5], qword[6], qword[7],
qword[8], qword[9], qword[10], qword[11],
qword[12], qword[13], qword[14], qword[15]);
}
if (autorefresh)
{
/* JavaScript to cause automatic page refresh */
hprintf(webblk->sock, "\n");
}
html_footer(webblk);
}
void cgibin_syslog(WEBBLK *webblk)
{
int num_bytes;
int logbuf_idx;
char *logbuf_ptr;
char *command;
char *value;
int autorefresh = 0;
int refresh_interval = 5;
int msgcount = 22;
if ((command = cgi_variable(webblk,"command")))
{
panel_command(command);
// Wait a bit before proceeding in case
// the command issues a lot of messages
usleep(50000);
}
if((value = cgi_variable(webblk,"msgcount")))
msgcount = atoi(value);
else
if((value = cgi_cookie(webblk,"msgcount")))
msgcount = atoi(value);
if ((value = cgi_variable(webblk,"refresh_interval")))
refresh_interval = atoi(value);
if (cgi_variable(webblk,"autorefresh"))
autorefresh = 1;
else if (cgi_variable(webblk,"norefresh"))
autorefresh = 0;
else if (cgi_variable(webblk,"refresh"))
autorefresh = 1;
html_header(webblk);
hprintf(webblk->sock,"\n",
msgcount);
hprintf(webblk->sock, "
Hercules System Log
\n");
hprintf(webblk->sock, "\n");
// Get the index to our desired starting message...
logbuf_idx = msgcount ? log_line( msgcount ) : -1;
// Now read the logfile starting at that index. The return
// value is the total #of bytes of messages data there is.
if ( (num_bytes = log_read( &logbuf_ptr, &logbuf_idx, LOG_NOBLOCK )) > 0 )
{
// Copy the message data to a work buffer for processing.
// This is to allow for the possibility, however remote,
// that the logfile buffer actually wraps around and over-
// lays the message data we were going to display (which
// could happen if there's a sudden flood of messages)
int sav_bytes = num_bytes;
char *wrk_bufptr = malloc( num_bytes );
if ( wrk_bufptr ) strncpy( wrk_bufptr, logbuf_ptr, num_bytes );
else wrk_bufptr = logbuf_ptr;
// We need to convert certain characters that might
// possibly be erroneously interpretted as HTML code
#define AMP_LT "<" // (HTML code for '<')
#define AMP_GT ">" // (HTML code for '>')
#define AMP_AMP "&" // (HTML code for '&')
while ( num_bytes-- )
{
switch ( *wrk_bufptr )
{
case '<':
hwrite( webblk->sock, AMP_LT , sizeof(AMP_LT) );
break;
case '>':
hwrite( webblk->sock, AMP_GT , sizeof(AMP_GT) );
break;
case '&':
hwrite( webblk->sock, AMP_AMP , sizeof(AMP_AMP));
break;
default:
hwrite( webblk->sock, wrk_bufptr , 1 );
break;
}
wrk_bufptr++;
}
// (free our work buffer if it's really ours)
if ( ( wrk_bufptr -= sav_bytes ) != logbuf_ptr )
free( wrk_bufptr );
}
hprintf(webblk->sock, "\n");
hprintf(webblk->sock, "\n
\n");
hprintf(webblk->sock, "\n");
hprintf(webblk->sock, "\n");
hprintf(webblk->sock, "\n");
if (autorefresh)
{
/* JavaScript to cause automatic page refresh */
hprintf(webblk->sock, "\n");
}
html_footer(webblk);
}
void cgibin_debug_registers(WEBBLK *webblk)
{
int i, cpu = 0;
int select_gr, select_cr, select_ar;
char *value;
REGS *regs;
if((value = cgi_variable(webblk,"cpu")))
cpu = atoi(value);
if((value = cgi_variable(webblk,"select_gr")) && *value == 'S')
select_gr = 1;
else
select_gr = 0;
if((value = cgi_variable(webblk,"select_cr")) && *value == 'S')
select_cr = 1;
else
select_cr = 0;
if((value = cgi_variable(webblk,"select_ar")) && *value == 'S')
select_ar = 1;
else
select_ar = 0;
/* Validate cpu number */
if (cpu < 0 || cpu >= MAX_CPU || !IS_CPU_ONLINE(cpu))
for (cpu = 0; cpu < MAX_CPU; cpu++)
if(IS_CPU_ONLINE(cpu))
break;
if(cpu < MAX_CPU)
regs = sysblk.regs[cpu];
else
regs = sysblk.regs[sysblk.pcpu];
if (!regs) regs = &sysblk.dummyregs;
if((value = cgi_variable(webblk,"alter_gr")) && *value == 'A')
{
for(i = 0; i < 16; i++)
{
char regname[16];
sprintf(regname,"alter_gr%d",i);
if((value = cgi_variable(webblk,regname)))
{
if(regs->arch_mode != ARCH_900)
sscanf(value,"%"I32_FMT"x",&(regs->GR_L(i)));
else
sscanf(value,"%"I64_FMT"x",&(regs->GR_G(i)));
}
}
}
if((value = cgi_variable(webblk,"alter_cr")) && *value == 'A')
{
for(i = 0; i < 16; i++)
{
char regname[16];
sprintf(regname,"alter_cr%d",i);
if((value = cgi_variable(webblk,regname)))
{
if(regs->arch_mode != ARCH_900)
sscanf(value,"%"I32_FMT"x",&(regs->CR_L(i)));
else
sscanf(value,"%"I64_FMT"x",&(regs->CR_G(i)));
}
}
}
if((value = cgi_variable(webblk,"alter_ar")) && *value == 'A')
{
for(i = 0; i < 16; i++)
{
char regname[16];
sprintf(regname,"alter_ar%d",i);
if((value = cgi_variable(webblk,regname)))
sscanf(value,"%x",&(regs->AR(i)));
}
}
html_header(webblk);
hprintf(webblk->sock,"\n");
if(!select_gr)
{
hprintf(webblk->sock,"\n",cpu,select_cr?'S':'H',select_ar?'S':'H');
}
else
{
hprintf(webblk->sock,"\n",cpu,select_cr?'S':'H',select_ar?'S':'H');
hprintf(webblk->sock,"\n",cpu,select_cr?'S':'H',select_ar?'S':'H');
}
if(!select_cr)
{
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_ar?'S':'H');
}
else
{
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_ar?'S':'H');
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_ar?'S':'H');
}
if(regs->arch_mode != ARCH_370)
{
if(!select_ar)
{
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_cr?'S':'H');
}
else
{
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_cr?'S':'H');
hprintf(webblk->sock,"\n",cpu,select_gr?'S':'H',select_cr?'S':'H');
}
}
html_footer(webblk);
}
void cgibin_debug_storage(WEBBLK *webblk)
{
int i, j;
char *value;
U32 addr = 0;
/* INCOMPLETE
* no storage alter
* no storage type (abs/real/prim virt/sec virt/access reg virt)
* no cpu selection for storage other then abs
*/
if((value = cgi_variable(webblk,"alter_a0")))
sscanf(value,"%x",&addr);
addr &= ~0x0F;
html_header(webblk);
hprintf(webblk->sock,"\n");
html_footer(webblk);
}
void cgibin_ipl(WEBBLK *webblk)
{
U32 i;
char *value;
DEVBLK *dev;
U16 ipldev;
U32 iplcpu;
U32 doipl;
html_header(webblk);
hprintf(webblk->sock,"Perform Initial Program Load
\n");
if(cgi_variable(webblk,"doipl"))
doipl = 1;
else
doipl = 0;
if((value = cgi_variable(webblk,"device")))
sscanf(value,"%hx",&ipldev);
else
ipldev = sysblk.ipldev;
if((value = cgi_variable(webblk,"cpu")))
sscanf(value,"%x",&iplcpu);
else
iplcpu = sysblk.iplcpu;
if((value = cgi_variable(webblk,"loadparm")))
set_loadparm(value);
/* Validate CPU number */
if(iplcpu >= MAX_CPU)
doipl = 0;
if(!doipl)
{
/* Present IPL parameters */
hprintf(webblk->sock,"\n");
}
else
{
obtain_lock (&sysblk.intlock);
/* Perform IPL function */
if( load_ipl(ipldev, iplcpu,0) )
{
hprintf(webblk->sock,"IPL failed, see the "
"system log "
"for details
\n");
}
else
{
hprintf(webblk->sock,"IPL completed
\n");
}
release_lock (&sysblk.intlock);
}
html_footer(webblk);
}
void cgibin_debug_device_list(WEBBLK *webblk)
{
DEVBLK *dev;
char *class;
char buf[80];
html_header(webblk);
hprintf(webblk->sock,"Attached Device List
\n"
"\n"
"| Number | "
"Subchannel | "
"Class | "
"Type | "
"Status |
\n");
for(dev = sysblk.firstdev; dev; dev = dev->nextdev)
if(dev->pmcw.flag5 & PMCW5_V)
{
(dev->hnd->query)(dev, &class, sizeof(buf), buf);
hprintf(webblk->sock,""
"| %4.4X | "
"%4.4X | "
"%s | "
"%4.4X | "
"%s%s%s | "
"
\n",
dev->devnum,
dev->subchan,dev->subchan,
class,
dev->devtype,
(dev->fd > 2 ? "open " : ""),
(dev->busy ? "busy " : ""),
(IOPENDING(dev) ? "pending " : ""));
}
hprintf(webblk->sock,"
\n");
html_footer(webblk);
}
void cgibin_debug_device_detail(WEBBLK *webblk)
{
DEVBLK *sel, *dev = NULL;
char *value;
int subchan;
html_header(webblk);
if((value = cgi_variable(webblk,"subchan"))
&& sscanf(value,"%x",&subchan) == 1)
for(dev = sysblk.firstdev; dev; dev = dev->nextdev)
if(dev->subchan == subchan)
break;
hprintf(webblk->sock,"Subchannel Details
\n");
hprintf(webblk->sock,"\n");
if(dev)
{
hprintf(webblk->sock,"\n"
""
"Path Management Control Word
"
"\n");
hprintf(webblk->sock,"| Interruption Parameter |
\n");
hprintf(webblk->sock,"| %2.2X%2.2X%2.2X%2.2X |
\n",
dev->pmcw.intparm[0], dev->pmcw.intparm[1],
dev->pmcw.intparm[2], dev->pmcw.intparm[3]);
hprintf(webblk->sock,"| Q | "
"0 | "
"ISC | "
"00 | "
"A | "
"E | "
"LM | "
"MM | "
"D | "
"T | "
"V | "
"DEVNUM |
\n");
hprintf(webblk->sock,"| %d | "
" | "
"%d | "
" | "
"%d | "
"%d | "
"%d%d | "
"%d%d | "
"%d | "
"%d | "
"%d | "
"%2.2X%2.2X |
\n",
((dev->pmcw.flag4 & PMCW4_Q) >> 7),
((dev->pmcw.flag4 & PMCW4_ISC) >> 3),
(dev->pmcw.flag4 & 1),
((dev->pmcw.flag5 >> 7) & 1),
((dev->pmcw.flag5 >> 6) & 1),
((dev->pmcw.flag5 >> 5) & 1),
((dev->pmcw.flag5 >> 4) & 1),
((dev->pmcw.flag5 >> 3) & 1),
((dev->pmcw.flag5 >> 2) & 1),
((dev->pmcw.flag5 >> 1) & 1),
(dev->pmcw.flag5 & 1),
dev->pmcw.devnum[0],
dev->pmcw.devnum[1]);
hprintf(webblk->sock,"| LPM | "
"PNOM | "
"LPUM | "
"PIM |
\n");
hprintf(webblk->sock,"| %2.2X | "
"%2.2X | "
"%2.2X | "
"%2.2X |
\n",
dev->pmcw.lpm,
dev->pmcw.pnom,
dev->pmcw.lpum,
dev->pmcw.pim);
hprintf(webblk->sock,"| MBI | "
"POM | "
"PAM |
\n");
hprintf(webblk->sock,"| %2.2X%2.2X | "
"%2.2X | "
"%2.2X |
\n",
dev->pmcw.mbi[0],
dev->pmcw.mbi[1],
dev->pmcw.pom,
dev->pmcw.pam);
hprintf(webblk->sock,"| CHPID=0 | "
"CHPID=1 | "
"CHPID=2 | "
"CHPID=3 |
\n");
hprintf(webblk->sock,"| %2.2X | "
"%2.2X | "
"%2.2X | "
"%2.2X |
\n",
dev->pmcw.chpid[0],
dev->pmcw.chpid[1],
dev->pmcw.chpid[2],
dev->pmcw.chpid[3]);
hprintf(webblk->sock,"| CHPID=4 | "
"CHPID=5 | "
"CHPID=6 | "
"CHPID=7 |
\n");
hprintf(webblk->sock,"| %2.2X | "
"%2.2X | "
"%2.2X | "
"%2.2X |
\n",
dev->pmcw.chpid[4],
dev->pmcw.chpid[5],
dev->pmcw.chpid[6],
dev->pmcw.chpid[7]);
hprintf(webblk->sock,"| ZONE | "
"00000 | "
"VISC | "
"00000000 | "
"I | "
"000000 | "
"S |
\n");
hprintf(webblk->sock,"| %2.2X | "
" | "
"%d | "
" | "
"%d | "
" | "
"%d |
\n",
dev->pmcw.zone,
(dev->pmcw.flag25 & PMCW25_VISC),
(dev->pmcw.flag27 & PMCW27_I) >> 7,
(dev->pmcw.flag27 & PMCW27_S));
hprintf(webblk->sock,"
\n");
}
html_footer(webblk);
}
void cgibin_debug_misc(WEBBLK *webblk)
{
int zone;
html_header(webblk);
hprintf(webblk->sock,"Miscellaneous Registers\n");
hprintf(webblk->sock,"
\n"
""
"Zone related Registers
"
"\n");
hprintf(webblk->sock,"| Zone | "
"CS Origin | "
"CS Limit | "
"ES Origin | "
"ES Limit | "
"Measurement Block | "
"Key |
\n");
for(zone = 0; zone < FEATURE_SIE_MAXZONES; zone++)
{
hprintf(webblk->sock,"| %2.2X | "
"%8.8X | "
"%8.8X | "
"%8.8X | "
"%8.8X | "
"%8.8X | "
"%2.2X |
\n",
zone,
(U32)sysblk.zpb[zone].mso << 20,
((U32)sysblk.zpb[zone].msl << 20) | 0xFFFFF,
(U32)sysblk.zpb[zone].eso << 20,
((U32)sysblk.zpb[zone].esl << 20) | 0xFFFFF,
(U32)sysblk.zpb[zone].mbo,
sysblk.zpb[zone].mbk);
}
hprintf(webblk->sock,"
\n");
hprintf(webblk->sock,"\n"
""
"Alternate Measurement
"
"\n");
hprintf(webblk->sock,"| Measurement Block | "
"Key |
\n");
hprintf(webblk->sock,"| %8.8X | "
"%2.2X |
\n",
(U32)sysblk.mbo,
sysblk.mbk);
hprintf(webblk->sock,"
\n");
hprintf(webblk->sock,"\n"
""
"Address Limit Register
"
"\n");
hprintf(webblk->sock,"| %8.8X |
\n",
(U32)sysblk.addrlimval);
hprintf(webblk->sock,"
\n");
html_footer(webblk);
}
void cgibin_configure_cpu(WEBBLK *webblk)
{
int i,j;
html_header(webblk);
hprintf(webblk->sock,"Configure CPU
\n");
for(i = 0; i < MAX_CPU; i++)
{
char cpuname[8], *cpustate;
int cpuonline = -1;
sprintf(cpuname,"cpu%d",i);
if((cpustate = cgi_variable(webblk,cpuname)))
sscanf(cpustate,"%d",&cpuonline);
obtain_lock (&sysblk.intlock);
switch(cpuonline) {
case 0:
if(IS_CPU_ONLINE(i))
deconfigure_cpu(i);
break;
case 1:
if(!IS_CPU_ONLINE(i))
configure_cpu(i);
break;
}
release_lock (&sysblk.intlock);
}
for(i = 0; i < MAX_CPU; i++)
{
hprintf(webblk->sock,"CPU%4.4X\n"
"
\n");
}
html_footer(webblk);
}
void cgibin_debug_version_info(WEBBLK *webblk)
{
html_header(webblk);
hprintf(webblk->sock,"Hercules Version Information
\n"
"\n");
display_version_2(NULL,"Hercules HTTP Server ", TRUE,webblk->sock);
hprintf(webblk->sock,"\n");
html_footer(webblk);
}
/* contributed by Tim Pinkawa [timpinkawa@gmail.com] */
void cgibin_xml_rates_info(WEBBLK *webblk)
{
hprintf(webblk->sock,"Expires: 0\n");
hprintf(webblk->sock,"Content-type: text/xml;\n\n"); /* XML document */
hprintf(webblk->sock,"\n");
hprintf(webblk->sock,"\n");
hprintf(webblk->sock,"\t%d\n", sysblk.arch_mode);
hprintf(webblk->sock,"\t%.1d.%.2d\n",
sysblk.mipsrate / 1000, (sysblk.mipsrate % 1000) / 10);
hprintf(webblk->sock,"\t%d\n", sysblk.siosrate);
hprintf(webblk->sock,"\n");
}
/* The following table is the cgi-bin directory, which */
/* associates directory filenames with cgibin routines */
CGITAB cgidir[] = {
{ "tasks/syslog", &cgibin_syslog },
{ "tasks/ipl", &cgibin_ipl },
{ "configure/cpu", &cgibin_configure_cpu },
{ "debug/registers", &cgibin_debug_registers },
{ "debug/storage", &cgibin_debug_storage },
{ "debug/misc", &cgibin_debug_misc },
{ "debug/version_info", &cgibin_debug_version_info },
{ "debug/device/list", &cgibin_debug_device_list },
{ "debug/device/detail", &cgibin_debug_device_detail },
{ "registers/general", &cgibin_reg_general },
{ "registers/control", &cgibin_reg_control },
{ "registers/psw", &cgibin_psw },
{ "xml/rates", &cgibin_xml_rates_info },
{ NULL, NULL } };
#endif /*defined(OPTION_HTTP_SERVER)*/