/******************************************************************** * ZCPR3 routines for Metal/Z-MSG * * File: MEZ3.C * * Copyright (c) 1984,1985,1986 Tim Gary * All Rights Reserved. * ******************************************************************** * * 1.50xx 04/10/86 Moved alias return, and z3_init stuff here (from metal.c) * 1.50xx 03/09/86 n_groups added.. * 1.40xx 01/26/86 Fix for new date/user formats.. * 1.31a 10/13/85 Release version. * 1.30xx 7/01/85 Print/echo flags saved... * 1.30xx 6/09/85 New bye stuff deleted, new protect method done. * 1.30xx 5/26/85 Save bye stuff if bye is active.. (at new topmem loc) * 1.30xx 5/25/85 Msg pointer saved in gp area, see also meinfreq.. * 1.30xx 5/12/85 Bug in calculations fixed. * 1.30xx 5/11/85 Protection code that should work with bye.. * 1.30xx 5/09/85 Protect mode working... * 1.30xx 5/05/85 Modified Path stuff, fixed protection for globals. * 1.30xx 5/03/85 Z3 Path stuff saved, and used in alias command lines. * 1.30xx 5/02/85 Z3BUG turned off, Z3MSG_OFFSET added, glbstr buffer * save fixed.. * 1.30xx 5/01/85 Error returned only if command not found, not if * can't access it. ALIASRET define used. If allocation * error, command line is restored. * 1.30xx 4/28/85 Z3BUG stuff added. * 1.30xx 4/26/85 Fix for saving command buffer before entering Z3 * 1.30xx 4/04/85 Etc.. * 1.30xx 3/03/85 Back to work. * 1.30xx 2/26/85 Command routine started. * ********************************************************************/ /* #define Z3BUG */ /* for Z3 alias debugging */ #include "xpm.h" /* CPMIO header file for i/o operations.*/ #include "megen.h" /* general defines */ #include "meglob.h" /* global variable definitions */ #include "meovfn.h" /* overlay function numbers */ #include "mefiles.h" /* file names */ #include "ctype.h" ovmain(func,parm) register int func; register char *parm; { #ifndef Z3 return ERROR; #else switch (func) { case CMD: return do_command(parm); case RETCMD: return ret_cmd(parm); case INITZ3: return z3_init(parm); default: send("\nMEZ3: Unknown Overlay function called for.\n"); return ERROR; } #endif } #ifdef Z3 /************************************************************************* * do_command looks for a command in a file of the following format: * * Status mask Command name Number of parms Alias command name * (4 hex chars) (small string) in alias ONE WORD ONLY! * * All fields are seperated by a space. * * *** EVERY FIELD MUST BE PRESENT!!!!!! *** * * The number of parms is not currently acurate. If there are * more than zero parms expected, it will take the rest of the line up * to the next ';' character (or eol). It does NOT take several parms * based on the value you give it. * When the alias is performed, and execution should return to * metal upon termination. This will be fairly slow, but it should * work ok. * ************************************************************************/ do_command(name) char *name; { FILE *commands; unsigned flags; /* temp storage of current mask flag from file */ char cmd_name[20]; /* current command name in file */ int n_parms; /* number of parms */ char alias[MAXLINE+1]; /* alias to use, parms are simply appended */ char *ccl; /* pointer to current command line */ char *ts; char a_user,a_drive; /* user/drive alias is in */ int ti; char *index(); static struct cmd_line savecmd; if ((commands=open(COMMANDS,0))==0) return ERROR; #ifdef Z3BUG printf("\nCommands file open, trying to match --> '%s'.\n",name); #endif read(commands,1); /* fill buffer to start with */ while (1) { fgets(buffer,commands); if (strlen(buffer)<10) break; /* EOF.... */ while (*buffer=='\n' || *buffer=='\r') strcpy(buffer,buffer+1); flags=xtou(nextf(buffer)); ts=index(buffer,' ')+1; strcpy(cmd_name,nextf(ts)); ts=index(ts,' ')+1; n_parms=atoi(ts); strcpy(alias,index(ts,' ')+1); #ifdef Z3BUG printf("\nFlag='%x' User flag='%x'\nCommand name='%s' Number of parms='%d' Alias='%s'.\n",flags,user.type_ptr->flags,cmd_name,n_parms,alias); #endif /* continue if no match, or not allowed... */ if ( !(flags & user.type_ptr->flags) || (ustrcmp(name,cmd_name))) continue; /* Ok, got here, command matches and available to this user */ ccl=z3env->cl->buffer; /* point to z3 command line buffer */ movmem(z3env->cl,&savecmd,z3env->cls+4); /* save for later */ a_user=0; a_drive=1; /* normally use A0: */ if (index(alias,':') && (index(alias)<(5+alias)) ) { a_user=atoi(alias+1); /* must be duu:alias format */ a_drive=1+(tolower(*alias)-'a'); strcpy(alias,index(alias,':')+1); /* delete drive spec */ } sprintf(ccl,"%s ",alias); if (n_parms && strloc) /* get parm if there is one on the line */ { ask("",buffer,40,UPLOW); /* get next parm */ strcat(ccl,buffer); /* append parm to command line */ } strcat(ccl,O.ALIASRET); /* make sure we return ok.. */ z3env->cl->next_char=ccl; close(commands); #ifdef Z3BUG printf("Command line buffer (Z3 one) is at %xh. Contents at %xh='%s'.\n", z3env->cl,ccl,ccl); #endif do_alias(&savecmd,a_user,a_drive); /* never returning function */ return NULL; /* if we're here, there's a problem */ } /* if we get here, there were problems */ close(commands); return ERROR; } /* do_command */ nextf(s) char *s; { static char tstr[MAXLINE+1]; strcpy(tstr,s); if (s=index(tstr,' ')) *s='\0'; /* make ' ' into terminator */ return tstr; } extern char sotries; /* do_alias function saves globals, and warm boots to perform command */ do_alias(savecmd,a_user,a_drive) struct cmd_line *savecmd; char a_user,a_drive; { struct g_save *gp; /* pointer to global variable area */ struct g_prot *gh_p; /* pointer to globals protect header */ /* char *troom; */ /* allocated space to play it safe */ char *g_v,*global_loc; /* pointer to start of all globals (msg, user, etc.) */ char **m_buff; /* pointer to char pointer */ char *ptr; int size,i; global_loc=g_v=malloc(sizeof(user)+sizeof(struct g_save)); #ifdef Z3BUG printf("\n%xh bytes of free memory required.",sizeof(user)+sizeof(struct g_save) ); printf("\nMalloc=%xh (zero indicates not enough space)\n",global_loc); #endif if (!global_loc) { movmem(savecmd,z3env->cl,(unsigned)((z3env->cls)+4)); if (user.status==SYSOP) send("\nERROR: Insufficient memory for aliases."); else send("\nCommand unavailable at this time.\n"); return ERROR; } /* to protect the private global area, we do a bye-like fake of top memory */ ptr=*((char **)0001)+3; /* Point to bios jump table */ g_h.obdos=*((char **)0x0006); /* warm boot address */ g_h.g_vars=g_v; /* pointer arith!.. pt. to globals */ movmem(ptr,g_h.bt,18); /* copy old bios jmp table */ g_h.prot_bdos=z3_hp; /* address of our bdos jmp (defined in main) */ /* if (bye!=nothing) movmem(g_h.obdos+0x0c,g_h.bye_a1,32); */ /* save bye vars */ /* this must go before the loop. z3_hp defined in main */ movmem(&g_h,z3_hp,sizeof(g_h)); /* move to actual location */ for (i=0; i<6; i++) { unsigned *uptr; z3_hp->abt[i].addr=z3_hp->bt[i].addr; /* fill in our new bios jumps */ z3_hp->abt[i].swapbdos=&(z3_hp->swap); uptr=(ptr+(3*i)+1); *uptr=&(z3_hp->abt[i]); /* store new bios vector */ } #ifdef Z3BUG printf("\nz3_hp=%xh z3_hp->g_vars=%xh\n",z3_hp,z3_hp->g_vars); #endif #ifdef Z3BUG printf("\nAfter swap, *(0006)=%xh.\n",*(int *)0006); #endif g_v=(z3_hp->g_vars); /* point to loc for variables */ movmem(&user,g_v,sizeof(user)); g_v+=sizeof(user); gp=g_v; /* compute gp like this or problem might occur */ #ifdef Z3BUG printf("gp=%xh msg=%xh \n",gp,msg); #endif gp->msg=msg; /* save location of msg array */ movmem(glbstr,gp->glbstr,MAXLINE+1); gp->strloc=strloc; gp->globalch=globalch; gp->print_flag=print_flag; gp->echo_flag=echo_flag; gp->sepstr=sepstr; gp->fmsg=fmsg; gp->lmsg=lmsg; gp->mindex=mindex; gp->msgcount=msgcount; gp->privmsgs=privmsgs; gp->nextmsg=nextmsg; gp->totalmsgs=totalmsgs; gp->callnum=callnum; movmem(date,gp->date,3); movmem(time,gp->time,2); movmem(last_date,gp->last_date,3); movmem(last_time,gp->last_time,2); gp->height=height; gp->n_groups=n_groups; gp->sotries=sotries; movmem(z3env->expath,gp->path,(z3env->expaths)*2); (z3env->expath)[0]=a_drive; /* setup alias drive/user */ (z3env->expath)[1]=a_user; (z3env->expath)[2]=1; /* setup A0: for bbs re-entry */ (z3env->expath)[3]=0; (z3env->expath)[4]=0; /* end of table */ /* save command buffer, away.. 4 bytes overhead for info, and buflen+1 */ movmem(savecmd,&(gp->cmdbuf),(unsigned)(z3env->cls+4)); ptr=0; *ptr=0xc3; /* make safe to warm boot */ /* now we put location of global save spot in message buffer (0x48/9) */ m_buff=z3env->msg+O.Z3MSG; *m_buff=z3_hp; /* global_loc; */ /* save this away */ #ifdef Z3BUG printf("Command line buffer (Z3 one) is at %xh. Contents are '%s'.\n", z3env->cl,z3env->cl->buffer); printf("Old contents were '%s'.\n",savecmd->buffer); #endif exit(0); /* and do so */ } /* routine generally never returns */ /************************************************************ * Restore values on return from alias... (was in metal.c) ************************************************************/ ret_cmd(glob_loc) char *glob_loc; { struct g_prot *gh_p; /* header pointer */ struct g_save *gp; /* global variables pointer */ int size; gh_p=glob_loc; /* header loc */ glob_loc=gh_p->g_vars; /* skip to real fields */ #ifdef Z3BUG printf("\nglob_loc now=%x gh_p=%x\n",glob_loc,gh_p); #endif movmem(glob_loc,&user,sizeof(user)); glob_loc+=sizeof(user); gp=glob_loc; /* get misc. variables area */ #ifdef Z3BUG printf("\nUser #%d '%s' From %s\n",user.number,user.name,user.city); printf("gp=%x, gp->glbstr=%x glbstr=%x\n",gp,gp->glbstr,glbstr); #endif movmem(gp->glbstr,glbstr,MAXLINE+1); /* restore command line */ #ifdef Z3BUG printf("after glbstr move, name='%s'\n",user.name); #endif /* msg=gp->msg; */ /* restore msg variable pointer */ strloc=gp->strloc; globalch=gp->globalch; print_flag=gp->print_flag; echo_flag=gp->echo_flag; sepstr=gp->sepstr; fmsg=gp->fmsg; lmsg=gp->lmsg; mindex=gp->mindex; msgcount=gp->msgcount; privmsgs=gp->privmsgs; nextmsg=gp->nextmsg; totalmsgs=gp->totalmsgs; callnum=gp->callnum; movmem(gp->date,date,3); movmem(gp->time,time,2); movmem(gp->last_date,last_date,3); movmem(gp->last_time,last_time,2); height=gp->height; n_groups=gp->n_groups; sotries=gp->sotries; #ifdef Z3BUG printf("\nname='%s' city='%s'...gp=%xh\n",user.name,user.city,gp); #endif movmem(gp->path,z3env->expath,(unsigned)(2*z3env->expaths)); movmem(&(gp->cmdbuf),z3env->cl,(unsigned)(z3env->cls+4) ); } /* g_restore */ /************************************************************************* * z3_init() does init stuff for zcpr3 systems.. * Like: loading system segments and setting registers.. ****************/ z3_init(t) char *t; { static struct seg_type { int num; /* segment # offset into sysseg array */ char *type; /* Filetype to add to file */ } segs[] = { ENV,".ENV", NDR,".NDR", RCP,".RCP", FCP,".FCP", IOP,".IOP", -1,0 }; int i; struct seg_type *sp; u_types *uptr; char *cp; send("\n[Initializing Environment]\n"); uptr=user.type_ptr; /* load system segments.. */ for (sp=segs; (sp->num)>=0; sp++) if (*(uptr->sysseg[sp->num])) load_seg(uptr->sysseg[sp->num],sp->num,sp->type); /* Set z3 regsiters.. */ for (i=0; i<10; i++) if (uptr->regs[i] & 0xff00) z3env->msg[0x30+i] = uptr->regs[i] &0xff; /* Put user name in system file name area */ cp=z3env; cp+=0x52+((uptr->sysnum-1)*11); /* point to system file name */ setmem(cp,11,' '); /* blank pad */ /*----------Try this-----------*/ movmem(&user.number,cp+8,3); strncpy(cp,index(user.name,' '),8); /* Set system path */ if (uptr->path) movmem(uptr->path,z3env->expath,(unsigned)(2*z3env->expaths)); } load_seg(file,num,ft) int num; char *file,*ft; { char tfile[20],*addr; FILE *seg_file; sprintf(tfile,"%s%s",file,ft); switch (num) { case ENV: addr=z3env->env; break; case NDR: addr=z3env->ndir; break; case RCP: addr=z3env->rcp; break; case FCP: addr=z3env->fcp; break; case IOP: addr=z3env->iop; break; } /* switch */ if (seg_file=open(tfile,F_RD)) { for ( ; read(seg_file,1)==128; addr+=128) movmem(bufloc(seg_file),addr,128); close(seg_file); } } /* load_seg */ #endif /* Z3 */ /* eof.. */