+-+-+-+ Beginning of part 7 +-+-+-+ X `125 vms_request[2];`009`009`009/* One and one NULL to terminate */ X X /* Do some setup stuff */ X X vms_request[0].buf_len = 8; `009/* max 8 characters for version_id */ X vms_request[0].code = SYI$_VERSION; /* Want the version */ X vms_request[0].buffer = ver;`009/* Where it goes */ X vms_request[0].ret_len = &len;`009/* Where to stuff the length */ X X vms_request[1].buf_len = 0; `009/* Nothing for the second */ X vms_request[1].code = 0; X X /* Get system information, synchronously */ X X sys$getsyiw(NULL, NULL, NULL, vms_request, NULL, NULL, NULL); X X /* Terminate the string */ X ver[8] = '\0'; X for (len = 7; len--; len != 0) `123 X`009if (ver[len] != ' ') X`009 break; X`009else X`009 ver[len] = '\0'; X `125 X X return(ver); X`125 X X/* Send a message out to a user through JNET */ X Xvoid send_msg(char * n, char * u, char * s) X`123 X static struct dsc$descriptor_s node; X static struct dsc$descriptor_s user; X static struct dsc$descriptor_s msg; X char * t_s; `009`009`009/* Need to fondle the string */ X V /* Redo the message with a '*' for *SERV machines, if we miss otherwise * X/ X X t_s = xmalloc(strlen(s)+4); X sprintf(t_s, "* %s", s); X X /* Setup for Jnet */ X X str_desc(&node, n); X str_desc(&user, u); X str_desc(&msg, t_s); X mode = 2; X X /* Send it to Jnet to do it's thing */ X X jan_send_msg(&mode, &node, &user, &msg); X X /* Don't need that hanging around */ X X xfree(t_s); X`125 X X/* Write a message to the log file */ X Xvoid send_log_file(char * s) X`123 X static struct dsc$descriptor_s log_msg; X X if (log_available != TRUE) X`009return;`009`009`009`009/* Can't log until hook is set up */ X str_desc(&log_msg, s);`009`009/* Build a descriptor, please */ X jan_jlog(&hook_name, &log_msg);`009/* Call Jnet to do it to it */ X`125 X X/* Start up a new log file */ X Xvoid init_log_file(void) X`123 X /* Build the logfile comment and send it through Jnet */ X X sprintf(temp, "I %s (%s) started.", hook_name.dsc$a_pointer, version); X send_log_file(temp); X X /* Tell OPCOM that we've started */ X X send_opcom(temp+2); X`125 X X/* Send a message to OPCOM */ X Xvoid send_opcom(char * s) X`123 X struct `123 X`009struct hdr `123`009`009`009/* Trust me, this is necessary */ X`009 unsigned char type; `009/* Read up on SYS$SNDOPR and you'll */ X`009 unsigned short target_0_15; /* see why. */ X`009 unsigned char target_16_23; X`009 unsigned long rqst_id; X`009`125 h; X`009char msg[200]; X `125 opc_request; X struct dsc$descriptor opc; X X opc_request.h.type = OPC$_RQ_RQST;`009/* Send out the string */ X opc_request.h.target_0_15 = OPC$M_NM_CENTRL; /* To main operator */ X opc_request.h.target_16_23 = 0; X opc_request.h.rqst_id = 0L; `009/* Default it */ X X strcpy(opc_request.msg, s); `009/* Copy the string */ X V opc.dsc$a_pointer = &opc_request;`009/* Build a descriptor for the block X */ X opc.dsc$w_length = strlen(s) + sizeof(struct hdr); X X /* And do it */ X X sys$sndopr(&opc, 0); X`125 X X/* Do the right things with the From: text lines */ X Xvoid from_text_fondle(char * s) X`123 X int front; X X /* First, get rid of '"'s. They mess up Notes */ X X remove_quotes(s); X X /* Strip leading blanks */ X X front = strspn(s, " ");`009`009/* Find length of leading blanks */ X if (front) `123 X`009strcpy(s, s+front); X `125 X X /* Now, let's see if there's any way to get a return address */ X X if (!strpbrk(s, "<> ")) `123 X X`009/* Well, there might be something useful there. Let's check */ X X`009if (strchr(s, '@')) `123 X`009 strcat(s, ">"); /* Throw a <> around the whole thing */ X`009 strcpy(s+1, s); X`009 s[0] = '<'; X`009`125 X `125 X X /* Last, let's see if we can do something interesting with the name */ X X if (s[0] && !isalpha(s[0]) && !isdigit(s[0])) `123 X`009strcpy(s+1, s);`009`009`009/* Make room, make room */ X`009s[0] = '_'; /* Something to make Notes happy */ X `125 X`125 X X/* Do the right things with the Subj: lines */ X Xvoid subj_text_fondle(char * s) X`123 X /* First, get rid of '"'s. They mess up Notes */ X X remove_quotes(s); X X /* Check for initial '$'s. They mess up DCL. [Isn't this fun, kids?] */ X X if (s[0] == '$') `123 X`009strcpy(s+1, s); `009`009/* Extra character */ X`009s[0] = ' '; X `125 X`125 X X/* Error to the log file, please */ X Xvoid report_error(char * s, int error) X`123 X static char msg[257];`009`009/* Place for the message */ X struct dsc$descriptor msgd; `009/* And a descriptor for it */ X int msg_len;`009`009`009/* How long was the message */ X X /* Some setup */ X X msg_len = 0;`009`009`009/* I have no idea how big it is... */ X msgd.dsc$w_length = 256;`009`009/* There's space for 256 characters */ X msgd.dsc$a_pointer = msg;`009`009/* Where does it go? */ X X /* What's the message for the error code */ X X sys$getmsg(error, &msg_len, &msgd, 0, &temp); X X /* Terminate the string please */ X X msg[msg_len] = '\0'; X X /* Send the error message to the log file */ X X sprintf(temp, "W %s %s :%s",hook_name.dsc$a_pointer, s, msg); X send_log_file(temp); X`125 X X/* Minor support function for errors, needed by jan_rec_file() */ X Xstatic int rec_error(struct dsc$descriptor * s) X`123 X return; X`125 X X/* Receive a file and place it accordingly */ X Xint receive_file(struct jnet_file_header * f) X`123 X $DESCRIPTOR(d_space, " "); /* Space holders for something */ X static struct dsc$descriptor_s d_file; X static struct dsc$descriptor_s d_dest; X static struct dsc$descriptor_s d_name; X X static struct dsc$descriptor_s X`009d_device = `123 10, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125; X X static struct `123 X`009int append;`009`009`009/* Unknown */ X`009int confirm;`009`009`009/* Unknown */ X`009int fortran;`009`009`009/* FORTRAN line carriage control */ X`009int interrupt;`009`009`009/* Unknown */ X`009int log;`009`009`009/* Unknown */ X`009int special_format;`009`009/* Special formats possible */ X`009int translate;`009`009`009/* EBC to ASC */ X `125 opt = `123 TRUE, FALSE, TRUE, FALSE, FALSE, TRUE, TRUE `125; X X int out_length;`009`009`009/* Length of local file name */ X char dest_file[128];`009`009/* Where we want it to go */ X X /* Figure out all of the file names */ X X sprintf(f->jnet_file, "JAN_SPOOL:%s.RSC;-0", hook_name.dsc$a_pointer); X sprintf(dest_file, "%s%s.RECEIVE", scratch_dir.dsc$a_pointer, X`009 hook_name.dsc$a_pointer); X X /* Get the TAG information from the file */ X X status = parse_tag(f->jnet_file, f, &d_device); X X#ifdef DEBUG X printf("receive_file: got TAG information\n"); X#endif X X /* If that didn't work, don't even think about trying the rest... */ X X if (!(status & 1)) `123 X`009report_error("Couldn't parse tag from file", status); X`009return (status); X `125 X X /* Jnet wants this stuff as descriptors */ X X str_desc(&d_file, f->jnet_file); X str_desc(&d_dest, dest_file); X f->local_file[0] = '\0'; X str_desc(&d_name, f->local_file); X d_name.dsc$w_length = 128; X X /* And now tell Jnet where/how/etc we want the file */ X X status = jan_rec_file(&d_device, &d_file, &d_space, &d_dest, &d_dest, X`009 &opt.translate, opt.log, opt.confirm, &opt.special_format, X`009 &opt.fortran, &d_space, &opt.append, &opt.interrupt, &rec_error, X`009 &d_name, &out_length); X X /* Did it work? */ X X if (!(status & 1)) `123 X`009sprintf(temp, "W Rec_file: %s %s", f->jnet_file, dest_file); X`009send_log_file(temp); X`009f->local_file[0] = '\0'; X `125 else `123 X`009f->local_file[out_length & 0xfff] = '\0'; X `125 X X /* And how did it all go? */ X X return(status); X`125 X V/* Read (with RMS) and interpret the file header, which is the RSCS TAG info X */ X Xstatic int parse_tag(char * jf, struct jnet_file_header * f, struct X`009dsc$descriptor * d_device) X`123 X static struct dsc$descriptor_s X`009d_tag`009 = `123`0090, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125, X`009d_host`009 = `123 10, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125, X`009d_user`009 = `123 10, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125, X`009d_filename = `123 10, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125, X`009d_filetype = `123 10, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125, X`009d_class = `123`0092, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`125; X X /* Fake out Jnet */ X X $DESCRIPTOR(d_dummy, " "); X X /* RMS structures and other information */ X X struct FAB fab; X struct RAB rab; X struct XABFHC xab; X int mrs; X X /* Some places for Jnet to stuff information */ X X int date[2]; X int rec_cnt; X int spool_id; X X /* And now it gets wierd... */ X X fab = cc$rms_fab;`009`009`009/* Initialize some stuff... */ X rab = cc$rms_rab; X xab = cc$rms_xabfhc; X X fab.fab$l_xab = &xab;`009`009/* Set the cross pointers */ X rab.rab$l_fab = &fab; X X fab.fab$l_fna = jf; `009`009/* Name of the file to use */ X fab.fab$b_fns = strlen(jf); X X#ifdef DEBUG X printf("parse_tag: About to open the file\n"); X#endif X X status = sys$open(&fab);`009`009/* Open the file */ X if (!(status & 1)) `123`009`009/* Did it work? */ X`009return (status); X `125 X X sys$connect(&rab);`009`009`009/* Hook up the Record Information */ X mrs = (xab.xab$w_lrl & 0xfffe) + 2; /* Record length */ X X rab.rab$l_ubf = temp;`009`009/* Buffer for the first record */ X rab.rab$w_usz = mrs;`009`009/* Record length */ X X status = sys$get(&rab);`009`009/* Now, let's read the record */ X if (!(status & 1)) `123`009`009/* Did it work? */ X`009return (status); X `125 X X sys$disconnect(&rab);`009`009/* Unhook the Record Info */ X X sys$close(&fab);`009`009`009/* And lose the file */ X X d_tag.dsc$a_pointer = temp; `009/* The TAG in its entirety */ X d_tag.dsc$w_length = rab.rab$w_rsz; /* How big is it */ X X d_host.dsc$a_pointer = f->host;`009/* Where we want the info to go */ X d_user.dsc$a_pointer = f->user; X d_filename.dsc$a_pointer = f->filename; X d_filetype.dsc$a_pointer = f->filetype; X d_device->dsc$a_pointer = f->device; X d_class.dsc$a_pointer = f->class; X X /* Ask Jnet to figure out what's going on here */ X X status = jan_tagparse(&d_tag, &d_dummy, &d_dummy, &d_host, &d_user, X`009 &d_filename, &d_filetype, d_device, &d_class, &date, &rec_cnt, X`009 &spool_id); X X /* Make sure that everything is NULL terminated */ X X f->host[8] = '\0'; X f->user[8] = '\0'; X f->filename[8] = '\0'; X f->filetype[8] = '\0'; X f->device[5] = '\0'; X f->class[1] = '\0'; X X /* And let caller know how it went */ X X return (status); X`125 X X/* Read a Jnet Immediate Message and stuff it */ X Xint receive_message(char * node, char * user, char * msg) X`123 X int msglen; `009`009`009/* How long was the message */ X struct dsc$descriptor_s node_dsc;`009/* Descriptors for the pieces */ X struct dsc$descriptor_s user_dsc; X struct dsc$descriptor_s msg_dsc; X X node[0] = '\0'; /* Terminate all of the buffers */ X user[0] = '\0'; X msg[0] = '\0'; X X str_desc(&node_dsc, node);`009`009/* Bulid descriptors for all */ X str_desc(&user_dsc, user); X str_desc(&msg_dsc, msg); X X node_dsc.dsc$w_length = 8;`009`009/* And say how big the buffers are */ X user_dsc.dsc$w_length = 8; X msg_dsc.dsc$w_length = 255; X X mode = 2;`009`009`009`009/* Jnet stuff */ X X /* Go grovelling to Jnet for the message and accoutrements */ X X jan_receive_msg(&mode, &node_dsc, &user_dsc, &msg_dsc, &msglen); X X#ifdef DEBUG X printf("receive_message: Got the message\n"); X#endif X X /* How did it go? */ X X if (mode == 2) `123 X`009return; X `125 X X /* Terminate all of the strings */ X X node[8] = '\0'; X user[8] = '\0'; X msg[msg_dsc.dsc$w_length&0xff] = '\0'; X X /* Perform perversities on the message */ X X scrunch(strupr(msg)); X X /* Log the message reception */ X X sprintf(temp, "C %s %s %s", node, user, msg); X send_log_file(temp); X X /* And remove trailing blanks for future use */ X X strip(node); X strip(user); X X return; X`125 $ GOSUB UNPACK_FILE $ FILE_IS = "BUILD.COM" $ CHECKSUM_IS = 319041600 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X$ ! For debugging, change all cc to cc/define=("DEBUG=1") below X$ cc bboard X$ cc bbsupp X$ cc hooks X$ cc supp X$ cc rules X$ cc comsupp X$ cc usefile X$ cc digest X$ cc usemsg X$ cc notelog X$ link/map bboard, bbsupp, hooks, supp, rules, comsupp, usefile,- X`009`009digest, usemsg, notelog, sys$input/opt Xjan_common:[lib]janshr/share`032 Xsys$share:vaxcrtl/sha`032 Xident="V1.44-FINAL" $ GOSUB UNPACK_FILE $ FILE_IS = "COMSUPP.C" $ CHECKSUM_IS = 1243453833 $ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY X#include X#include X#include X#include X#include X#include X#include X#include "bboard.h" X Xint setuname_used;`009`009`009/* Do we need to clean up afterwards? */ X Xstatic FILE * com_file; `009`009/* Maintain info about the stream */ Xstatic char com_fn[200]; X#ifdef DEBUG Xstatic char log_fn[200]; X#endif X Xint post_job_running(void); X X/* Run a detached process to write out unwritten notes */ X Xvoid com_write_notes(void) X`123 X static struct dsc$descriptor cmd_d; X static struct dsc$descriptor inp_d; X static struct dsc$descriptor out_d; X static struct dsc$descriptor nam_d; X char prcnam[16]; X static unsigned long prc_cnt = 1; X X /* Are we allowed to write Notes or do we need to wait until later? */ X X if (postings_suspended && !shutdown_state) `123 X`009timer_reset(); X`009return; X `125 X X /* Let's make sure that there aren't any posting jobs running */ X X if (post_job_running()) `123 X`009timer_reset();`009`009`009/* Let's set up to do it again */ X`009return; X `125 X X /* Need to write close-up commands */ X X com_file = fopen(com_fn, "a+"); X X if (setuname_used) `123 X`009fputs("$ setuname 'oldname'\n", com_file); X `125 X#ifndef DEBUG X fprintf(com_file, "$ delete %s;*\n", com_fn); X#endif X fputs("$ exit\n", com_file); X fclose(com_file); X X /* Magic here to run detached process 'com_fn' */ X X str_desc(&cmd_d, "SYS$SYSTEM:LOGINOUT.EXE"); X str_desc(&inp_d, com_fn); X#ifdef DEBUG X str_desc(&out_d, log_fn); X#else X str_desc(&out_d, "NL:"); X#endif X sprintf(prcnam, "BB_Post_%07lX", prc_cnt++); X prc_cnt &= 0xfffffff; X str_desc(&nam_d, prcnam); X X /* Run with it */ X X status = sys$creprc(NULL, &cmd_d, &inp_d, &out_d, NULL, 0, NULL, &nam_d, -+-+-+-+-+ End of part 7 +-+-+-+-+-