/****************************************************************************** ** @source AJAX system functions ** ** Copyright (c) Alan Bleasby 1999 ** @version 1.0 ** @@ ** ** This library is free software; you can redistribute it and/or ** modify it under the terms of the GNU Library General Public ** License as published by the Free Software Foundation; either ** version 2 of the License, or (at your option) any later version. ** ** This library is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** Library General Public License for more details. ** ** You should have received a copy of the GNU Library General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ******************************************************************************/ #include "ajax.h" #ifndef WIN32 #ifndef __VMS #include #endif #include #include #include #include #else #include "win32.h" #endif static AjPStr sysTokRets = NULL; static AjPStr sysTokSou = NULL; static const char *sysTokp = NULL; /* @filesection ajutil ******************************************************** ** ** @nam1rule aj Function belongs to the AJAX library. ** */ /* @datasection [none] System utility functions ******************************* ** ** @nam2rule Sys Function belongs to the AJAX ajsys library. ** */ /* @section Argument list manipulation functions ****************************** ** ** Function for manipulating argument list. ** ** @fdata [none] ** ** @nam3rule Arglist Function for manipulating argument list. ** @nam4rule ArglistBuild Generates a program name and argument list from a ** command line string. ** @nam4rule ArglistFree Free memory in an argument list allocated by ** ajSysArglistBuild. ** ** @argrule Build cmdline [const AjPStr] Original command line ** @argrule Build Pname [char**] Returned program name ** @argrule Arglist PParglist [char***] Returns argument array ** ** @valrule Build [AjBool] True on success ** @valrule Free [void] ** ** @fcategory misc ** ******************************************************************************/ /* @func ajSysArglistBuild **************************************************** ** ** Generates a program name and argument list from a command line string. ** ** @param [r] cmdline [const AjPStr] Command line. ** @param [w] Pname [char**] Program name. ** @param [w] PParglist [char***] Argument list. ** @return [AjBool] ajTrue on success. ** @@ ******************************************************************************/ AjBool ajSysArglistBuild(const AjPStr cmdline, char** Pname, char*** PParglist) { static AjPRegexp argexp = NULL; AjPStr tmpline = NULL; const char* cp; ajint ipos = 0; ajint iarg = 0; ajint ilen = 0; ajint i; char** al; AjPStr argstr = NULL; if(!argexp) argexp = ajRegCompC("^[ \t]*(\"([^\"]*)\"|'([^']*)'|([^ \t]+))"); ajDebug("ajSysArglistBuild '%S'\n", cmdline); ajStrAssignS(&tmpline, cmdline); cp = ajStrGetPtr(cmdline); ipos = 0; while(ajRegExecC(argexp, &cp[ipos])) { ipos += ajRegLenI(argexp, 0); iarg++; } AJCNEW(*PParglist, iarg+1); al = *PParglist; ipos = 0; iarg = 0; while(ajRegExecC(argexp, &cp[ipos])) { ilen = ajRegLenI(argexp, 0); ajStrDelStatic(&argstr); for(i=2;i<5;i++) { if(ajRegLenI(argexp, i)) { ajRegSubI(argexp, i, &argstr); /*ajDebug("parsed [%d] '%S'\n", i, argstr);*/ break; } } ipos += ilen; if(!iarg) *Pname = ajCharNewS(argstr); al[iarg] = ajCharNewS(argstr); iarg++; } al[iarg] = NULL; ajRegFree(&argexp); argexp = NULL; ajStrDel(&tmpline); ajStrDel(&argstr); ajDebug("ajSysArglistBuild %d args for '%s'\n", iarg, *Pname); return ajTrue; } /* @obsolete ajSysArglist ** @rename ajSysArglistBuild */ __deprecated AjBool ajSysArglist(const AjPStr cmdline, char** Pname, char*** PParglist) { return ajSysArglistBuild(cmdline, Pname, PParglist); } /* @func ajSysArglistFree ***************************************************** ** ** Free memory in an argument list allocated by ajSysArgList ** ** @param [w] PParglist [char***] Argument list. ** @return [void] ** @@ ******************************************************************************/ void ajSysArglistFree(char*** PParglist) { char** ca; ajint i; ca = *PParglist; i = 0; while(ca[i]) { AJFREE(ca[i]); ++i; } AJFREE(*PParglist); return; } /* @obsolete ajSysArgListFree ** @rename ajSysArglistFree */ __deprecated void ajSysArgListFree(char*** PParglist) { ajSysArglistFree(PParglist); return; } /* @section System cast functions ********************************************* ** ** Function for casting one datatype to another. ** ** @fdata [none] ** @fcategory misc ** ** @nam3rule Cast Function for casting one datatype to another. ** @nam4rule CastItoc Convert Int to Char (for fussy compilers) ** @nam4rule CastItouc Convert Int to Unsigned Char (for fussy compilers). ** ** @argrule * v [ajint] Character as an integer ** ** @valrule *Itoc [char] Character ** @valrule *Itouc [unsigned char] Unsigned character ** ******************************************************************************/ /* @func ajSysCastItoc ******************************************************** ** ** Convert Int to Char ** Needed for very fussy compilers i.e. Digital C ** ** @param [r] v [ajint] integer ** @return [char] Character cast ** @@ ******************************************************************************/ char ajSysCastItoc(ajint v) { char c; c = (char) v; return c; } /* @obsolete ajSysItoC ** @rename ajSysCastItoC */ __deprecated char ajSysItoC(ajint v) { return ajSysCastItoc(v); } /* @func ajSysCastItouc ******************************************************* ** ** Convert Int to Unsigned Char ** Needed for very fussy compilers i.e. Digital C ** ** @param [r] v [ajint] integer ** @return [unsigned char] Unisigned character cast ** @@ ******************************************************************************/ unsigned char ajSysCastItouc(ajint v) { char c; c = (unsigned char) v; return c; } /* @obsolete ajSysItoUC ** @rename ajSysCastItouc */ __deprecated unsigned char ajSysItoUC(ajint v) { return ajSysCastItouc(v); } /* @section System functions for files **************************************** ** ** System functions for files. ** ** @fdata [none] ** @fcategory misc ** ** @nam3rule File System functions for files. ** @nam4rule FileWhich Searches $PATH sequentially for a user-EXECUTABLE ** file. ** @nam5rule FileWhichEnv Uses environment to extract the PATH list. ** @nam4rule FileUnlink Deletes a file or link ** ** @argrule Unlink filename [const AjPStr] File name ** @argrule Which Pfilename [AjPStr*] File name (updated when found) ** @argrule Env env [char* const[]] File name (updated when found) ** @valrule * [AjBool] True if operation is successful. ** ******************************************************************************/ /* @func ajSysFileUnlink ****************************************************** ** ** Deletes a file or link ** ** @param [r] filename [const AjPStr] Filename in AjStr. ** @return [AjBool] true if deleted false otherwise ** @@ ******************************************************************************/ AjBool ajSysFileUnlink(const AjPStr filename) { ajDebug("ajSysFileUnlink '%S'\n", filename); #ifndef WIN32 if(!unlink(ajStrGetPtr(filename))) return ajTrue; #else if(DeleteFile(ajStrGetPtr(filename))) return ajTrue; #endif ajDebug("ajSysUnlink failed to delete '%S'\n", filename); return ajFalse; } /* @obsolete ajSysUnlink ** @rename ajSysFileUnlink */ __deprecated AjBool ajSysUnlink(const AjPStr s) { return ajSysFileUnlink(s); } /* @func ajSysFileWhich ******************************************************* ** ** Gets the Basename of a file then searches $PATH sequentially until it ** finds a user-EXECUTABLE file of the same name. ** ** @param [u] Pfilename [AjPStr*] Filename in AjStr, replaced by full pathname ** @return [AjBool] True if executable found, false otherwise ** @@ ******************************************************************************/ AjBool ajSysFileWhich(AjPStr *Pfilename) { char *p; static AjPStr tname = NULL; static AjPStr fname = NULL; p = getenv("PATH"); if(!p) return ajFalse; ajStrAssignS(&tname, *Pfilename); if(!fname) fname = ajStrNew(); ajFilenameTrimPath(&tname); p=ajSysFuncStrtok(p,PATH_SEPARATOR); if(p==NULL) { ajStrDelStatic(&fname); ajStrDelStatic(&tname); return ajFalse; } while(1) { ajFmtPrintS(&fname,"%s%s%S",p,SLASH_STRING,tname); if(ajFilenameExistsExec(fname)) { ajStrSetClear(Pfilename); ajStrAssignEmptyS(Pfilename,fname); break; } if((p = ajSysFuncStrtok(NULL,PATH_SEPARATOR))==NULL) { ajStrDelStatic(&fname); ajStrDelStatic(&tname); return ajFalse; } } ajStrDelStatic(&fname); ajStrDelStatic(&tname); return ajTrue; } /* @obsolete ajSysWhich ** @rename ajSysFileWhich */ __deprecated AjBool ajSysWhich(AjPStr *s) { return ajSysFileWhich(s); } /* @func ajSysFileWhichEnv **************************************************** ** ** Gets the Basename of a file then searches $PATH sequentially until it ** finds a user-EXECUTABLE file of the same name. Reentrant. ** ** @param [u] Pfilename [AjPStr*] Filename in AjStr, replaced by full pathname ** @param [r] env [char* const[]] Environment ** @return [AjBool] True if executable found, false otherwise ** @@ ******************************************************************************/ AjBool ajSysFileWhichEnv(AjPStr *Pfilename, char * const env[]) { ajint count; char *p = NULL; const char *cp; AjPStr tname = NULL; AjPStr fname = NULL; AjPStr path = NULL; const char *save = NULL; AjPStr buf = NULL; AjPStr tmp = NULL; buf = ajStrNew(); tname = ajStrNew(); tmp = ajStrNew(); ajStrAssignS(&tname,*Pfilename); fname = ajStrNew(); path = ajStrNew(); ajFilenameTrimPath(&tname); #ifdef WIN32 ajStrAppendC(&tname,".exe"); #endif ajDebug("ajSysFileWhichEnv '%S' => %S\n", *Pfilename, tname); count = 0; while(env[count]!=NULL) { if(!(*env[count])) break; /*ajDebug(" env[%d] '%s'\n", count, env[count]);*/ #ifndef WIN32 if(!strncmp("PATH=",env[count],5)) #else if(!strnicmp("PATH=",env[count],5)) #endif break; ++count; } /* ajDebug("PATH env[%d] '%s'\n", count, env[count]);*/ if(env[count]==NULL || !(*env[count])) { ajStrDel(&fname); ajStrDel(&tname); ajStrDel(&path); ajStrDel(&buf); ajStrDel(&tmp); return ajFalse; } ajStrAssignC(&path, env[count]); cp = ajStrGetPtr(path); cp += 5; ajStrAssignC(&tmp,cp); /*ajDebug("tmp '%S' save '%S' buf '%S'\n", tmp, save, buf);*/ p = ajSysFuncStrtokR(ajStrGetuniquePtr(&tmp),PATH_SEPARATOR,&save,&buf); if(p==NULL) { ajStrDel(&fname); ajStrDel(&tname); ajStrDel(&path); ajStrDel(&buf); ajStrDel(&tmp); return ajFalse; } ajFmtPrintS(&fname,"%s%s%S",p,SLASH_STRING,tname); while(!ajFilenameExistsExec(fname)) { if((p = ajSysFuncStrtokR(NULL,PATH_SEPARATOR,&save,&buf))==NULL) { ajStrDel(&fname); ajStrDel(&tname); ajStrDel(&path); ajStrDel(&buf); ajStrDel(&tmp); return ajFalse; } ajFmtPrintS(&fname,"%s%s%S",p,SLASH_STRING,tname); } ajStrAssignS(Pfilename,fname); ajDebug("ajSysFileWhichEnv returns '%S'\n", *Pfilename); ajStrDel(&fname); ajStrDel(&tname); ajStrDel(&path); ajStrDel(&buf); ajStrDel(&tmp); return ajTrue; } /* @obsolete ajSysWhichEnv ** @rename ajSysFileWhichEnv */ __deprecated AjBool ajSysWhichEnv(AjPStr *Pfilename, char * const env[]) { return ajSysFileWhichEnv(Pfilename, env); } /* @section Wrappers to C functions ******************************************* ** ** Functions for calling or substituting C-functions. ** ** @fdata [none] ** @fcategory misc ** ** @nam3rule Func Replacement for C-function. ** @nam4rule FuncStrtok strtok that doesn't corrupt the source string ** @nam5rule FuncStrtokR Reentrant version. ** @nam4rule FuncFgets An fgets replacement that will cope with Mac OSX ** files ** @nam4rule FuncFopen An fopen replacement to cope with cygwin and windows ** @nam4rule FuncFdopen Calls non-ANSI fdopen. ** @nam4rule FuncStrdup Duplicate BSD strdup function for very strict ANSI ** @nam3rule System Execute a command line as if from the C shell ** @nam4rule SystemEnv Execute command line and pass the environment ** received from main to extract the PATH list ** @nam4rule SystemOut Execute command line and write standard output to ** a named file ** ** @argrule Fdopen filedes [ajint] file descriptor ** @argrule Fdopen mode [const char*] file mode ** @argrule Fgets buf [char*] buffer ** @argrule Fgets size [int] maximum length to read ** @argrule Fgets fp [FILE*] stream ** @argrule Fopen name [const char*] Name of file to open ** @argrule Fopen flags [const char*] Read/write/append flags ** @argrule Strdup dupstr [const char*] String to duplicate ** @argrule Strtok srcstr [const char*] source string ** @argrule Strtok delimstr [const char*] delimiter string ** @argrule R ptrptr [const char**] Saved pointer ** @argrule R buf [AjPStr*] Independent buffer provided by caller ** @argrule System cmdline [const AjPStr] The command line ** @argrule SystemEnv env [char* const[]] Environment variables and values ** @argrule SystemOut outfname [const AjPStr] The output file name ** ** @valrule Fdopen [FILE*] C open file ** @valrule Fgets [char*] Buffer on success ** @valrule Fopen [FILE*] C open file ** @valrule Strdup [char*] New string ** @valrule Strtok [char*] New string ** @valrule System [void] ** ******************************************************************************/ /* @func ajSysFuncFdopen ****************************************************** ** ** Place non-ANSI fdopen here ** ** @param [r] filedes [ajint] file descriptor ** @param [r] mode [const char *] file mode ** @return [FILE*] file pointer ** @@ ******************************************************************************/ FILE* ajSysFuncFdopen(ajint filedes, const char *mode) { return fdopen(filedes,mode); } /* @obsolete ajSysFdopen ** @rename ajSysFuncFdopen */ __deprecated FILE* ajSysFdopen(ajint filedes, const char *mode) { return ajSysFuncFdopen(filedes, mode); } /* @func ajSysFuncFgets ******************************************************* ** ** An fgets replacement that will cope with Mac OSX files ** ** @param [w] buf [char*] buffer ** @param [r] size [int] maximum length to read ** @param [u] fp [FILE*] stream ** ** @return [char*] buf or NULL ** @@ ******************************************************************************/ char* ajSysFuncFgets(char *buf, int size, FILE *fp) { #ifdef __ppc__ int c = 0; char *p; int cnt; p = buf; if(!size || size<0) return NULL; cnt = 0; while(cnt!=size-1) { c = getc(fp); if(c==EOF || c=='\r' || c=='\n') break; *(p++) = c; ++cnt; } *p ='\0'; if(c==EOF && !cnt) return NULL; if(cnt == size-1) return buf; if(c=='\r' || c=='\n') { if(c=='\r' && cnt