Blame | Last modification | View Log | RSS feed
/** MS-DOS SHELL - Function Processing** MS-DOS SHELL - Copyright (c) 1990,4 Data Logic Limited** This code is subject to the following copyright restrictions:** 1. Redistribution and use in source and binary forms are permitted* provided that the above copyright notice is duplicated in the* source form and the copyright notice in file sh6.c is displayed* on entry to the program.** 2. The sources (or parts thereof) or objects generated from the sources* (or parts of sources) cannot be sold under any circumstances.** Note: 1. The PrintProcessTree code is based on code written by Kai Uwe* Rommel** 2. When parts of the original 2.1 shell were replaced by the Lexical* Analsyer written by Simon J. Gerraty (for his Public Domain Korn* Shell, which is also based on Charles Forsyth original idea), a* number of changes were made to reflect the changes Simon made to* the Parse output tree. Some parts of this code in this module* are based on the algorithms/ideas that he incorporated into his* shell, in particular the Function Processing functions.** $Header: /cvsroot/device/DEVL/UTILS/SH/SH10.C,v 1.1 2002/08/02 06:49:32 adamy Exp $** $Log: SH10.C,v $* Revision 1.1 2002/08/02 06:49:32 adamy* imported (reference only)** Revision 1.1 2001/07/20 05:55:42 ayoung* WIN32 support** Revision 1.1.1.1 1999/12/02 01:11:12 gordonh* UTIL** Revision 2.15 1994/08/25 20:49:11 istewart* MS Shell 2.3 Release** Revision 2.14 1994/02/23 09:23:38 istewart* Beta 233 updates** Revision 2.13 1994/02/01 10:25:20 istewart* Release 2.3 Beta 2, including first NT port** Revision 2.12 1994/01/11 17:55:25 istewart* Release 2.3 Beta 0 patches** Revision 2.11 1993/12/01 11:58:34 istewart* Release 226 beta** Revision 2.10 1993/08/25 16:03:57 istewart* Beta 225 - see Notes file** Revision 2.9 1993/07/02 10:21:35 istewart* 224 Beta fixes** Revision 2.8 1993/06/14 11:01:44 istewart* More changes for 223 beta** Revision 2.7 1993/06/02 09:52:35 istewart* Beta 223 Updates - see Notes file** Revision 2.6 1993/02/16 16:03:15 istewart* Beta 2.22 Release** Revision 2.5 1993/01/26 18:35:09 istewart* Release 2.2 beta 0** Revision 2.4 1992/12/14 10:54:56 istewart* BETA 215 Fixes and 2.1 Release** Revision 2.3 1992/11/06 10:03:44 istewart* 214 Beta test updates** Revision 2.2 1992/07/16 14:33:34 istewart* Beta 212 Baseline** Revision 2.1 1992/07/10 10:52:48 istewart* 211 Beta updates** Revision 2.0 1992/04/13 17:39:09 Ian_Stewartson* MS-Shell 2.0 Baseline release**/#include <sys/types.h>#include <sys/stat.h>#include <stdio.h>#include <signal.h>#include <errno.h>#include <setjmp.h>#include <ctype.h>#include <string.h>#include <unistd.h>#include <stdlib.h>#include <fcntl.h>#include <limits.h>#include <dirent.h>#include "sh.h"#if (OS_TYPE == OS_UNIX)# include <sys/times.h>#endif/* Function declarations */static void F_LOCAL PrintCommand (C_Op *, int);static void F_LOCAL PrintIOInformation (IO_Actions *);static void F_LOCAL PrintCaseCommand (C_Op *);static void F_LOCAL PrintIndentedString (char *, int, int);static void F_LOCAL PrintVarArg (unsigned char *);static void F_LOCAL fputMagicChar (unsigned int);static void F_LOCAL PrintMode (int);static void F_LOCAL SaveReleaseExecuteTree (C_Op *, void (*)(void *));static void F_LOCAL SaveReleaseWordList (char **, void (*)(void *));static void F_LOCAL SaveReleaseIOActions (IO_Actions **, void (*)(void *));static void SaveTreeEntry (void *);static C_Op * F_LOCAL DuplicateFunctionTree (C_Op *);static char ** F_LOCAL DuplicateWordList (char **list);static IO_Actions ** F_LOCAL DuplicateIOActions (IO_Actions **);static int FindFunction (const void *, const void *);static int SearchFunction (const void *, const void *);static void DisplayFunction (const void *, VISIT, int);static void DeleteAFunction (const void *, VISIT, int);static int FindAlias (const void *, const void *);static int SearchAlias (const void *, const void *);static void UntrackAlias (const void *, VISIT, int);static void DisplayAlias (const void *, VISIT, int);#if (OS_TYPE != OS_DOS)static void DisplayJob (const void *, VISIT, int);static void CountJob (const void *, VISIT, int);static int SearchJob (const void *, const void *);static int FindJob (const void *, const void *);static void FindJobByString (const void *, VISIT, int);static int FindJobByPID (const void *, const void *);static int FindJobBySession (const void *, const void *);#endif#if (OS_TYPE == OS_OS2)# if (OS_SIZE == OS_32)# if !defined (__EMX__)# define Dos32GetPrty DosGetPrty# define Dos32QProcStatus DosQProcStatus# pragma linkage (DosQProcStatus, far16 pascal)# pragma linkage (DosGetPrty, far16 pascal)# elseUSHORT _THUNK_FUNCTION (Dos16GetPrty) ();USHORT _THUNK_FUNCTION (Dos16QProcStatus) ();# endifextern USHORT Dos32QProcStatus (PVOID, USHORT);extern USHORT Dos32GetPrty (USHORT, PUSHORT, USHORT);# else# define Dos32QProcStatus DosQProcStatus# define Dos32GetPrty DosGetPrtyextern USHORT APIENTRY Dos32QProcStatus (PVOID, USHORT);# endif#endif/** OS/2 Process Information structures*** Declare OS2 1.x 16-bit version structures*/#if (OS_TYPE == OS_OS2) && (OS_SIZE == OS_16)typedef struct process{USHORT pid;USHORT ppid;USHORT threads;USHORT children;USHORT modhandle;USHORT module;} V1Process_t;typedef struct module{USHORT modhandle;USHORT max_dependents;USHORT *dependents;UCHAR *modname;} V1Module_t;typedef struct ProcessInfo{V1Process_t **V1Processes;V1Module_t **V1Modules;USHORT M_Processes;USHORT N_Processes;USHORT M_Modules;USHORT N_Modules;} V1ProcessStatus_t;#endif/** OS2 2.0 - 32 Bit version structures*/#if (OS_TYPE == OS_OS2)# if (OS_SIZE == OS_32)# define PTR(ptr) (ptr)# else# define PTR(ptr) ((void *)((((ULONG)ps) & 0xFFFF0000L) | \(((ULONG)(ptr)) & 0x0000FFFFL) ))# endif# define PROCESS_END_INDICATOR 3/* Process Status structures */# if (OS_SIZE == OS_32)# pragma pack(1)# endif/** Thread Info*/typedef struct thread2{ULONG ulRecType; /* Record type (thread = 100) */USHORT tidWithinProcess; /* TID within process (TID is *//* 4 bytes!!) */USHORT usSlot; /* Unique thread slot number */ULONG ulBlockId; /* Sleep id thread is sleeping on*/ULONG ulPriority; /* Priority */ULONG ulSysTime; /* Thread System Time */ULONG ulUserTime; /* Thread User Time */UCHAR uchState; /* 1=ready,2=blocked,5=running */UCHAR uchPad; /* Filler */USHORT usPad; /* Filler */} V2Thread_t;/** Process Information*/typedef struct process2{ULONG ulEndIndicator; /* 1 means not end, 3 means *//* last entry */V2Thread_t *ptiFirst; /* Address of the 1st Thread *//* Control Blk */USHORT pid; /* Process ID (2 bytes - PID *//* is 4 bytes) */USHORT pidParent; /* Parent's process ID */ULONG ulType; /* Process Type */ULONG ulStatus; /* Process Status */ULONG idSession; /* Session ID */USHORT hModRef; /* Module handle of EXE */USHORT usThreadCount; /* Number of threads in this *//* process */ULONG ulSessionType; /* Session Type */PVOID pvReserved; /* Unknown */USHORT usSem16Count; /* Number of 16-bit system *//* semaphores */USHORT usDllCount; /* Number of Dlls used by *//* process */USHORT usShrMemHandles; /* Number of shared memory *//* handles */USHORT usReserved; /* Unknown */PUSHORT pusSem16TableAddr; /* Address of a 16-bit semaphore*//* table */PUSHORT pusDllTableAddr; /* Address of a Dll table */PUSHORT pusShrMemTableAddr; /* Address of a shared memory *//* table */} V2Process_t;/** Process Status header*/typedef struct processstatus2{PVOID psumm; /* SUMMARY section ptr */V2Process_t *ppi; /* PROCESS section ptr */PVOID psi; /* SEM section ptr (add 16 to offset) */PVOID pDontKnow1; /* */PVOID psmi; /* SHARED MEMORY section ptr */PVOID pmi; /* MODULE section ptr */PVOID pDontKnow2; /* */PVOID pDontKnow3; /* */} V2ProcessStatus_t;# if (OS_SIZE == OS_32)# pragma pack()# endif#endif/** Associated functions*/#if (OS_TYPE == OS_OS2) && (OS_SIZE == OS_16)static int SortV1Processes (void *, void *);static void F_LOCAL PrintV1ProcessTree (pid_t, int,V1ProcessStatus_t *);static bool F_LOCAL Parse_V1ProcessTable (UCHAR *,V1ProcessStatus_t *);#endif#if (OS_TYPE == OS_OS2)static void F_LOCAL V2_DisplayProcessTree (USHORT, USHORT,V2ProcessStatus_t *);static V2ProcessStatus_t * F_LOCAL GetProcessStatus (char *);#endif#if (OS_TYPE != OS_DOS)static char *JobSearchKey; /* Job search string */static int NumberOfJobs = 0; /* Number of Jobs */static JobList **JobSearchEntry; /* Matching entry */#endifstatic bool DisplayListMode = FALSE;/* Mode for Display Job/Alias */static int Print_indent; /* Current indent level *//* IO types */static char *IOTypes [] = { "<", ">", "<>", "<<", ">>", ">&" };/** Duplicate a memory area*/#define DuplicateMemoryArea(area, type) \(type)((area == (void *)NULL) \? (void *)NULL \: DuplicateMemoryCell (area))/** Print ALL functions*/int PrintAllFunctions (void){twalk (FunctionTree, DisplayFunction);return 0;}/** TWALK function to display the JOB, FUNCTION and ALIAS trees*/#if (OS_TYPE != OS_DOS)static void CountJob (const void *key, VISIT visit, int level){if ((visit == postorder) || (visit == leaf))NumberOfJobs++;}static void DisplayJob (const void *key, VISIT visit, int level){if ((visit == postorder) || (visit == leaf)){printf ("[%d] %c", (*(JobList **)key)->Number,((*(JobList **)key)->Number == CurrentJob)? CHAR_PLUS: (((*(JobList **)key)->Number == PreviousJob)? CHAR_HYPHEN : CHAR_SPACE));if (DisplayListMode)printf (" %d", (*(JobList **)key)->pid);fputchar (CHAR_TAB);FlushStreams ();DisplayLineWithControl ((*(JobList **)key)->Command);fputchar (CHAR_NEW_LINE);}}#endifstatic void DisplayFunction (const void *key, VISIT visit, int level){if ((visit == postorder) || (visit == leaf))PrintFunction ((*(FunctionList **)key)->tree, PF_MODE_NORMAL);}static void DisplayAlias (const void *key, VISIT visit, int level){if (((visit == postorder) || (visit == leaf)) &&(!DisplayListMode || (*(AliasList **)key)->AFlags & ALIAS_TRACKED))PrintAlias ((*(AliasList **)key)->name);}/** DISPLAY A FUNCTION TREE*//** print the execute tree - used for displaying functions*/void PrintFunction (register C_Op *t, int mode){char **wp;if (t == (C_Op *)NULL)return;/* Check for start of print */if (t->type == TFUNC){Print_indent = 0;printf (LIT_2Strings, t->str, "()");PrintFunction (t->left, PF_MODE_NORMAL);FlushStreams ();return;}/* Otherwise, process the tree and print it */switch (t->type){case TASYNC: /* Asyn commands */PrintFunction (t->left, PF_MODE_ASYNC);return;case TCOPROCESS: /* Co-process */PrintFunction (t->left, PF_MODE_COPROC);return;case TPAREN: /* () */case TCOM: /* A command process */PrintCommand (t, mode);return;case TPIPE: /* Pipe processing */PrintFunction (t->left, PF_MODE_NORMAL);PrintIndentedString ("|\n", 0, PF_MODE_NORMAL);PrintFunction (t->right, mode);return;case TLIST: /* Entries in a for statement */PrintFunction (t->left, PF_MODE_NORMAL);PrintFunction (t->right, mode);return;case TOR: /* || and && */case TAND:PrintFunction (t->left, PF_MODE_NORMAL);if (t->right != (C_Op *)NULL){PrintIndentedString ((t->type == TAND) ? "&&\n" : "||\n",0, PF_MODE_NORMAL);PrintFunction (t->right, mode);}return;case TFOR: /* First part of a for statement*/case TSELECT:PrintIndentedString ((t->type == TFOR) ? "for " : "select ",0, PF_MODE_NORMAL);foputs (t->str);if ((wp = t->vars) != NOWORDS){foputs (" in");while (*wp != NOWORD){fputchar (CHAR_SPACE);PrintVarArg ((unsigned char *)*(wp++));}}fputchar (CHAR_NEW_LINE);PrintIndentedString ("do\n", 1, PF_MODE_NORMAL);PrintFunction (t->left, PF_MODE_NORMAL);PrintIndentedString (LIT_done, -1, mode);return;case TWHILE: /* WHILE and UNTIL functions */case TUNTIL:PrintIndentedString ((t->type == TWHILE) ? "while\n" : "until\n",1, PF_MODE_NORMAL);PrintFunction (t->left, PF_MODE_NORMAL);Print_indent--;PrintIndentedString ("do\n", 1, PF_MODE_NORMAL);PrintFunction (t->right, PF_MODE_NORMAL);PrintIndentedString (LIT_done, -1, mode);return;case TIF: /* IF and ELSE IF functions */case TELIF:if (t->type == TIF)PrintIndentedString ("if\n", 1, PF_MODE_NORMAL);elsePrintIndentedString ("elif\n", 1, PF_MODE_NORMAL);PrintFunction (t->left, PF_MODE_NORMAL);if (t->right != (C_Op *)NULL){Print_indent -= 1;PrintIndentedString ("then\n", 1, PF_MODE_NORMAL);PrintFunction (t->right->left, PF_MODE_NORMAL);if (t->right->right != (C_Op *)NULL){Print_indent -= 1;if (t->right->right->type != TELIF)PrintIndentedString ("else\n", 1, PF_MODE_NORMAL);PrintFunction (t->right->right, PF_MODE_NORMAL);}}if (t->type == TIF)PrintIndentedString ("fi", -1, mode);return;case TCASE: /* CASE function */PrintIndentedString ("case ", 1, PF_MODE_NORMAL);PrintVarArg ((unsigned char *)t->str);puts (" in");PrintCaseCommand (t->left);PrintIndentedString ("esac", -1, mode);return;case TBRACE: /* {} statement */PrintIndentedString ("{\n", 1, PF_MODE_NORMAL);if (t->left != (C_Op *)NULL)PrintFunction (t->left, mode);PrintIndentedString ("}", -1, PF_MODE_NORMAL);return;case TTIME:PrintIndentedString ("time\n", 1, PF_MODE_NORMAL);PrintFunction (t->left, mode);Print_indent--;return;}}/** Print a command line*/static void F_LOCAL PrintCommand (register C_Op *t, int mode){IO_Actions **iopp;char **wp;int i;/* Parenthesis ? */if (t->type == TPAREN){PrintIndentedString ("(\n", 1, PF_MODE_NORMAL);PrintFunction (t->left, PF_MODE_NORMAL);PrintIndentedString (")", -1, PF_MODE_NO);}else{PrintIndentedString (null, 0, PF_MODE_NORMAL);/* Process arguments and assigments */for (i = 0, wp = t->vars; i < 2; i++){if (wp != NOWORDS){while (*wp != NOWORD){PrintVarArg ((unsigned char *)*(wp++));if (*wp != NOWORD)fputchar (CHAR_SPACE);}}wp = t->args;}}/* Set up anyother IO required */if ((iopp = t->ioact) != (IO_Actions **)NULL){while (*iopp != (IO_Actions *)NULL)PrintIOInformation (*(iopp++));}PrintMode (mode);}/** Print an argument or variable assigment string*/static void F_LOCAL PrintVarArg (unsigned char *string){register unsigned c;register bool quoted = FALSE;while (1){switch ((c = *(string++))){case WORD_EOS: /* end of string */return;case WORD_CHAR: /* unquoted character */fputMagicChar (*(string++));break;case WORD_QCHAR: /* quoted character */case WORD_QTCHAR:if (!quoted)fputchar (CHAR_META);fputMagicChar (*(string++));break;case WORD_OQUOTE: /* opening " or ' */case WORD_ODQUOTE:quoted = TRUE;fputchar ((c == WORD_OQUOTE) ? CHAR_SINGLE_QUOTE: CHAR_DOUBLE_QUOTE);break;case WORD_CQUOTE: /* closing " or ' */case WORD_CDQUOTE:quoted = FALSE;fputchar ((c == WORD_CQUOTE) ? CHAR_SINGLE_QUOTE: CHAR_DOUBLE_QUOTE);break;case WORD_OARRAY: /* Opening ${...[...] ... */fputchar (CHAR_OPEN_BRACKETS);break;case WORD_CARRAY: /* Closing ${...[...] ... */case WORD_OSUBST: /* opening ${ substitution */if (c == WORD_CARRAY)fputchar (CHAR_CLOSE_BRACKETS);/* Start of variable - output the name */else{fputchar (CHAR_VARIABLE);fputchar (CHAR_OPEN_BRACES);while ((c = *(string++)) != 0)fputchar (c);}/* Check for some special characters */if ((*string != WORD_CSUBST) && (*string != WORD_OARRAY)){if (((c = *(string++)) & CHAR_MAGIC) &&(IS_VarOp (c & 0x7f))){/* Check for %% or ## */if (((c &= 0x7f) == CHAR_MATCH_START) ||(c == CHAR_MATCH_END))fputMagicChar (c);/* :?string case */elsefputMagicChar (':');}fputMagicChar (c);}break;case WORD_CSUBST: /* closing } of above */fputchar (CHAR_CLOSE_BRACES);break;case WORD_COMSUB: /* $() substitution (0 terminated) */case WORD_OMATHS: /* opening $(()) substitution (0 term) */fputchar (CHAR_VARIABLE);fputchar (CHAR_OPEN_PARATHENSIS);if (c == WORD_OMATHS)fputchar (CHAR_OPEN_PARATHENSIS);while (*string != 0)fputMagicChar (*(string++));string++; /* Skip over the terminator */fputchar (CHAR_CLOSE_PARATHENSIS);if (c == WORD_OMATHS)fputchar (CHAR_CLOSE_PARATHENSIS);break;}}}/** Output a potentially magic character*/static void F_LOCAL fputMagicChar (unsigned int c){if ((c & 0x60) == 0){fputchar ((c & CHAR_MAGIC) ? CHAR_VARIABLE : '^');fputchar (((c & 0x7F) | 0x40));}else if ((c&0x7F) == 0x7F){fputchar ((c & CHAR_MAGIC) ? CHAR_VARIABLE : '^');fputchar ('?');}elsefputchar (c);}/** Print the IO re-direction*/static void F_LOCAL PrintIOInformation (register IO_Actions *iop){int unit = iop->io_unit;int IOflag = iop->io_flag & IOTYPE;char *type;bool TermQuote = FALSE;/* Set up the IO type string and display it */type = IOTypes [IOflag - 1];if ((IOflag == IODUP) && (!unit))type = "<&";printf (" %d%s", unit, type);/* Print clobber override and skip tabs information on here documents */if (iop->io_flag & IOCLOBBER)fputchar (CHAR_PIPE);if (iop->io_flag & IOSKIP)fputchar (CHAR_HYPHEN);/* Quoted here document ? */if ((TermQuote = C2bool ((IOflag == IOHERE) && (!(iop->io_flag & IOEVAL)))))fputchar (CHAR_SINGLE_QUOTE);/* Here document names are in expanded format */(IOflag == IOHERE) ? (void)foputs (iop->io_name): (void)PrintVarArg ((unsigned char *)iop->io_name);if (TermQuote)fputchar (CHAR_SINGLE_QUOTE);}/** Print out the contents of a case statement*/static void F_LOCAL PrintCaseCommand (C_Op *t){register char **wp;while (t != (C_Op *)NULL){/* Print patterns (the conditions) */PrintIndentedString (null, 0, PF_MODE_NORMAL);for (wp = t->vars; *wp != NOWORD; ){PrintVarArg ((unsigned char *)*(wp++));if (*wp != NOWORD)foputs (" | ");}puts (" )");Print_indent += 1;/* print the functions */PrintFunction (t->left, PF_MODE_NORMAL);PrintIndentedString (";;", -1, PF_MODE_NORMAL);t = t->right;}}/** Print an indented string*/static void F_LOCAL PrintIndentedString (char *cp, int indent, int mode){int i;if (indent < 0)Print_indent += indent;for (i = 0; i < (Print_indent / 2); i++)fputchar (CHAR_TAB);if (Print_indent % 2)foputs (" ");foputs (cp);/* Append the mode */if ((mode != PF_MODE_NORMAL) || (indent < 0))PrintMode (mode);if (indent > 0)Print_indent += indent;}/** Output mode*/static void F_LOCAL PrintMode (int mode){if (mode == PF_MODE_ASYNC)foputs (" &\n");else if (mode == PF_MODE_COPROC)foputs (" |&\n");else if (mode == PF_MODE_NORMAL)fputchar (CHAR_NEW_LINE);}/** TWALK and TDELETE compare functions for FUNCTION, ALIAS and JOB trees** Note: We know about these two function, so we know the key is always* the first parameter. So we only pass the char * not the FunctionList* pointer (in the case of JOB, its an int *)*/static int FindFunction (const void *key1, const void *key2){return strcmp (key1, ((FunctionList *)key2)->tree->str);}static int FindAlias (const void *key1, const void *key2){return strcmp (key1, ((AliasList *)key2)->name);}/* By string name */#if (OS_TYPE != OS_DOS)static void FindJobByString (const void *key, VISIT visit, int level){if (JobSearchEntry != (JobList **)NULL)return;if (((visit == postorder) || (visit == leaf)) &&(((*JobSearchKey == CHAR_MATCH_ANY) &&(strstr (((JobList *)key)->Command, JobSearchKey) != (char *)NULL)) ||((*JobSearchKey != CHAR_MATCH_ANY) &&(strncmp (JobSearchKey, ((JobList *)key)->Command,strlen (JobSearchKey)) == 0))))JobSearchEntry = (JobList **)&key;}/* By process id */static int FindJobByPID (const void *key1, const void *key2){return *(PID *)key1 - ((JobList *)key2)->pid;}/* By session id */static int FindJobBySession (const void *key1, const void *key2){return *(unsigned short *)key1 - ((JobList *)key2)->SessionId;}/* By job number */static int FindJob (const void *key1, const void *key2){return *(int *)key1 - ((JobList *)key2)->Number;}#endif/** Look up a function in the save tree*/FunctionList *LookUpFunction (char *name, bool AllowDot){FunctionList **fp = (FunctionList **)NULL;if (AllowDot || (*name != '.'))fp = (FunctionList **)tfind (name, &FunctionTree, FindFunction);return fp != (FunctionList **)NULL ? *fp : (FunctionList *)NULL;}/** TSEARCH compare functions for FUNCTION, ALIAS and JOB trees*/static int SearchFunction (const void *key1, const void *key2){return strcmp (((FunctionList *)key1)->tree->str,((FunctionList *)key2)->tree->str);}static int SearchAlias (const void *key1, const void *key2){return strcmp (((AliasList *)key1)->name, ((AliasList *)key2)->name);}#if (OS_TYPE != OS_DOS)static int SearchJob (const void *key1, const void *key2){return ((JobList *)key1)->Number - ((JobList *)key2)->Number;}#endif/** SAVE/DELETE A FUNCTION*//** Save a function tree*/bool SaveFunction (C_Op *t){char *name = t->str;register FunctionList *fp;void (_SIGDECL *save_signal)(int);char *sname = name;/* Allow dot as the first character */if ((*name == '.') && (strlen (name) > (size_t)1))sname++;if (!IsValidAliasName (sname, FALSE)){PrintWarningMessage (BasicErrorMessage, name, LIT_Invalidfunction);return FALSE;}/* Create new entry */if ((fp = (FunctionList *)GetAllocatedSpace (sizeof (FunctionList)))== (FunctionList *)NULL)return FALSE;/* Delete the old function if it exists */DeleteFunction (t);/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);fp->tree = t;fp->Traced = FALSE;/* Set up the tree */if (tsearch (fp, &FunctionTree, SearchFunction) != (void *)NULL){SetMemoryAreaNumber ((void *)fp, 0);SaveReleaseExecuteTree (t, SaveTreeEntry);}/* Restore signals */signal (SIGINT, save_signal);return TRUE;}/** Clean up functions on exit. We should just delete the files, but its* easier to delete the functions*/void DeleteAllFunctions (void){void (_SIGDECL *save_signal)(int);save_signal = signal (SIGINT, SIG_IGN);twalk (FunctionTree, DeleteAFunction);signal (SIGINT, save_signal);}/** Associate TREE WALK function to delete all functions*/static void DeleteAFunction (const void *key, VISIT visit, int level){if ((visit == postorder) || (visit == leaf))SaveReleaseExecuteTree ((*(FunctionList **)key)->tree,ReleaseMemoryCell);}/** Delete a function tree*/void DeleteFunction (C_Op *t){char *name = t->str;register FunctionList *fp = LookUpFunction (name, TRUE);void (_SIGDECL *save_signal)(int);if (fp == (FunctionList *)NULL)return;/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);/* Free the tree and delete the entry */tdelete (name, &FunctionTree, FindFunction);SaveReleaseExecuteTree (fp->tree, ReleaseMemoryCell);ReleaseMemoryCell ((void *)fp);/* Restore signals */signal (SIGINT, save_signal);}/** Set ExTree areas to zero function*/static void SaveTreeEntry (void *s){SetMemoryAreaNumber (s, 0);}/** Set/Free function tree area by recursively processing of tree*/static void F_LOCAL SaveReleaseExecuteTree (C_Op *t, void (* func)(void *)){if (t == (C_Op *)NULL)return;/** Process the tree - saving or deleting*/if (t->str != (char *)NULL)(*func)((void *)t->str);SaveReleaseWordList (t->vars, func);SaveReleaseWordList (t->args, func);SaveReleaseIOActions (t->ioact, func);SaveReleaseExecuteTree (t->left, func);SaveReleaseExecuteTree (t->right, func);(*func)((void *)t);}/** Save/Release a Block of words*/static void F_LOCAL SaveReleaseWordList (char **list, void (* func)(void *)){char **Slist = list;if (list == NOWORDS)return;/* Ok - save/release it */while (*list != NOWORD)(*func)((void *)*(list++));/* Handle the block itself */(*func)((void *)Slist);}/** Save/Release the IO Actions block*/static void F_LOCAL SaveReleaseIOActions (IO_Actions **list, void (* func)(void *)){IO_Actions **Slist = list;if (list == (IO_Actions **)NULL)return;/* Ok - save/release it */while (*list != (IO_Actions *)NULL){/** If this is a Here Document, we need some clever processing to stop it* beening deleted or to delete it when the function disappears*/if (((*list)->io_flag & IOTYPE) == IOHERE){/** Mark this is a function file name. This should stop the here processing* from deleting it*/(*list)->io_flag |= IOFUNCTION;/* If this is a delete - delete the file name */if (func == ReleaseMemoryCell)unlink ((*list)->io_name);}/* OK, normal processing now!! */(*func)((void *)(*list)->io_name);(*func)((void *)*(list++));}/* Handle the block itself */(*func)((void *)Slist);}/** FUNCTION TREE DUPLICATION*//** Copy function tree area by recursively processing of tree*/static C_Op * F_LOCAL DuplicateFunctionTree (C_Op *Old_t){C_Op *New_t;if (Old_t == (C_Op *)NULL)return (C_Op *)NULL;/** This will copy function and for identifiers quite accidently*/New_t = (C_Op *)DuplicateMemoryCell (Old_t);New_t->str = DuplicateMemoryArea (Old_t->str, char *);New_t->vars = DuplicateWordList (Old_t->vars);New_t->args = DuplicateWordList (Old_t->args);New_t->ioact = DuplicateIOActions (Old_t->ioact);New_t->left = DuplicateFunctionTree (Old_t->left);New_t->right = DuplicateFunctionTree (Old_t->right);return New_t;}/** Duplicate a Block of words*/static char ** F_LOCAL DuplicateWordList (char **list){char **Nlist;char **Np;if ((Nlist = DuplicateMemoryArea (list, char **)) == (char **)NULL)return NOWORDS;/* Ok - dup it */for (Np = Nlist; *list != NOWORD; list++)*(Np++) = DuplicateMemoryArea (*list, char *);/* Terminate it */*Np = NOWORD;return Nlist;}/** Duplicate the IO Actions block*/static IO_Actions ** F_LOCAL DuplicateIOActions (IO_Actions **list){IO_Actions **Nlist;IO_Actions **Np;if ((Nlist = DuplicateMemoryArea (list,IO_Actions **)) == (IO_Actions **)NULL)return (IO_Actions **)NULL;/* Ok - dup it */for (Np = Nlist; *list != (IO_Actions *)NULL; list++, Np++){*Np = (IO_Actions *)DuplicateMemoryCell (*list);(*Np)->io_name = DuplicateMemoryArea ((*list)->io_name, char *);}/* Terminate it */*Np = (IO_Actions *)NULL;return Nlist;}/** Duplicate the tree*/C_Op *CopyFunction (C_Op *Old_t){ErrorPoint save_ErrorReturnPoint;jmp_buf new_ErrorReturnPoint;C_Op *New_t = (C_Op *)NULL;/* Set up for error handling - like out of space */save_ErrorReturnPoint = e.ErrorReturnPoint;if (SetErrorPoint (new_ErrorReturnPoint) == 0)New_t = DuplicateFunctionTree (Old_t);e.ErrorReturnPoint = save_ErrorReturnPoint;return New_t;}/** Alias processing*/void PrintAlias (char *name){register AliasList *al = LookUpAlias (name, FALSE);if ((al == (AliasList *)NULL) || (al->value == null))return;printf (ListVarFormat, name, al->value);}/** Print All Aliases*/int PrintAllAlias (bool tracked){DisplayListMode = tracked; /* Set mode */twalk (AliasTree, DisplayAlias);return 0;}/** Save an alias*/bool SaveAlias (char *name, char *arguments, bool tracked){register AliasList *al;void (_SIGDECL *save_signal)(int);/* Create new entry */if (((al = (AliasList *)GetAllocatedSpace (sizeof (AliasList)))== (AliasList *)NULL) ||((al->name = GetAllocatedSpace (strlen (name) + 1)) == (char *)NULL))return FALSE;if ((arguments != null) &&((al->value = GetAllocatedSpace (strlen (arguments) + 1))== (char *)NULL))return FALSE;/* Delete old name */DeleteAlias (name);/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);strcpy (al->name, name);/* Add it to the tree */if (tsearch (al, &AliasTree, SearchAlias) != (void *)NULL){SetMemoryAreaNumber ((void *)al, 0);SetMemoryAreaNumber ((void *)al->name, 0);if (arguments != null)SetMemoryAreaNumber ((void *)strcpy (al->value, arguments), 0);elseal->value = null;if (tracked)al->AFlags = ALIAS_TRACKED;}/* Restore signals */signal (SIGINT, save_signal);return TRUE;}/** Delete an alias*/void DeleteAlias (char *name){register AliasList **alp = (AliasList **)tfind (name, &AliasTree,FindAlias);void (_SIGDECL *save_signal)(int);register AliasList *al;if (alp == (AliasList **)NULL)return;/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);/* Delete the tree entry and release the memory */al = *alp;tdelete (name, &AliasTree, FindAlias);ReleaseMemoryCell ((void *)al->name);if (al->value != null)ReleaseMemoryCell ((void *)al->value);ReleaseMemoryCell ((void *)al);/* Restore signals */signal (SIGINT, save_signal);}/** Search for an Alias*/AliasList *LookUpAlias (char *name, bool CreateTracked){AliasList **alp = (AliasList **)tfind (name, &AliasTree, FindAlias);char *path;/* If we found a tracked alias, which has been untracked, re-track it if* necesary*/if ((alp != (AliasList **)NULL) && ((*alp)->value == null)){if (CreateTracked &&((path = AllocateMemoryCell (FFNAME_MAX)) != (char *)NULL) &&(FindLocationOfExecutable (path, name) != EXTENSION_NOT_FOUND)){SetMemoryAreaNumber ((void *)path, 0);(*alp)->value = PATH_TO_UNIX (path);return *alp;}elsereturn (AliasList *)NULL;}return (alp == (AliasList **)NULL) ? (AliasList *)NULL : *alp;}/** Check for valid alias name*/bool IsValidAliasName (char *s, bool alias){if (!IS_VariableFC ((int)*s) || LookUpSymbol (s))return FALSE;while (IS_VariableSC ((int)*s))++s;return C2bool (!*s);}/** Untrack all Aliases*/void UnTrackAllAliases (void){twalk (AliasTree, UntrackAlias);}/** The associate TWALK function*/static void UntrackAlias (const void *key, VISIT visit, int level){AliasList *al = *(AliasList **)key;if (((visit == postorder) || (visit == leaf)) &&(al->AFlags & ALIAS_TRACKED) && (al->value != null)){ReleaseMemoryCell ((void *)al->value);al->value = null;}}/** Look up a job in the save tree*/#if (OS_TYPE != OS_DOS)JobList *LookUpJob (int JobNumber){JobList **jp = (JobList **)tfind (&JobNumber, &JobTree, FindJob);return jp != (JobList **)NULL ? *jp : (JobList *)NULL;}/** Search for a job*/JobList *SearchForJob (char *String){JobSearchKey = String;JobSearchEntry = (JobList **)NULL;if ((strcmp (String, "%") == 0) || (strcmp (String, "+") == 0))return LookUpJob (CurrentJob);else if (strcmp (String, "-") == 0)return LookUpJob (PreviousJob);/* Search for it */twalk (JobTree, FindJobByString);return JobSearchEntry != (JobList **)NULL ? *JobSearchEntry: (JobList *)NULL;}/** Delete a job by Session ID*/void DeleteJobBySession (unsigned short SessionId){register JobList **jpp = (JobList **)tfind (&SessionId, &JobTree,FindJobBySession);if (jpp != (JobList **)NULL)DeleteJob ((*jpp)->pid);}/** Delete a job by Process ID*/void DeleteJob (PID pid){register JobList **jpp = (JobList **)tfind (&pid, &JobTree,FindJobByPID);void (_SIGDECL *save_signal)(int);JobList *jp;if (jpp == (JobList **)NULL)return;/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);jp = *jpp;/* Free the tree and delete the entry */tdelete (&pid, &JobTree, FindJobByPID);if (jp->Number == PreviousJob)PreviousJob = 0;if (jp->Number == CurrentJob)CurrentJob = PreviousJob;ReleaseMemoryCell ((void *)jp->Command);ReleaseMemoryCell ((void *)jp);/* Restore signals */signal (SIGINT, save_signal);}/** Save a job ID*/int AddNewJob (PID pid, unsigned short SessionId, char *command){register JobList *jp;static int JobNumber = 1;void (_SIGDECL *save_signal)(int);char *tmp;/* We if we can get the full command */if ((tmp = GetLastHistoryString ()) != (char *)NULL)command = tmp;/* Create new entry */if (((jp = (JobList *)GetAllocatedSpace (sizeof (JobList))) == (JobList *)NULL) ||((jp->Command = GetAllocatedSpace (strlen (command) + 1)) == (char *)NULL))return 0;/* Get the next available job number */while (TRUE){jp->pid = pid;jp->Number = JobNumber++;jp->SessionId = SessionId;if (JobNumber > 32000)JobNumber = 1;if (tfind (jp, &JobTree, SearchJob) == (void *)NULL)break;}/* Disable signals */save_signal = signal (SIGINT, SIG_IGN);if (tsearch (jp, &JobTree, SearchJob) != (void *)NULL){SetMemoryAreaNumber ((void *)jp, 0);SetMemoryAreaNumber ((void *)strcpy (jp->Command, command), 0);PATH_TO_UNIX (jp->Command);}/* Restore signals */signal (SIGINT, save_signal);PreviousJob = CurrentJob;return CurrentJob = jp->Number;}/** Display Jobs*/int PrintJobs (bool Mode){DisplayListMode = Mode; /* Set mode */twalk (JobTree, DisplayJob);return 0;}/** Count the number of active jobs*/int NumberOfActiveJobs (void){NumberOfJobs = 0;twalk (JobTree, CountJob);return NumberOfJobs;}#endif/** OS2 1.x - Parse the kernel process information*/#if (OS_TYPE == OS_OS2) && (OS_SIZE == OS_16)static bool F_LOCAL Parse_V1ProcessTable (UCHAR * bBuf, V1ProcessStatus_t *pi){USHORT sel, offs;USHORT type, tpid;USHORT count, kount;UCHAR buffer[256];UCHAR *cptr, *ptr;ptr = bBuf;sel = SELECTOROF (ptr);while ((type = *(USHORT *) ptr) != 0xFFFFU ){ptr += 2;offs = *(USHORT *) ptr;ptr += 2;switch ( type ){case 0: /* Process */if (pi->N_Processes >= pi->M_Processes){V1Process_t **newp = (V1Process_t **)ReAllocateSpace ((void *)pi->V1Processes,(pi->M_Processes + 50) *sizeof (V1Process_t *));if (newp == (V1Process_t **)NULL)return TRUE;pi->V1Processes = newp;pi->M_Processes += 50;}/* Create the process entry */pi->V1Processes[pi->N_Processes] =(V1Process_t *) GetAllocatedSpace (sizeof (V1Process_t));if (pi->V1Processes[pi->N_Processes] == (V1Process_t *)NULL)return TRUE;pi->V1Processes[pi->N_Processes]->pid = *(USHORT *)ptr;ptr += 2;pi->V1Processes[pi->N_Processes]->ppid = *(USHORT *) ptr;ptr += 2;ptr += 2;pi->V1Processes[pi->N_Processes]->modhandle = *(USHORT *) ptr;pi->V1Processes[pi->N_Processes++]->threads = 0;break;case 1: /* Thread */ptr += 2;tpid = *(USHORT *) ptr;/* Increment the thread count for the process */for (count = 0; count < pi->N_Processes; count++){if (pi->V1Processes[count]->pid == tpid){++pi->V1Processes[count]->threads;break;}}break;case 2: /* module */if (pi->N_Modules >= pi->M_Modules){V1Module_t **newm = (V1Module_t **)ReAllocateSpace ((void *)pi->V1Modules,(pi->M_Modules + 50) *sizeof (V1Module_t *));if (newm == (V1Module_t **)NULL)return TRUE;pi->V1Modules = newm;pi->M_Modules += 50;}pi->V1Modules[pi->N_Modules]= (V1Module_t *)GetAllocatedSpace (sizeof(V1Module_t));if (pi->V1Modules[pi->N_Modules] == (V1Module_t *)NULL)return TRUE;pi->V1Modules[pi->N_Modules]->modhandle = *(USHORT *) ptr;ptr += 2;pi->V1Modules[pi->N_Modules]->max_dependents = *(USHORT *) ptr;ptr += 2;ptr += 2;ptr += 2;if (pi->V1Modules[pi->N_Modules] -> max_dependents)ptr += (pi->V1Modules[pi->N_Modules] -> max_dependents) * 2;for (cptr = buffer; *cptr++ = *ptr++;)continue;if ((pi->V1Modules[pi->N_Modules]->modname =StringCopy (buffer)) == null)return 1;++pi->N_Modules;break;case 3: /* system semaphore */case 4: /* shared memory */break;}ptr = MAKEP(sel, offs);}/* Count modules */for (count = 0; count < pi->N_Processes; count++){for (kount = 0; kount < pi->N_Modules; kount++){if (pi->V1Processes[count]->modhandle ==pi->V1Modules[kount]->modhandle){pi->V1Processes[count]->module = kount;break;}}}/* Count children */for (count = 0; count < pi->N_Processes; count++){for (kount = 0; kount < pi->N_Processes; kount++){if (pi->V1Processes[count]->pid == pi->V1Processes[kount]->ppid)(pi->V1Processes[count]->children)++;}}return FALSE;}/** Process the process information*/static void F_LOCAL PrintV1ProcessTree (pid_t pid, int indent,V1ProcessStatus_t *pi){USHORT count;UCHAR *mName, pName[256];for (count = 0; count < pi->N_Processes; count++){if ((indent && (pi->V1Processes[count]->ppid == (USHORT)pid)) ||((!indent) && (pi->V1Processes[count]->pid == (USHORT)pid))){if (pi->V1Processes[count]->module){mName = pi->V1Modules[pi->V1Processes[count]->module]->modname;DosGetModName (pi->V1Processes[count]->modhandle,sizeof(pName), pName);}else{mName = "unknown"; /* Zombie process, */pName[0] = 0;}printf ("%5d %5d %3d %-8s %*s%s\n", pi->V1Processes[count]->pid,pi->V1Processes[count]->ppid,pi->V1Processes[count]->threads, mName, indent, "", pName);PrintV1ProcessTree (pi->V1Processes[count]->pid, indent + 2, pi);}}}static int SortV1Processes (void *p1, void *p2){return (*(V1Process_t **)p1)->pid - (*(V1Process_t **)p2)->pid;}#endif/** OS/2 2.x 32-bit version - Display Process Tree*/#if (OS_TYPE == OS_OS2)static void F_LOCAL V2_DisplayProcessTree (USHORT pid, USHORT indent,V2ProcessStatus_t *ps){V2Process_t *proc;UCHAR name[FFNAME_MAX];USHORT prty;/* Not sure if there isn't another termination method */for (proc = PTR (ps->ppi); (proc->ulEndIndicator != PROCESS_END_INDICATOR);proc = (V2Process_t *) PTR (proc->ptiFirst + proc->usThreadCount)){if ((indent && (proc->pidParent == pid)) ||((!indent) && (proc->pid == pid))){# if (OS_SIZE == OS_32)if (DosQueryModuleName (proc->hModRef, sizeof (name), name))# elseif (DosGetModName (proc->hModRef, sizeof (name), name))# endifstrcpy(name, "<unknown>");if (Dos32GetPrty (PRTYS_PROCESS, &prty, proc->pid))prty = 0;printf ("%5d %5d %3d %04x %*s%s\n", proc->pid, proc->pidParent,proc->usThreadCount, prty, indent, "", name);V2_DisplayProcessTree (proc->pid, indent + 2, ps);}}}/** Print the Process Tree*/int PrintProcessTree (pid_t pid){# if (OS_SIZE == OS_16)USHORT rc;/* Switch on release number */if (_osmajor < 20){UCHAR *pBuf = GetAllocatedSpace (0x2000);USHORT count;V1ProcessStatus_t pi;pi.M_Processes = pi.M_Modules = pi.N_Processes = pi.N_Modules = 0;pi.V1Processes = NULL;pi.V1Modules = NULL;if (pBuf == (UCHAR *)NULL)return 1;if (rc = Dos32QProcStatus (pBuf, 0x2000))return PrintWarningMessage ("jobs: DosQProcStatus failed\n%s",GetOSSystemErrorMessage (rc));if (Parse_V1ProcessTable (pBuf, &pi))return 1;ReleaseMemoryCell ((void *)pBuf);qsort ((void *)pi.V1Processes, pi.N_Processes, sizeof (V1Process_t *),SortV1Processes);puts (" PID PPID TC Name Program");PrintV1ProcessTree (pid, 0, &pi);for (count = 0; count < pi.N_Processes; count++)ReleaseMemoryCell ((void *)pi.V1Processes[count]);for (count = 0; count < pi.N_Modules; count++){ReleaseMemoryCell ((void *)pi.V1Modules[count] -> modname);ReleaseMemoryCell ((void *)pi.V1Modules[count]);}ReleaseMemoryCell ((void *)pi.V1Processes);ReleaseMemoryCell ((void *)pi.V1Modules);}/** OS2 2.0 - grap space, get the information and display it*/else# endif# if defined (__WATCOMC__){int res;if ((res = spawnlp (P_WAIT, "ps.exe", "ps", IntegerToString (pid),(char *)NULL)) < 0)return PrintWarningMessage ("jobs: cannot find ps.exe\n");else if (res)return 1;}# else{V2ProcessStatus_t *ps;if ((ps = GetProcessStatus ("jobs")) == (V2ProcessStatus_t *)NULL)return 1;puts (" PID PPID TC PRI Program");V2_DisplayProcessTree (pid, 0, ps);ReleaseMemoryCell ((void *)ps);}# endifreturn 0;}/** Get OS/2 2.x Process Structure*/static V2ProcessStatus_t * F_LOCAL GetProcessStatus (char *name){OSCALL_RET rc;V2ProcessStatus_t *ps;if ((ps = (V2ProcessStatus_t *)GetAllocatedSpace (0x8000))== (V2ProcessStatus_t *)NULL)return (V2ProcessStatus_t *)NULL;if ((rc = Dos32QProcStatus (ps, 0x8000))){PrintWarningMessage ("%s: DosQProcStatus failed\n%s", name,GetOSSystemErrorMessage (rc));return (V2ProcessStatus_t *)NULL;}return ps;}#endif/** A unix version of print process tree*/#if (OS_TYPE == OS_UNIX)int PrintProcessTree (pid_t pid){return system ("ps") ? PrintWarningMessage ("jobs: cannot find ps\n"): 0;}#endif/** A sort of times is available for OS/2. Not quite the complete UNIX* emulation, since it only reports current children. However!* I think the times in the process structure are in 1/100th second.*/#if (OS_TYPE == OS_OS2) && (OS_SIZE == OS_32)int PrintTimes (void){V2ProcessStatus_t *ps;V2Process_t *ppiLocal;V2Thread_t *ptiCurrent;time_t *Utime;time_t *Stime;int i;USHORT pid = getpid ();time_t tms_utime = 0;time_t tms_stime = 0;time_t tms_cutime = 0;time_t tms_cstime = 0;/* Initialise */if ((ps = GetProcessStatus ("times")) == (V2ProcessStatus_t *)NULL)return 1;/* Scan the process tree */for (ppiLocal = ps->ppi;(ppiLocal->ulEndIndicator != PROCESS_END_INDICATOR);ppiLocal = (V2Process_t *) (ppiLocal->ptiFirst +ppiLocal->usThreadCount)){if (ppiLocal->pidParent == pid){Utime = &tms_cutime;Stime = &tms_cstime;}else if (ppiLocal->pid == pid){Utime = &tms_utime;Stime = &tms_stime;}/* If neither - skip */elsecontinue;/* Process threads */ptiCurrent = ppiLocal->ptiFirst;for (i = 0; i < ppiLocal->usThreadCount; i++, ptiCurrent++){*Utime += ptiCurrent->ulUserTime;*Stime += ptiCurrent->ulSysTime;}}/* Dump the info */printf ("%ldm%.2ld.%.2lds %ldm%ld.%.2lds\n",tms_utime / 6000L, (tms_utime % 6000L) / 100L, tms_utime % 100L,tms_stime / 6000L, (tms_stime % 6000L) / 100L, tms_stime % 100L);printf ("%ldm%.2ld.%.2lds %ldm%ld.%.2lds\n",tms_cutime / 6000L, (tms_cutime % 6000L) / 100L, tms_cutime % 100L,tms_cstime / 6000L, (tms_cstime % 6000L) / 100L, tms_cstime % 100L);return 0;}#endif/* NT Version */#if (OS_TYPE == OS_NT)int PrintTimes (void){FILETIME CreationTime;FILETIME ExitTime;FILETIME KernelTime;FILETIME UserTime;if (!GetProcessTimes (0, &CreationTime, &ExitTime, &KernelTime, &UserTime))return PrintWarningMessage ("times: GetProcesTimes failed\n%s",GetOSSystemErrorMessage (GetLastError ()));printf ("Kernel Time = %ld %ld\n", KernelTime.dwHighDateTime,KernelTime.dwLowDateTime);printf ("User Time = %ld %ld\n", UserTime.dwHighDateTime,UserTime.dwLowDateTime);return 0;}#endif/* UNIX Version */#if (OS_TYPE == OS_UNIX)int PrintTimes (void){struct tms tms;times (&tms);printf ("%dm%.2d.%.2ds %dm%d.%.2ds\n%dm%.2d.%.2ds %dm%d.%.2ds\n",tms.tms_utime / (60L * (long)CLK_TCK),(tms.tms_utime % (60L * (long)CLK_TCK)) / (long)CLK_TCK,tms.tms_utime % (long)CLK_TCK,tms.tms_stime / (60L * (long)CLK_TCK),(tms.tms_stime % (60L * (long)CLK_TCK)) / (long)CLK_TCK,tms.tms_stime % (long)CLK_TCK,tms.tms_cutime / (60L * (long)CLK_TCK),(tms.tms_cutime % (60L * (long)CLK_TCK)) / (long)CLK_TCK,tms.tms_cutime % (long)CLK_TCK,tms.tms_cstime / (60L * (long)CLK_TCK),(tms.tms_cstime % (60L * (long)CLK_TCK)) / (long)CLK_TCK,tms.tms_cstime % (long)CLK_TCK);return 0;}#endif/** Specials for EMX*/#if defined (__EMX__) && (OS_TYPE == OS_OS2)USHORT Dos32GetPrty (USHORT usScope, PUSHORT pusPriority, USHORT pid){return ((USHORT)(_THUNK_PROLOG (2 + 4 + 2);_THUNK_SHORT (usScope);_THUNK_FLAT (pusPriority);_THUNK_SHORT (pid);_THUNK_CALL (Dos16GetPrty)));}USHORT Dos32QProcStatus (PVOID pvProcData, USHORT usSize){return ((USHORT)(_THUNK_PROLOG (4 + 2);_THUNK_FLAT (pvProcData);_THUNK_SHORT (usSize);_THUNK_CALL (Dos16QProcStatus)));}#endif