/*** uxp_internal_Filter - this is the worker thread that does the *** html-to-pcl-or-fx conversion process, using prtConvertHTML. ***/ void uxp_internal_Filter(void* v) { pUxpData inf = (pUxpData)v; pPrtSession s; char* type; char* printcmd; char* uxname; char* form=NULL; char cmd[128]; /** Set thread name **/ thSetName(NULL, "Print Writer"); /** Open the new print session. **/ stAttrValue(stLookup(inf->Node->Data,"type"), NULL, &type, 0); s = prtOpenSession(type, fdWrite, inf->SpoolFileFD, 0); if (!s) { fdClose(inf->SlaveFD, 0); inf->SlaveFD = NULL; thExit(); } /** Run the converter, and close when done. **/ prtConvertHTML(fdRead, inf->SlaveFD, s); prtCloseSession(s); fdClose(inf->SlaveFD, 0); inf->SlaveFD = NULL; /** Print the thing via the OS's spooler **/ fdClose(inf->SpoolFileFD, 0); stAttrValue(stLookup(inf->Node->Data,"if_type"),NULL,&printcmd,0); stAttrValue(stLookup(inf->Node->Data,"unix_name"),NULL,&uxname,0); stAttrValue(stLookup(inf->Node->Data,"form_name"),NULL,&form,0); if (printcmd && uxname) { if (!strcmp(printcmd,"lp")) sprintf(cmd,"(%s -d%s %s%s %s; /bin/rm %s) &",printcmd, uxname, form?"-f":"",form?form:"", inf->SpoolPathname, inf->SpoolPathname); else sprintf(cmd,"(%s -P%s %s%s %s; /bin/rm %s) &",printcmd, uxname, form?"-f":"", form?form:"", inf->SpoolPathname, inf->SpoolPathname); system(cmd); } thExit(); }
/*** qyt_internal_ReadText() - attempt to read data from a 'text' type object *** that might have a 'content' property giving the object's content. ***/ int qyt_internal_ReadText(pQytData inf, char* buffer, int maxcnt, int offset, int flags, pObjTrxTree* oxt) { pStructInf content_inf; int len; char* ptr; /** do we have content? **/ content_inf = stLookup(inf->NodeData, "content"); if (!content_inf) { mssError(1,"QYT","Text querytree object has no content"); return -1; } /** ok, get our bearings... **/ if (stGetAttrValue(content_inf, DATA_T_STRING, POD(&ptr), 0) != 0) { mssError(1,"QYT","Could not read content from text querytree object"); return -1; } len = strlen(ptr); if (flags & OBJ_U_SEEK) inf->Offset = offset; if (inf->Offset < 0) inf->Offset = 0; if (inf->Offset > len) inf->Offset = len; if (inf->Offset + maxcnt > len) maxcnt = len - inf->Offset; if (maxcnt <= 0) return 0; memcpy(buffer, ptr+inf->Offset, maxcnt); inf->Offset += maxcnt; return maxcnt; }
/*** uxpGetAttrType - get the type (DATA_T_xxx) of an attribute by name. ***/ int uxpGetAttrType(void* inf_v, char* attrname, pObjTrxTree* oxt) { pUxpData inf = UXP(inf_v); pStructInf search_inf; /** If name, it's a string. **/ if (!strcmp(attrname,"name")) return DATA_T_STRING; /** If content-type, it's also a string. **/ if (!strcmp(attrname,"content_type") || !strcmp(attrname, "inner_type") || !strcmp(attrname,"outer_type")) return DATA_T_STRING; /** If annotation, it's a string. **/ if (!strcmp(attrname,"annotation")) return DATA_T_STRING; /** Hunt around in the structinf for the thing **/ search_inf = stLookup(inf->Node->Data, attrname); if (search_inf) { return stGetAttrType(search_inf, 0); } mssError(1,"UXP","Invalid attribute for printer object"); return -1; }
/*** uxpSetAttrValue - sets the value of an attribute. 'val' must *** point to an appropriate data type. ***/ int uxpSetAttrValue(void* inf_v, char* attrname, int datatype, pObjData val, pObjTrxTree* oxt) { pUxpData inf = UXP(inf_v); pStructInf attr_inf; /** Choose the attr name **/ if (!strcmp(attrname,"name")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch setting attribute '%s' (should be string)", attrname); return -1; } if (!strcmp(inf->Obj->Pathname->Pathbuf,".")) return -1; if (strlen(inf->Obj->Pathname->Pathbuf) - strlen(strrchr(inf->Obj->Pathname->Pathbuf,'/')) + strlen(val->String) + 1 > 255) { mssError(1,"UXP","SetAttr 'name': new value exceeds internal size limits"); return -1; } strcpy(inf->Pathname, inf->Obj->Pathname->Pathbuf); strcpy(strrchr(inf->Pathname,'/')+1,val->String); if (rename(inf->Obj->Pathname->Pathbuf, inf->Pathname) < 0) { mssErrorErrno(1,"UXP","Could not rename printer node object"); return -1; } strcpy(inf->Obj->Pathname->Pathbuf, inf->Pathname); } else { attr_inf = stLookup(inf->Node->Data, attrname); if (!attr_inf && !strcmp(attrname,"annotation")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch setting attribute '%s' (should be string)", attrname); return -1; } attr_inf = stAddAttr(inf->Node->Data, attrname); stSetAttrValue(attr_inf, DATA_T_STRING, val, 0); } else if (!attr_inf) { mssError(1,"UXP","Invalid attribute for printer object"); return -1; } else { stSetAttrValue(attr_inf, datatype, val, 0); } } return 0; }
/*** uxpClose - close an open file or directory. ***/ int uxpClose(void* inf_v, pObjTrxTree* oxt) { pUxpData inf = UXP(inf_v); char cmd[320]; char* printcmd; char* uxname; char* form=NULL; /** Node need to be updated? **/ snWriteNode(inf->Obj->Prev, inf->Node); /** Close the master end of the filter socketpair? **/ if (inf->MasterFD) fdClose(inf->MasterFD, 0); /** Need to spool print job? **/ if (inf->SpoolFileFD && !inf->MasterFD) { fdClose(inf->SpoolFileFD, 0); stAttrValue(stLookup(inf->Node->Data,"if_type"),NULL,&printcmd,0); stAttrValue(stLookup(inf->Node->Data,"unix_name"),NULL,&uxname,0); stAttrValue(stLookup(inf->Node->Data,"form_name"),NULL,&form,0); if (printcmd && uxname) { if (!strcmp(printcmd,"lp")) sprintf(cmd,"(%s -d%s %s%s %s; /bin/rm %s) &",printcmd, uxname, form?"-f":"",form?form:"", inf->SpoolPathname, inf->SpoolPathname); else sprintf(cmd,"(%s -P%s %s%s %s; /bin/rm %s) &",printcmd, uxname, form?"-f":"", form?form:"", inf->SpoolPathname, inf->SpoolPathname); system(cmd); } } /** Free the structure **/ nmFree(inf,sizeof(UxpData)); return 0; }
/*** stxGetAttrType - get the type (DATA_T_xxx) of an attribute by name. ***/ int stxGetAttrType(void* inf_v, char* attrname, pObjTrxTree* oxt) { pStxData inf = STX(inf_v); pStructInf find_inf; int t; /** If name, it's a string **/ if (!strcmp(attrname,"name")) return DATA_T_STRING; /** If 'content-type', it's also a string. **/ if (!strcmp(attrname,"content_type") || !strcmp(attrname,"inner_type") || !strcmp(attrname,"outer_type")) return DATA_T_STRING; if (!strcmp(attrname,"annotation")) return DATA_T_STRING; /** Lookup the subgroup inf **/ find_inf = stLookup(inf->Data, attrname); if (!find_inf || stStructType(find_inf) != ST_T_ATTRIB) { /** For unset attributes on a structure file, we default to a NULL integer **/ /*mssError(1,"STX","Could not locate requested structure file attribute");*/ return (find_inf)?(-1):DATA_T_INTEGER; } /** Examine the expr to determine the type **/ t = stGetAttrType(find_inf, 0); if (find_inf->Value && find_inf->Value->NodeType == EXPR_N_LIST) { if (t == DATA_T_INTEGER) return DATA_T_INTVEC; else return DATA_T_STRINGVEC; } else if (find_inf->Value) { return t; } return -1; }
/*** stxOpen - open a file or directory. ***/ void* stxOpen(pObject obj, int mask, pContentType systype, char* usrtype, pObjTrxTree* oxt) { pStxData inf; char* endptr; pSnNode node = NULL; pStruct open_inf; pStructInf find_inf, attr_inf, search_inf; int i,j,n; char* ptr; /** Allocate the structure **/ inf = (pStxData)nmMalloc(sizeof(StxData)); if (!inf) return NULL; memset(inf,0,sizeof(StxData)); inf->Obj = obj; inf->Mask = mask; /** Check node access. IF newly created node object, handle differently. **/ if ((obj->Prev->Flags & OBJ_F_CREATED) && (obj->Mode & O_CREAT)) { /** Make the node **/ node = snNewNode(obj->Prev,"system/structure"); if (!node) { mssError(0,"STX","Could not create new structure file"); nmFree(inf, sizeof(StxData)); return NULL; } /** Any parameters to set? **/ if (obj->Pathname->OpenCtl[obj->SubPtr]) { for(i=0;i<obj->Pathname->OpenCtl[obj->SubPtr]->nSubInf;i++) { open_inf = obj->Pathname->OpenCtl[obj->SubPtr]->SubInf[i]; if (strncmp(open_inf->Name,"ls__",4) && open_inf->StrVal) { attr_inf = stAddAttr(node->Data, open_inf->Name); endptr = NULL; n = strtoi(open_inf->StrVal,&endptr,0); if (endptr && *endptr == '\0') stSetAttrValue(attr_inf, DATA_T_INTEGER, POD(&n), 0); else stSetAttrValue(attr_inf, DATA_T_STRING, POD(&(open_inf->StrVal)), 0); } } } /** Write the node. **/ snWriteNode(obj->Prev, node); } else { /** Open an existing node. **/ node = snReadNode(obj->Prev); if (node && (obj->Mode & O_CREAT) && (obj->Mode & O_EXCL) && obj->SubPtr == obj->Pathname->nElements) { mssError(0,"STX","Structure file already exists"); nmFree(inf, sizeof(StxData)); return NULL; } if (!node) { mssError(0,"STX","Could not read structure file"); nmFree(inf, sizeof(StxData)); return NULL; } } /** Search down the struct tree if we opened a sub-structure. **/ search_inf = node->Data; obj->SubCnt = obj->Pathname->nElements - obj->SubPtr + 1; for(i=obj->SubPtr;i<obj->Pathname->nElements;i++) { ptr = obj_internal_PathPart(obj->Pathname,i,1); find_inf = NULL; for(j=0;j<search_inf->nSubInf;j++) if (!strcmp(ptr,search_inf->SubInf[j]->Name) && stStructType(search_inf->SubInf[j]) == ST_T_SUBGROUP) { if (i == obj->Pathname->nElements-1 && (obj->Mode & O_CREAT) && (obj->Mode & O_EXCL)) { nmFree(inf,sizeof(StxData)); mssError(1,"STX","Structure file sub-group already exists"); return NULL; } find_inf = search_inf->SubInf[j]; break; } if (!find_inf && i == obj->Pathname->nElements-1 && (obj->Mode & O_CREAT)) { find_inf = stAddGroup(search_inf, ptr, usrtype); node->Status = SN_NS_DIRTY; } else if (!find_inf) { nmFree(inf,sizeof(StxData)); mssError(1,"STX","Structure file sub-group does not exist"); return NULL; } search_inf = find_inf; /** Stop searching because the current level is final? **/ if (stAttrValue(stLookup(search_inf,"final"),NULL,&ptr,0) == 0 && !strcasecmp(ptr,"yes")) { obj->SubCnt = i - obj->SubPtr + 1; break; } } /** Set object params. **/ inf->Node = node; inf->Data = search_inf; strcpy(inf->Pathname, obj_internal_PathPart(obj->Pathname,0,0)); inf->Node->OpenCnt++; return (void*)inf; }
/*** stxSetAttrValue - sets the value of an attribute. 'val' must *** point to an appropriate data type. ***/ int stxSetAttrValue(void* inf_v, char* attrname, int datatype, pObjData val, pObjTrxTree oxt) { pStxData inf = STX(inf_v); pStructInf find_inf; int t; /** Choose the attr name **/ if (!strcmp(attrname,"name")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch setting attribute '%s' (should be string)", attrname); return -1; } if (inf->Data == inf->Node->Data) { if (!strcmp(inf->Obj->Pathname->Pathbuf,".")) return -1; if (strlen(inf->Obj->Pathname->Pathbuf) - strlen(strrchr(inf->Obj->Pathname->Pathbuf,'/')) + strlen(val->String) + 1 > 255) { mssError(1,"STX","SetAttr 'name': name too large for internal representation"); return -1; } strcpy(inf->Pathname, inf->Obj->Pathname->Pathbuf); strcpy(strrchr(inf->Pathname,'/')+1,val->String); if (rename(inf->Obj->Pathname->Pathbuf, inf->Pathname) < 0) { mssError(1,"STX","SetAttr 'name': could not rename structure file node object"); return -1; } strcpy(inf->Obj->Pathname->Pathbuf, inf->Pathname); } strcpy(inf->Data->Name,val->String); return 0; } /** Set content type if that was requested. **/ if (!strcmp(attrname,"content_type")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch setting attribute '%s' (should be string)", attrname); return -1; } strcpy(inf->Data->UsrType,val->String); return 0; } /** Otherwise, set the integer or string value **/ find_inf = stLookup(inf->Data,attrname); if (!find_inf) { mssError(1,"STX","Requested structure file attribute not found"); return -1; } if (stStructType(find_inf) != ST_T_ATTRIB) return -1; /** Set value of attribute **/ t = stGetAttrType(find_inf, 0); if (t <= 0) return -1; if (datatype != t) { mssError(1,"STX","Type mismatch setting attribute '%s' [requested=%s, actual=%s", attrname, obj_type_names[datatype], obj_type_names[t]); return -1; } stSetAttrValue(find_inf, t, val, 0); /** Set dirty flag **/ inf->Node->Status = SN_NS_DIRTY; return 0; }
/*** stxGetAttrValue - get the value of an attribute by name. The 'val' *** pointer must point to an appropriate data type. ***/ int stxGetAttrValue(void* inf_v, char* attrname, int datatype, pObjData val, pObjTrxTree* oxt) { pStxData inf = STX(inf_v); pStructInf find_inf; int rval; /** Choose the attr name **/ if (!strcmp(attrname,"name")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be string)", attrname); return -1; } val->String = inf->Data->Name; return 0; } /** If content-type, return as appropriate **/ if (!strcmp(attrname,"content_type") || !strcmp(attrname,"inner_type")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be string)", attrname); return -1; } if (stLookup(inf->Data,"content")) val->String = "application/octet-stream"; else val->String = "system/void"; return 0; } else if (!strcmp(attrname,"outer_type")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be string)", attrname); return -1; } val->String = inf->Data->UsrType; return 0; } /** Look through the attribs in the subinf **/ find_inf = stLookup(inf->Data, attrname); /** If annotation, and not found, return "" **/ if (!find_inf && !strcmp(attrname,"annotation")) { if (datatype != DATA_T_STRING) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be string)", attrname); return -1; } val->String = ""; return 0; } /** Not found, or not an attribute? **/ if (!find_inf) return 1; if (stStructType(find_inf) != ST_T_ATTRIB) return -1; /** Vector or scalar? **/ if (find_inf->Value->NodeType == EXPR_N_LIST) { if (inf->VecData) { nmSysFree(inf->VecData); inf->VecData = NULL; } if (stGetAttrType(find_inf, 0) == DATA_T_INTEGER) { if (datatype != DATA_T_INTVEC) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be intvec)", attrname); return -1; } inf->VecData = stGetValueList(find_inf, DATA_T_INTEGER, &(inf->IVvalue.nIntegers)); val->IntVec = &(inf->IVvalue); val->IntVec->Integers = (int*)(inf->VecData); } else { if (datatype != DATA_T_STRINGVEC) { mssError(1,"STX","Type mismatch getting attribute '%s' (should be stringvec)", attrname); return -1; } /** FIXME - the below StringVec->Strings never gets freed **/ inf->VecData = stGetValueList(find_inf, DATA_T_STRING, &(inf->SVvalue.nStrings)); val->StringVec = &(inf->SVvalue); val->StringVec->Strings = (char**)(inf->VecData); } return 0; } else { rval = stGetAttrValue(find_inf, datatype, val, 0); if (rval < 0) { mssError(1,"STX","Type mismatch or non-existent attribute '%s'", attrname); } return rval; } /*mssError(1,"STX","Could not locate requested structure file attribute");*/ return -1; }
/*** qy_internal_GetQueryItem - finds the first(next) inf item in the .qy *** file to include in this query. Items to include are system/querytree *** type subitems that either have a source= or text= property. Source= *** type subitems will result in zero or more items for the query. Text= *** subitems will result in exactly one returned object for the query. *** Text= types cannot be modified/etc by the enduser. The .qy must be *** opened as a structure file (via objdrv_struct) to modify Text=items. *** modifications/addidions/deletions of query results from a Source= *** item will be passed on to the source driver (such as objdrv_sybase). ***/ int qy_internal_GetQueryItem(pQyQuery qy) { pStructInf main_inf; pStructInf find_inf; char* val; char* ptr; /** Already hit end of query? **/ if (qy->NextSubInfID == -1) return -1; /** Need to 'prime' the struct table? **/ if (qy->StructTable.nItems == 0) { find_inf = qy->ObjInf->NodeData; while(find_inf) { if (find_inf->Type == ST_T_SUBGROUP) xhAdd(&qy->StructTable, find_inf->Name, (void*)find_inf); find_inf = find_inf->Parent; } } /** Search for a SOURCE= or TEXT= subgroup inf **/ main_inf = qy->ObjInf->NodeData; while(qy->NextSubInfID < main_inf->nSubInf) { find_inf = main_inf->SubInf[qy->NextSubInfID++]; if (find_inf->Type == ST_T_ATTRIB && !strcmp(find_inf->Name, "recurse")) { stGetAttrValue(find_inf, DATA_T_STRING, POD(&ptr), 0); find_inf = (pStructInf)xhLookup(&qy->StructTable, ptr); if (!find_inf) continue; } if (find_inf->Type == ST_T_SUBGROUP) { xhAdd(&qy->StructTable, find_inf->Name, (void*)find_inf); val = NULL; stAttrValue(stLookup(find_inf,"text"),NULL,&val,0); if (val) { qy->ItemText = val; qy->ItemSrc = NULL; qy->ItemWhere = NULL; return qy->NextSubInfID - 1; } stAttrValue(stLookup(find_inf,"source"),NULL,&val,0); if (val) { qy->ItemText = NULL; qy->ItemSrc = val; qy->ItemWhere = NULL; stAttrValue(stLookup(find_inf,"where"),NULL,&(qy->ItemWhere),0); return qy->NextSubInfID - 1; } } } /** End of query. **/ qy->NextSubInfID = -1; return -1; }
/****type checking****/ void typeCheck(TreeNode* node) { TreeNode* argPtr=NULL; StPara* stParaPtr=NULL; StNode* stPtr; int i; /***postorder travel***/ for(i=0;i<MAXCHILDREN;i++){ if(node->child[i]!=NULL){ typeCheck(node->child[i]); } } /***check***/ switch(node->kind){ case DeclK:{ /*declaration, already have types, no operation*/ switch(node->subkind.declType){ case SimVarDcl:{ break; } case ArrVarDcl:{ break; } case FunDcl:{ break; } } break; } case ParaK:{ /*parameters, already have types, no operation*/ switch(node->subkind.paraType){ case Simple:{ break; } case Array:{ break; } } break; } case StmtK:{ switch(node->subkind.stmtType){ case ComStmt:{ /*compound statement, nothing to check*/ if(node->child[0]!=NULL) node->type=node->child[0]->type; else{} break; } case ExprStmt:{ /*expression statement, nothing to check*/ if(node->child[0]!=NULL) node->type=node->child[0]->type; break; } case SeleStmt:{ /*if statement, check if the condition is boolean*/ if(node->child[0]->type!=Boolean){ printf("error:line %d:condition must be a boolean value\n",node->lineno); Error=1; } break; } case IterStmt:{ /*while statement, check if the condition is boolean*/ if(node->child[0]->type!=Boolean){ printf("error:line %d:condition must be a boolean value\n",node->lineno); Error=1; } break; } case ReturnStmt:{ /*reutrn statement, check if the type is compatible with the funcation declaration*/ if(node->child[0]==NULL){ if(node->handle->funType!=Void){ printf("error:line %d:return value not compatible\n",node->lineno); Error=1; } } else{ node->type=node->child[0]->type; if(node->handle->funType!=node->child[0]->type){ printf("error:line %d:return value not compatible\n",node->lineno); Error=1; } } break; } } break; } case ExprK:{ switch(node->subkind.exprType){ case AssignExp:{ /*assigment expresstion, check if the type is compatible*/ if(node->child[0]->type!=node->child[1]->type){ printf("error:line %d:type error while assign to %s\n",node->lineno,node->child[0]->attr.name); Error=1; } node->type=node->child[0]->type; break; } case SimpExp:{ if(node->child[1]==NULL){ /***just one expresstion***/ node->type=node->child[0]->type; } else{ if(node->child[0]->type!=node->child[1]->type){ printf("error:line %d:operand type not compatible\n",node->lineno); Error=1; } node->type=Boolean; } break; } } break; } case VarK:{ switch(node->subkind.varType){ /**variables, check if it is declared**/ case ArrayVar:{ stPtr=stLookup(node->handle,node->attr.name); if(stPtr==NULL){ printf("error:line %d:%s has not been declared as a variable\n",node->lineno,node->attr.name); Error=1; node->type=Integer; } else{ if(stPtr->type==IntArray) node->type=Integer; else if(stPtr->type==VoidArray) node->type=Void; else node->type=Boolean; } break; } case SimpVar:{ stPtr=stLookup(node->handle,node->attr.name); if(stPtr==NULL){ printf("error:line %d:%s is not a variable\n",node->lineno,node->attr.name); Error=1; node->type=Integer; } else{ node->type=stPtr->type; } break; } } break; } case AddexprK:{ if(node->child[0]->type!=node->child[1]->type){ printf("error:line %d:operand type not compatible\n",node->lineno); Error=1; } node->type=node->child[0]->type; break; } case TermK:{ switch(node->subkind.termType){ case Multiple:{ /***term type with mulop, check if two operand is compatible**/ if(node->child[0]->type!=node->child[1]->type){ printf("error:line %d:operand type not compatible\n",node->lineno); Error=1; } node->type=node->child[0]->type; break; } case Single:{ /**single factor, just assign type**/ node->type=node->child[0]->type; break; } } break; } case FactK:{ switch(node->subkind.factorType){ case Expr:{ /**expression, **/ node->type=node->child[0]->type; break; } case Var:{ /**variable, assign type of variable**/ node->type=node->child[0]->type; break; } case Call:{ /**call factor, assign the type of the function**/ node->type=node->child[0]->type; break; } case Num:{ /**just a Integer**/ node->type=Integer; break; } } break; } case CallK:{ /***call function***/ stPtr=stLookup(node->handle,node->attr.name); if(stPtr==NULL || stPtr->isFun==0){ /**check if the function is declared**/ printf("error: line %d: %s is not a function name\n",node->lineno,node->attr.name); Error=1; node->type=Integer; } else{ /**check if the arguements is all right**/ argPtr=node->child[0]; stParaPtr=stPtr->para; while(argPtr!=NULL && stParaPtr!=NULL){ if(argPtr->type!=stParaPtr->type){ printf("error:line %d:arguement type not compatible\n",node->lineno); Error=1; } argPtr=argPtr->sibling; stParaPtr=stParaPtr->next; } if(argPtr!=NULL || stParaPtr!=NULL){ printf("error:line %d:arguement number not compatible\n",node->lineno); Error=1; } node->type=stPtr->type; } break; } case ArgsK:{ break; } } /*****travel the sibling******/ if(node->sibling!=NULL){ typeCheck(node->sibling); } }
/*** uxpGetAttrValue - get the value of an attribute by name. The 'val' *** pointer must point to an appropriate data type. ***/ int uxpGetAttrValue(void* inf_v, char* attrname, int datatype, pObjData val, pObjTrxTree* oxt) { pUxpData inf = UXP(inf_v); char* ptr; pStructInf find_inf; /** Choose the attr name **/ if (!strcmp(attrname,"name")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } ptr = strrchr(inf->Obj->Pathname->Pathbuf+1,'/')+1; if (ptr) { strcpy(inf->Pathname,ptr); val->String = inf->Pathname; } else { val->String = "/"; } /* val->String = inf->Node->Data->Name;*/ } else if (!strcmp(attrname,"content_type") || !strcmp(attrname,"inner_type")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } stAttrValue(stLookup(inf->Node->Data,"type"), NULL, &ptr, 0); val->String = ptr; } else if (!strcmp(attrname,"outer_type")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } val->String = "system/printer"; } else if (!strcmp(attrname,"spool_file")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } val->String = inf->SpoolPathname; } else { /** Lookup in the structinf tree. **/ find_inf = stLookup(inf->Node->Data, attrname); if (!find_inf && !strcmp(attrname,"annotation")) { if (datatype != DATA_T_STRING) { mssError(1,"UXP","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } val->String = "Printer"; return 0; } else if (!find_inf) { mssError(1,"UXP","Invalid attribute for printer object"); return -1; } /** Found it - return the value **/ return stGetAttrValue(find_inf, datatype, val, 0); } return 0; }
/*** uxpWrite - write to a new print job. Each time this driver is opened *** and written to, it spools a new print job. ***/ int uxpWrite(void* inf_v, char* buffer, int cnt, int offset, int flags, pObjTrxTree* oxt) { pUxpData inf = UXP(inf_v); int rval; char* spooldir = NULL; char* type = NULL; struct stat fileinfo; int start_filter = 0; int saved_errno; /** Start the filter process? **/ if (!inf->SpoolFileFD && !inf->MasterFD) { start_filter = 1; } /** Ok, need to create a new print job? **/ if (inf->SpoolFileFD == NULL) { /** Get spool dir. **/ stAttrValue(stLookup(inf->Node->Data,"spool_directory"), NULL, &spooldir, 0); if (!spooldir) { mssError(1,"UXP","Spool directory not specified in node object"); return -1; } /** Generate a spool file name **/ TRY_SPOOL_AGAIN: do { sprintf(inf->SpoolPathname,"%s/%8.8d.job",spooldir,UXP_INF.SpoolCnt++); } while (lstat(inf->SpoolPathname, &fileinfo) == 0); /** Open the spool file **/ inf->SpoolFileFD = fdOpen(inf->SpoolPathname, O_WRONLY | O_CREAT | O_EXCL, 0600); if (!inf->SpoolFileFD) { /** oops - race condition, someone else got it, try again **/ saved_errno = errno; if (lstat(inf->SpoolPathname, &fileinfo) == 0) goto TRY_SPOOL_AGAIN; /** Oh well, can't open the thing. **/ /** Shouldn't be writing to errno, but mssErrorErrno wants it... sigh... **/ errno = saved_errno; mssErrorErrno(1,"UXP","Could not open spool file"); return -1; } } /** Ok, delayed start of filter process to wait until spoofile-fd is open **/ if (start_filter) { stAttrValue(stLookup(inf->Node->Data,"type"), NULL, &type, 0); if (type && strcmp(type, inf->ReqType) && !strcmp(inf->ReqType,"text/html")) { uxp_internal_StartFilter(inf); } } /** Need to filter the data? **/ if (inf->MasterFD) { rval = fdWrite(inf->MasterFD, buffer, cnt, offset, flags); } else { /** Write to the spool file. **/ rval = fdWrite(inf->SpoolFileFD, buffer, cnt, offset, flags); } return rval; }
/*** uxp_internal_LoadPrintQueue - load the information from the print queue *** into the print queue structures for further examination and reporting/ *** querying to the user. Takes path to the printer node as the parameter, *** and returns a pointer to the print queue structure. ***/ pLprPrintQueue uxp_internal_LoadPrintQueue(char* nodepath, pSnNode nodeinfo) { pLprPrintQueue pq; int pipefd[2]; pFile fd; char* lpname; char* spoolname; pLxSession lxs; int t; char* str; int childpid; char user[32]; char filename[128]; int rank,jobid; int cnt; pLprQueueEntry e; /** Find out if this print queue is already hashed. **/ pq = (pLprPrintQueue)xhLookup(&UXP_INF.PrintQueues, nodepath); /** If not, create new entry. **/ if (!pq) { pq = (pLprPrintQueue)nmMalloc(sizeof(LprPrintQueue)); xaInit(&pq->Entries, 16); strcpy(pq->Pathname, nodepath); xhAdd(&UXP_INF.PrintQueues, pq->Pathname, (void*)pq); } /** Determine printer's name, and centrallix spool dir. **/ stAttrValue(stLookup(nodeinfo->Data,"unix_name"), NULL, &lpname, 0); stAttrValue(stLookup(nodeinfo->Data,"spool_directory"), NULL, &spoolname, 0); /** Ok, now open a pipe from the 'lpq' command. **/ socketpair(AF_UNIX, SOCK_STREAM, 0, pipefd); if ((childpid=fork())) { /** Close the child's end of the pipe, since we don't use it in the parent **/ close(pipefd[1]); /** Open an fd to the pipe **/ fd = fdOpenFD(pipefd[0],O_RDONLY); /** Open an mtlexer session **/ lxs = mlxOpenSession(fd, MLX_F_EOL | MLX_F_EOF | MLX_F_IFSONLY); /** Read until we get "Rank" at the beginning of a line. **/ while(1) { t = mlxNextToken(lxs); if (t != MLX_TOK_STRING) { kill(childpid,SIGKILL); wait(NULL); return pq; } str = mlxStringVal(lxs,0); while ((t=mlxNextToken(lxs) != MLX_TOK_EOL && t != MLX_TOK_ERROR)); if (!strcmp(str,"Rank")) break; } /** Clean out any existing entries from our internal queue list. **/ while(pq->Entries.nItems) { nmFree(pq->Entries.Items[0],sizeof(LprQueueEntry)); xaRemoveItem(&pq->Entries,0); } /** Ok, should be one line per print job now **/ for(cnt=0;;) { /** Get rank, owner, jobid, filename **/ if (mlxNextToken(lxs) != MLX_TOK_STRING) break; rank = strtoi(mlxStringVal(lxs,0),NULL,10); if (mlxNextToken(lxs) != MLX_TOK_STRING) break; mlxCopyToken(lxs,user,32); if (mlxNextToken(lxs) != MLX_TOK_STRING) break; jobid = strtoi(mlxStringVal(lxs,0),NULL,10); if (mlxNextToken(lxs) != MLX_TOK_STRING) break; mlxCopyToken(lxs,filename,128); /** If it isn't our file, skip to eol and continue looking **/ if (strncmp(filename, spoolname, strlen(spoolname))) { while ((t=mlxNextToken(lxs) != MLX_TOK_EOL && t != MLX_TOK_ERROR)); continue; } /** Create the queue entry structure **/ e = (pLprQueueEntry)nmMalloc(sizeof(LprQueueEntry)); e->JobID = jobid; strcpy(e->User,user); e->Percent = 0; if (cnt==0) strcpy(e->Status,"Printing"); else strcpy(e->Status,"Queued"); strcpy(e->Pathname, filename); strcpy(e->Name, strrchr(filename,'/')+1); /** Get the file's size and skip to eol. **/ if (mlxNextToken(lxs) != MLX_TOK_STRING) break; e->Size = strtoi(mlxStringVal(lxs,0),NULL,10); while ((t=mlxNextToken(lxs) != MLX_TOK_EOL && t != MLX_TOK_ERROR)); /** Add entry to our queue list **/ xaAddItem(&pq->Entries, (void*)e); cnt++; } /** Wait on lpq's completion. **/ wait(NULL); } else { /** Close the parent's end of the pipe, since we don't use it in the child **/ close(pipefd[0]); /** Make the pipe lpq's standard input and output **/ close(0); close(1); close(2); dup(pipefd[1]); dup(pipefd[1]); dup(pipefd[1]); /** Execute the lpq process, exit if failed. **/ execlp("lpq","lpq","-P",lpname,NULL); _exit(0); } return pq; }
/*** qytGetAttrValue - get the value of an attribute by name. The 'val' *** pointer must point to an appropriate data type. ***/ int qytGetAttrValue(void* inf_v, char* attrname, int datatype, pObjData val, pObjTrxTree* oxt) { pQytData inf = QYT(inf_v); pStructInf content_inf; int rval; /** Choose the attr name **/ if (!strcmp(attrname,"name")) { if (datatype != DATA_T_STRING) { mssError(1,"QYT","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } if (inf->Obj->Mode & OBJ_O_AUTONAME && inf->LLObj) { return objGetAttrValue(inf->LLObj, "name", DATA_T_STRING, val); } else { val->String = obj_internal_PathPart(inf->Obj->Pathname, inf->Obj->Pathname->nElements - 1, 0); obj_internal_PathPart(inf->Obj->Pathname,0,0); } return 0; } /** annotation? **/ if (!strcmp(attrname,"annotation")) { if (datatype != DATA_T_STRING) { mssError(1,"QYT","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } /** If object associated, get annot from it **/ if (inf->LLObj) return objGetAttrValue(inf->LLObj, attrname, datatype, val); /** Otherwise, get annot from node if it has it **/ if (stGetAttrValue(stLookup(inf->NodeData,attrname), DATA_T_STRING, val, 0) == 0) { return 0; } else { val->String = ""; return 0; } } /** If content-type, return as appropriate **/ if (!strcmp(attrname,"outer_type") && !(inf->LLObj)) { if (datatype != DATA_T_STRING) { mssError(1,"QYT","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } val->String = inf->NodeData->UsrType; return 0; } else if ((!strcmp(attrname,"content_type") || !strcmp(attrname,"inner_type")) && !(inf->LLObj)) { if (datatype != DATA_T_STRING) { mssError(1,"QYT","Type mismatch accessing attribute '%s' (should be string)", attrname); return -1; } if (stLookup(inf->NodeData, "content")) { if ((content_inf = stLookup(inf->NodeData, "content_type")) != NULL) stGetAttrValue(content_inf, DATA_T_STRING, val, 0); else val->String = "text/plain"; } else { val->String = "system/void"; } return 0; } /** Low-level object? Lookup the attribute in it **/ if (inf->LLObj) { rval = objGetAttrValue(inf->LLObj, attrname, datatype, val); if (rval != 0 && (!strcmp(attrname,"inner_type") || !strcmp(attrname,"content_type")) && datatype == DATA_T_STRING) { val->String = "application/octet-stream"; return 0; } if (rval != 0 && !strcmp(attrname,"outer_type") && datatype == DATA_T_STRING) { val->String = "system/object"; return 0; } if (rval < 0 && !strcmp(attrname,"last_modification")) return 1; return rval; } /** last_modification? Lookup from node **/ if (!strcmp(attrname,"last_modification")) { val->DateTime = snGetLastModification(inf->BaseNode); return 0; } mssError(1,"QYT","Invalid attribute '%s' for querytree object", attrname); return -1; }
/*** qyt_internal_ProcessPath - handles the lookup of the snNode from the given *** path in the querytree, and the optional creation of a new entity, as needed, *** manipulating the WHERE sql in the snNode to assign parent foreign key links *** and so forth. ***/ pQytData qyt_internal_ProcessPath(pObjSession s, pPathname path, pSnNode node, int subref, pStructInf dptr, int openflags, int no_open) { pQytData inf; pStructInf lookup_inf, find_inf, next_inf; char* strval; char* exprval; char* ptr; int i,v,t; pExpression expr; pParamObjects objlist; pObject test_obj; XHashTable struct_table; XString sql; pObjQuery test_qy; char createpath[OBJSYS_MAX_PATH+1]; /** Setup the pathname into its subparts **/ for(i=1;i<path->nElements;i++) path->Elements[i][-1] = 0; /** Allocate the data info first **/ inf = (pQytData)nmMalloc(sizeof(QytData)); if (!inf) return NULL; memset(inf,0,sizeof(QytData)); inf->BaseNode = node; inf->LLObj = NULL; inf->Offset = 0; /** Create the object parameter list... **/ objlist = expCreateParamList(); /** Initialize the listing of query tree elements **/ xhInit(&struct_table, 17, 0); /** Look for the part of the structinf which this path references. **/ while(subref < path->nElements) { /** Add a slot to the param object list for this tree level **/ objlist->ParentID = objlist->CurrentID; /** Look for text and source items in the querytree definition. **/ next_inf = NULL; for(i=0;i<dptr->nSubInf;i++) { find_inf = dptr->SubInf[i]; if (stStructType(find_inf) == ST_T_SUBGROUP) { PROCESS_SUBGROUP: inf->Pathname[0] = '\0'; inf->Flags = 0; if ((lookup_inf = stLookup(find_inf, "text"))) { strval = ""; stAttrValue(lookup_inf,NULL,&strval,0); if (!strcmp(path->Elements[subref],strval)) { expAddParamToList(objlist,strval,NULL,EXPR_O_CURRENT | EXPR_O_ALLOWDUPS); next_inf = find_inf; break; } if (subref == path->nElements - 1) inf->LLObj = NULL; } else if ((lookup_inf = stLookup(find_inf, "sql"))) { xhAdd(&struct_table, find_inf->Name, (void*)find_inf); /** not opening objects? skip sql query if so **/ if (no_open) { next_inf = find_inf; break; } /** forced leaf flag and having clause flag **/ strval = NULL; stAttrValue(stLookup(find_inf, "force_leaf"), NULL, &strval, 0); if (strval && !strcasecmp(strval,"yes")) inf->Flags |= QYT_F_FLEAF; strval = NULL; stAttrValue(stLookup(find_inf, "use_having"), NULL, &strval, 0); if (strval && !strcasecmp(strval,"yes")) inf->Flags |= QYT_F_USEHAVING; /** build and run the sql query to find the object **/ expAddParamToList(objlist,find_inf->Name,NULL,EXPR_O_CURRENT | EXPR_O_ALLOWDUPS); xsInit(&sql); strval = ""; expr = NULL; t = stGetAttrType(lookup_inf, 0); if (t == DATA_T_STRING) { stAttrValue(lookup_inf, NULL, &strval, 0); } else if (t == DATA_T_CODE) { if (stGetAttrValue(lookup_inf, DATA_T_CODE, POD(&expr), 0) == 0) { expr = expDuplicateExpression(expr); if (expr) { objlist->Session = s; expBindExpression(expr, objlist, EXPR_F_RUNSERVER); if (expEvalTree(expr, objlist) == 0 && expr->DataType == DATA_T_STRING && !(expr->Flags & EXPR_F_NULL)) strval = expr->String; } } } if (!strcmp(strval, "")) { if (expr) expFreeExpression(expr); mssError(0,"QYT","Invalid SQL for '%s'",find_inf->Name); goto error; } xsQPrintf(&sql, "%STR %STR :name = %STR&DQUOT", strval, (inf->Flags & QYT_F_USEHAVING)?"HAVING":"WHERE", path->Elements[subref]); if (expr) expFreeExpression(expr); expr = NULL; test_obj = NULL; test_qy = objMultiQuery(s, sql.String, objlist, 0); if (test_qy) { /** sizeof(createpath)-2 to leave room for two chars **/ if (objGetQueryIdentityPath(test_qy, createpath, sizeof(createpath) - 2) < 0) createpath[0] = '\0'; /** query open succeeded, try to fetch a result **/ test_obj = objQueryFetch(test_qy, O_RDONLY); /** are we creating a new object? **/ if (!test_obj && subref == path->nElements - 1 && (openflags & O_CREAT) && createpath[0]) { /** We left room for these two chars in the ** above call to objGetQueryIdentityPath(). **/ strcat(createpath, "/*"); test_obj = objOpen(s, createpath, O_RDWR | O_TRUNC | (openflags & (O_CREAT | OBJ_O_AUTONAME)), 0600, "system/file"); } objQueryClose(test_qy); } xsDeInit(&sql); if (!test_obj) continue; /** ok, found the object **/ expModifyParam(objlist,NULL,test_obj); objUnmanageObject(test_obj->Session, test_obj); if (subref == path->nElements - 1) { inf->LLObj = objLinkTo(test_obj); } next_inf = find_inf; break; } else if ((lookup_inf = stLookup(find_inf, "source"))) { strval = ""; stAttrValue(lookup_inf,NULL,&strval,0); expr = NULL; exprval = NULL; stAttrValue(stLookup(find_inf, "where"),NULL,&exprval,0); if (exprval && !no_open) { //objlist->Names[(signed char)(objlist->CurrentID)] = find_inf->Name; expr = (pExpression)expCompileExpression(exprval, objlist, MLX_F_ICASE | MLX_F_FILENAMES, 0); } snprintf(inf->Pathname,sizeof(inf->Pathname),"%s/%s?ls__type=application%%2foctet-stream",strval,path->Elements[subref]); /** forced leaf flag **/ strval = NULL; stAttrValue(stLookup(find_inf, "force_leaf"), NULL, &strval, 0); if (strval && !strcasecmp(strval,"yes")) inf->Flags |= QYT_F_FLEAF; strval = NULL; stAttrValue(stLookup(find_inf, "use_having"), NULL, &strval, 0); if (strval && !strcasecmp(strval,"yes")) inf->Flags |= QYT_F_USEHAVING; /** Setup this querytree struct entry for lookups **/ xhAdd(&struct_table, find_inf->Name, (void*)find_inf); expAddParamToList(objlist,find_inf->Name,NULL,EXPR_O_CURRENT | EXPR_O_ALLOWDUPS); /** Not opening any objects? Skip open attempt if so. **/ if (no_open) { next_inf = find_inf; break; } /** Open the object, or create if need be. If create, convert any WHERE to setattrs **/ test_obj = objOpen(s, inf->Pathname, O_RDONLY, 0600, "system/file"); if (test_obj) { expModifyParam(objlist, NULL, test_obj); objUnmanageObject(test_obj->Session, test_obj); } if (!test_obj && subref == path->nElements - 1 && (openflags & O_CREAT)) { test_obj = objOpen(s, inf->Pathname, O_RDWR | O_TRUNC | (openflags & (O_CREAT | OBJ_O_AUTONAME)), 0600, "system/file"); if (!test_obj) continue; expModifyParam(objlist, NULL, test_obj); objUnmanageObject(test_obj->Session, test_obj); objlist->Flags[(signed char)(objlist->CurrentID)] |= EXPR_O_UPDATE; if (expr) { /** Reverse eval the expression to set the object attributes **/ expr->Integer = 1; v = expReverseEvalTree(expr, objlist); expFreeExpression(expr); expr = NULL; if (v < 0) { objClose(test_obj); expModifyParam(objlist, NULL, NULL); break; } } } else if (!test_obj) continue; /** Validate the where clause expression if need be. **/ objlist->Session = s; v = !expr || (expEvalTree(expr,objlist) >= 0 && expr->Integer != 0); if (expr) expFreeExpression(expr); expr = NULL; if (subref == path->nElements - 1) { inf->LLObj = objLinkTo(test_obj); } /*else { if (!v) objClose(test_obj); }*/ if (v) { next_inf = find_inf; break; } } } else if (!strcmp(find_inf->Name,"recurse")) { expr = NULL; exprval = NULL; stAttrValue(stLookup(dptr, "known_leaf"),NULL,&exprval,0); expAddParamToList(objlist,find_inf->Name,NULL,EXPR_O_CURRENT | EXPR_O_ALLOWDUPS); if (exprval) { expr = (pExpression)expCompileExpression(exprval, objlist, MLX_F_ICASE | MLX_F_FILENAMES, 0); if (!expr) { mssError(0,"QYT","Error in known_leaf expression"); break; } else { v = (expEvalTree(expr,objlist) >= 0 && expr->Integer != 0); expFreeExpression(expr); expr = NULL; if (v) break; } } expRemoveParamFromList(objlist, find_inf->Name); stGetAttrValue(find_inf, DATA_T_STRING, POD(&ptr), 0); find_inf = (pStructInf)xhLookup(&struct_table, ptr); if (find_inf) goto PROCESS_SUBGROUP; } } /** Didn't find? **/ if (!next_inf) { inf->LLObj = NULL; mssError(0,"QYT","Could not find object via access through querytree"); goto error; } dptr = next_inf; subref++; } /** Ok, close up the structure table. **/ xhClear(&struct_table, NULL, NULL); xhDeInit(&struct_table); inf->NodeData = dptr; inf->ObjList = objlist; return inf; error: /** Ok, close up the structure table. **/ xhClear(&struct_table, NULL, NULL); xhDeInit(&struct_table); if (objlist) { for(i=0;i<objlist->nObjects-1;i++) if (objlist->Objects[i]) objClose(objlist->Objects[i]); expFreeParamList(objlist); } nmFree(inf,sizeof(QytData)); return NULL; }
/*** shlOpen - open an object. ***/ void* shlOpen(pObject obj, int mask, pContentType systype, char* usrtype, pObjTrxTree* oxt) { pShlData inf; int rval; char* node_path; pSnNode node = NULL; char* ptr; pStructInf argStruct; pStructInf changeStruct; int i,j; pStruct paramdata; int nameindex; char* endorsement_name; /** Allocate the structure **/ inf = (pShlData)nmMalloc(sizeof(ShlData)); if (!inf) return NULL; memset(inf,0,sizeof(ShlData)); inf->Obj = obj; inf->Mask = mask; obj->SubCnt=1; if(SHELL_DEBUG & SHELL_DEBUG_INIT) printf("%s was offered: (%i,%i,%i) %s\n",__FILE__,obj->SubPtr, obj->SubCnt,obj->Pathname->nElements,obj_internal_PathPart(obj->Pathname,0,0)); /** Determine the node path **/ node_path = obj_internal_PathPart(obj->Pathname, 0, obj->SubPtr); if(SHELL_DEBUG & SHELL_DEBUG_OPEN) printf("opening: %s\n",node_path); /** If CREAT and EXCL, we only create, failing if already exists. **/ if ((obj->Mode & O_CREAT) && (obj->Mode & O_EXCL) && (obj->SubPtr == obj->Pathname->nElements)) { node = snNewNode(obj->Prev, usrtype); if (!node) { nmFree(inf,sizeof(ShlData)); mssError(0,"SHL","Could not create new node object"); return NULL; } } /** Otherwise, try to open it first. **/ if (!node) { node = snReadNode(obj->Prev); } /** If no node, and user said CREAT ok, try that. **/ if (!node && (obj->Mode & O_CREAT) && (obj->SubPtr == obj->Pathname->nElements)) { node = snNewNode(obj->Prev, usrtype); } /** If _still_ no node, quit out. **/ if (!node) { nmFree(inf,sizeof(ShlData)); mssError(0,"SHL","Could not open structure file"); return NULL; } /** Set object params. **/ inf->Node = node; strcpy(inf->Pathname, obj_internal_PathPart(obj->Pathname,0,0)); inf->Node->OpenCnt++; /** Security check **/ if (endVerifyEndorsements(node->Data, stGetObjAttrValue, &endorsement_name) < 0) { inf->Node->OpenCnt --; nmFree(inf,sizeof(ShlData)); mssError(1,"SHL","Security check failed - endorsement '%s' required", endorsement_name); return NULL; } /** figure out command to run **/ if(stAttrValue(stLookup(node->Data,"program"),NULL,&ptr,0)<0) ptr=""; strncpy(inf->program,ptr,79); inf->program[79]='\0'; if(SHELL_DEBUG & SHELL_DEBUG_PARAM) printf("program: %s\n",inf->program); argStruct=stLookup(node->Data,"arg"); /** init structures for holding arguments and environmental variables **/ xaInit(&inf->argArray,argStruct?5:1); xaInit(&inf->envArray,3); xaInit(&inf->envList,3); xhInit(&inf->envHash,17,0); if(!argStruct) { /** no 'arg' value present -- no parameters **/ } else { if(argStruct->Value->NodeType == EXPR_N_LIST) { /** 'arg' value is present and is a list -- parameters > 1 **/ int i; pXArray values; values = &argStruct->Value->Children; for(i=0;i<values->nItems;i++) xaAddItem(&inf->argArray,((pExpression)(values->Items[i]))->String); } else { char *ptr; /** 'arg' value is present and is exactly one value -- 1 parameter **/ if(stAttrValue(argStruct,NULL,&ptr,0)<0) ptr=NULL; xaAddItem(&inf->argArray,ptr); } xaAddItem(&inf->argArray,NULL); } for(i=0;i<node->Data->nSubInf;i++) { pStructInf str = node->Data->SubInf[i]; if (strcmp(str->Name, "program") && strcmp(str->Name,"arg") && strcmp(str->Name,"changeable") ) { pEnvVar pEV = (pEnvVar)nmMalloc(sizeof(EnvVar)); if(stAttrValue(str,NULL,&pEV->value,0)<0) pEV->value=NULL; pEV->changeable = 0; pEV->shouldfree = 0; xhAdd(&inf->envHash,str->Name,(char*)pEV); // add it to the hash xaAddItem(&inf->envList,str->Name); // add the name to the list } } changeStruct=stLookup(node->Data,"changeable"); if(changeStruct) { if(changeStruct->Value->NodeType == EXPR_N_LIST) { /** 'arg' value is present and is a list -- parameters > 1 **/ int i; pXArray values; pEnvVar pEV=NULL; values = &argStruct->Value->Children; for(i=0;i<values->nItems;i++) { pEV=(pEnvVar)xhLookup(&inf->envHash,((pExpression)(values->Items[i]))->String); if(pEV) { pEV->changeable = 1; } else mssError(0,"SHL","can't find %s to mark changeable\n",((pExpression)(values->Items[i]))->String); } } else { char *ptr; pEnvVar pEV=NULL; /** 'arg' value is present and is exactly one value -- 1 parameter **/ if(stAttrValue(changeStruct,NULL,&ptr,0)<0) ptr=NULL; if(ptr) pEV=(pEnvVar)xhLookup(&inf->envHash,ptr); if(pEV) { pEV->changeable = 1; } else mssError(0,"SHL","can't find %s to mark changeable\n",ptr); } } /** note that the child process hasn't been started yet **/ inf->shell_pid = -1; /** this is set to 1 when a read fails with EIO **/ inf->done = 0; if(SHELL_DEBUG & SHELL_DEBUG_OPEN) printf("SHELL: returning object: %p\n",inf); /** Set initial param values? **/ nameindex = obj->SubPtr - 1 + obj->SubCnt - 1; if (obj->Pathname->OpenCtl[nameindex]) { paramdata = obj->Pathname->OpenCtl[nameindex]; for(i=0;i<paramdata->nSubInf;i++) { shl_internal_SetParam(inf, paramdata->SubInf[i]->Name, DATA_T_STRING, POD(&(paramdata->SubInf[i]->StrVal))); } } return (void*)inf; }
/*** qyt_internal_GetQueryItem - finds the first(next) inf item in the .qyt *** file to include in this query. Items to include are system/querytree *** type subitems that either have a source= or text= property. Source= *** type subitems will result in zero or more items for the query. Text= *** subitems will result in exactly one returned object for the query. *** Text= types cannot be modified/etc by the enduser. The .qyt must be *** opened as a structure file (via objdrv_struct) to modify Text=items. *** modifications/addidions/deletions of query results from a Source= *** item will be passed on to the source driver (such as objdrv_sybase). ***/ int qyt_internal_GetQueryItem(pQytQuery qy) { pStructInf main_inf; pStructInf find_inf; char* val; char* ptr; int t; /** Already hit end of query? **/ if (qy->NextSubInfID == -1) return -1; /** Need to 'prime' the struct table? **/ if (qy->StructTable.nItems == 0) { find_inf = qy->ObjInf->NodeData; while(find_inf) { if (stStructType(find_inf) == ST_T_SUBGROUP) xhAdd(&qy->StructTable, find_inf->Name, (void*)find_inf); find_inf = find_inf->Parent; } } /** Search for a SOURCE= or TEXT= subgroup inf **/ main_inf = qy->ObjInf->NodeData; /** Is main_inf already a 'recurse' node? **/ /*if (stStructType(main_inf) == ST_T_ATTRIB && !strcmp(main_inf->Name, "recurse")) { stGetAttrValue(main_inf, DATA_T_STRING, POD(&ptr), 0); find_inf = (pStructInf)xhLookup(&qy->StructTable, ptr); if (find_inf) main_inf = find_inf; }*/ /** Do the search **/ while(qy->NextSubInfID < main_inf->nSubInf) { find_inf = main_inf->SubInf[qy->NextSubInfID++]; if (stStructType(find_inf) == ST_T_ATTRIB && !strcmp(find_inf->Name, "recurse")) { stGetAttrValue(find_inf, DATA_T_STRING, POD(&ptr), 0); find_inf = (pStructInf)xhLookup(&qy->StructTable, ptr); if (!find_inf) continue; } qy->ItemText = NULL; qy->ItemSrc = NULL; qy->ItemWhere = NULL; qy->ItemOrder = NULL; qy->ItemSql = NULL; if (qy->ItemSqlExpr) expFreeExpression(qy->ItemSqlExpr); qy->ItemSqlExpr = NULL; if (stStructType(find_inf) == ST_T_SUBGROUP) { xhAdd(&qy->StructTable, find_inf->Name, (void*)find_inf); val = NULL; stAttrValue(stLookup(find_inf,"text"),NULL,&val,0); if (val) { qy->ItemText = val; return qy->NextSubInfID - 1; } stAttrValue(stLookup(find_inf,"source"),NULL,&val,0); if (val) { qy->ItemSrc = val; stAttrValue(stLookup(find_inf,"where"),NULL,&(qy->ItemWhere),0); stAttrValue(stLookup(find_inf,"order"),NULL,&(qy->ItemOrder),0); return qy->NextSubInfID - 1; } t = stGetAttrType(stLookup(find_inf,"sql"), 0); if (t == DATA_T_STRING) { stAttrValue(stLookup(find_inf,"sql"),NULL,&val,0); if (val) { qy->ItemSql = val; return qy->NextSubInfID - 1; } } else if (t == DATA_T_CODE) { stGetAttrValue(stLookup(find_inf,"sql"), DATA_T_CODE, POD(&qy->ItemSqlExpr), 0); if (qy->ItemSqlExpr) { qy->ItemSqlExpr = expDuplicateExpression(qy->ItemSqlExpr); qy->ItemSql = ""; return qy->NextSubInfID - 1; } } } } /** End of query. **/ qy->NextSubInfID = -1; return -1; }
/*** objInfToHints - converts a StructInfo structure tree to a presentation *** hints structure. The StructInfo should be the format of a *** system/parameter. ***/ pObjPresentationHints objInfToHints(pStructInf inf, int data_type) { pObjPresentationHints ph; pParamObjects tmplist; char* ptr; char* newptr; int n,cnt; /** Allocate a new ph structure **/ ph = (pObjPresentationHints)nmMalloc(sizeof(ObjPresentationHints)); memset(ph,0,sizeof(ObjPresentationHints)); xaInit(&(ph->EnumList),16); /** Check for constraint, default, min, and max expressions. **/ stAttrValue(stLookup(inf,"constraint"),NULL,(char**)&(ph->Constraint),0); stAttrValue(stLookup(inf,"default"),NULL,(char**)&(ph->DefaultExpr),0); stAttrValue(stLookup(inf,"min"),NULL,(char**)&(ph->MinValue),0); stAttrValue(stLookup(inf,"max"),NULL,(char**)&(ph->MaxValue),0); /** Compile expressions, if any **/ if (ph->Constraint || ph->DefaultExpr || ph->MinValue || ph->MaxValue) { tmplist = expCreateParamList(); expAddParamToList(tmplist,"this",NULL,EXPR_O_CURRENT); if (ph->Constraint) { ph->Constraint = expCompileExpression(ph->Constraint, tmplist, MLX_F_ICASE | MLX_F_FILENAMES, 0); if (!ph->Constraint) { mssError(0,"OSML","Error in 'constraint' expression"); nmFree(ph,sizeof(ObjPresentationHints)); expFreeParamList(tmplist); return NULL; } ph->DefaultExpr = expCompileExpression(ph->DefaultExpr, tmplist, MLX_F_ICASE | MLX_F_FILENAMES, 0); if (!ph->DefaultExpr) { mssError(0,"OSML","Error in 'default' expression"); nmFree(ph,sizeof(ObjPresentationHints)); expFreeParamList(tmplist); return NULL; } ph->MinValue = expCompileExpression(ph->MinValue, tmplist, MLX_F_ICASE | MLX_F_FILENAMES, 0); if (!ph->MinValue) { mssError(0,"OSML","Error in 'min' expression"); nmFree(ph,sizeof(ObjPresentationHints)); expFreeParamList(tmplist); return NULL; } ph->MaxValue = expCompileExpression(ph->MaxValue, tmplist, MLX_F_ICASE | MLX_F_FILENAMES, 0); if (!ph->MaxValue) { mssError(0,"OSML","Error in 'max' expression"); nmFree(ph,sizeof(ObjPresentationHints)); expFreeParamList(tmplist); return NULL; } } expFreeParamList(tmplist); } /** Enumerated values list, given explicitly? **/ ptr = NULL; cnt = 0; while(stAttrValue(stLookup(inf,"enumlist"),&n, &ptr, cnt) >= 0) { /** Check for string enum or integer enum. **/ if (ptr) { newptr = nmSysStrdup(ptr); } else { newptr = (char*)nmSysMalloc(16); sprintf(newptr,"%d",n); } xaAddItem(&(ph->EnumList), (void*)newptr); cnt++; ptr = NULL; } /** Or, enumerated value list, given via query? **/ if (cnt == 0 && stAttrValue(stLookup(inf,"enumquery"),NULL,&ptr,0) >= 0) { ph->EnumQuery = nmSysStrdup(ptr); } /** Has a presentation format? **/ if (stAttrValue(stLookup(inf,"format"),NULL,&ptr,0) >= 0) { ph->Format = nmSysStrdup(ptr); } /** Permitted and not permitted characters in a string? **/ if (stAttrValue(stLookup(inf,"allowchars"),NULL,&ptr,0) >= 0) { ph->AllowChars = nmSysStrdup(ptr); } if (stAttrValue(stLookup(inf,"badchars"),NULL,&ptr,0) >= 0) { ph->BadChars = nmSysStrdup(ptr); } /** Set VisualLength attributes? **/ if (stAttrValue(stLookup(inf,"length"),&n,NULL,0) >= 0) { ph->VisualLength = n; } else { switch(data_type) { case DATA_T_INTEGER: ph->VisualLength = 13; break; case DATA_T_STRING: ph->VisualLength = 32; break; case DATA_T_DATETIME: ph->VisualLength = 20; break; case DATA_T_MONEY: ph->VisualLength = 16; break; case DATA_T_DOUBLE: ph->VisualLength = 18; break; default: ph->VisualLength = 16; break; } } if (stAttrValue(stLookup(inf,"height"),&n,NULL,0) >= 0) ph->VisualLength2 = n; else ph->VisualLength2 = 1; /** Check for read-only bits in a bitmask **/ ph->BitmaskRO = 0; cnt = 0; while(stAttrValue(stLookup(inf,"readonlybits"), &n, NULL,cnt) >= 0) { ph->BitmaskRO |= (1<<n); cnt++; } /** Check for style information. **/ cnt = 0; ph->Style = 0; while(stAttrValue(stLookup(inf,"style"),NULL,&ptr,cnt) >= 0) { hnt_internal_SetStyleItem(ph, ptr); } /** Check for group ID and Name **/ ph->GroupID = -1; ph->GroupName = NULL; if (stAttrValue(stLookup(inf,"groupid"),&n,NULL,0) >= 0) ph->GroupID = n; if (stAttrValue(stLookup(inf,"groupname"),NULL,&ptr,0) >= 0) { ph->GroupName = nmSysStrdup(ptr); } /** Description of field? **/ if (stAttrValue(stLookup(inf,"description"),NULL,&ptr,0) >= 0) { ph->FriendlyName = nmSysStrdup(ptr); } return ph; }
static void sfe_ui_TreeSelectionChanged( GtkWidget *tree ) { GList *itemlist; gchar *name; GtkBox *hbox; GtkLabel *label; GtkWidget *item; pStructInf infptr, subinf; gchar* annotation; int i; gchar* rowtext[2]; gchar intbuf[32]; char* strval; int intval; /** Get the hidden label which contains the pointer to the inf **/ if (!tree) return; itemlist = GTK_TREE_SELECTION(tree); if (!itemlist) return; item = GTK_WIDGET (itemlist->data); if (!item) return; hbox = GTK_BOX (GTK_BIN (item)->child); label = GTK_LABEL (((GtkBoxChild*)(hbox->children->next->next->data))->widget); gtk_label_get (label, &name); infptr = (pStructInf)(strtol(name, NULL, 16)); if (!infptr) return; /** Show the info on the right side of the window **/ gtk_entry_set_text(GTK_ENTRY(SFE_Globals.NameEdit), infptr->Name); gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(SFE_Globals.TypeCombo)->entry), infptr->UsrType); gtk_text_set_point(GTK_TEXT(SFE_Globals.AnnotText), 0); gtk_text_forward_delete(GTK_TEXT(SFE_Globals.AnnotText), gtk_text_get_length(GTK_TEXT(SFE_Globals.AnnotText))); annotation=""; stAttrValue(stLookup(infptr,"annotation"), NULL, &annotation, 0); gtk_text_insert(GTK_TEXT(SFE_Globals.AnnotText), NULL, NULL, NULL, annotation, strlen(annotation)); /** Build the attributes listing **/ gtk_clist_clear(GTK_CLIST(SFE_Globals.AttrsCList)); for(i=0;i<infptr->nSubInf;i++) { subinf = infptr->SubInf[i]; if (stStructType(subinf) == ST_T_ATTRIB) { strval = NULL; stAttrValue(subinf, &intval, &strval, 0); rowtext[0] = subinf->Name; if (strval) { rowtext[1] = strval; } else { snprintf(intbuf, 32, "%d", intval); rowtext[1] = intbuf; } gtk_clist_append(GTK_CLIST(SFE_Globals.AttrsCList), rowtext); } } return; }
/*** qy_internal_ProcessPath - handles the lookup of the snNode from the given *** path in the querytree, and the optional creation of a new entity, as needed, *** manipulating the WHERE sql in the snNode to assign parent foreign key links *** and so forth. ***/ pQyData qy_internal_ProcessPath(pObjSession s, pPathname path, pSnNode node, int subref, pStructInf dptr, int create, int no_open) { pQyData inf; pStructInf lookup_inf, find_inf, next_inf; char* ptr; char* strval; char* exprval; int i,v; pExpression expr; pParamObjects objlist; pObject test_obj; XHashTable struct_table; /** Setup the pathname into its subparts **/ for(i=1;i<path->nElements;i++) path->Elements[i][-1] = 0; /** Allocate the data info first **/ inf = (pQyData)nmMalloc(sizeof(QyData)); if (!inf) return NULL; memset(inf,0,sizeof(QyData)); inf->BaseNode = node; inf->LLObj = NULL; /** Create the object parameter list... **/ objlist = expCreateParamList(); /** Initialize the listing of query tree elements **/ xhInit(&struct_table, 17, 0); /** Look for the part of the structinf which this path references. **/ while(subref < path->nElements) { /** Add a slot to the param object list for this tree level **/ objlist->ParentID = objlist->CurrentID; expAddParamToList(objlist,"",NULL,EXPR_O_CURRENT); /** Look for text and source items in the querytree definition. **/ next_inf = NULL; for(i=0;i<dptr->nSubInf;i++) { find_inf = dptr->SubInf[i]; if (find_inf->Type == ST_T_SUBGROUP) { PROCESS_SUBGROUP: inf->Pathname[0] = '\0'; if (lookup_inf = stLookup(find_inf, "text")) { strval = ""; stAttrValue(lookup_inf,NULL,&strval,0); if (!strcmp(path->Elements[subref],strval)) { next_inf = find_inf; break; } if (subref == path->nElements - 1) inf->LLObj = NULL; } else if (lookup_inf = stLookup(find_inf, "source")) { strval = ""; stAttrValue(lookup_inf,NULL,&strval,0); expr = NULL; exprval = NULL; stAttrValue(stLookup(find_inf, "where"),NULL,&exprval,0); if (exprval) { objlist->Names[objlist->CurrentID] = find_inf->Name; expr = (pExpression)expCompileExpression(exprval, objlist, MLX_F_ICASE | MLX_F_FILENAMES, 0); } sprintf(inf->Pathname,"%s/%s",strval,path->Elements[subref]); /** Setup this querytree struct entry for lookups **/ xhAdd(&struct_table, find_inf->Name, (void*)find_inf); /** Not opening any objects? Skip open attempt if so. **/ if (no_open) { next_inf = find_inf; break; } /** Open the object, or create if need be. If create, convert any WHERE to setattrs **/ test_obj = objOpen(s, inf->Pathname, O_RDONLY, 0600, "system/file"); if (test_obj) { expModifyParam(objlist, NULL, test_obj); } if (!test_obj && subref == path->nElements - 1 && create) { test_obj = objOpen(s, inf->Pathname, O_RDWR | O_CREAT | O_TRUNC, 0600, "system/file"); if (!test_obj) break; expModifyParam(objlist, NULL, test_obj); objlist->Flags[objlist->CurrentID] |= EXPR_O_UPDATE; if (expr) { /** Reverse eval the expression to set the object attributes **/ expr->Integer = 1; v = expReverseEvalTree(expr, objlist); expFreeExpression(expr); expr = NULL; if (v < 0) { objClose(test_obj); break; } } } else if (!test_obj) break; /** Validate the where clause expression if need be. **/ objlist->Session = s; v = !expr || (expEvalTree(expr,objlist) != -1 && expr->Integer != 0); if (expr) expFreeExpression(expr); expr = NULL; if (subref == path->nElements - 1) { inf->LLObj = test_obj; } else { if (!v) objClose(test_obj); } if (v) { next_inf = find_inf; break; } } } else if (!strcmp(find_inf->Name,"recurse")) { stGetAttrValue(find_inf, DATA_T_STRING, POD(&ptr), 0); find_inf = (pStructInf)xhLookup(&struct_table, ptr); if (find_inf) goto PROCESS_SUBGROUP; } } /** Didn't find? **/ if (!next_inf) { /** Ok, close up the structure table. **/ xhDeInit(&struct_table); nmFree(inf,sizeof(QyData)); inf->LLObj = NULL; /** Close the objects and free the param list. **/ for(i=0;i<objlist->nObjects-1;i++) objClose(objlist->Objects[i]); expFreeParamList(objlist); mssError(0,"QY","Could not find object via access through querytree"); return NULL; } dptr = next_inf; subref++; } inf->NodeData = dptr; xhDeInit(&struct_table); for(i=0;i<objlist->nObjects-1;i++) objClose(objlist->Objects[i]); return inf; }