1 /* @source ajsys **************************************************************
2 **
3 ** AJAX system functions
4 **
5 ** Copyright (c) Alan Bleasby 1999
6 ** @version $Revision: 1.90 $
7 ** @modified $Date: 2011/11/23 09:52:54 $ by $Author: rice $
8 ** @@
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 ** MA  02110-1301,  USA.
24 **
25 ******************************************************************************/
26 
27 
28 #include "ajlib.h"
29 
30 #include "ajsys.h"
31 #include "ajlist.h"
32 #include "ajfile.h"
33 #include "ajreg.h"
34 #include "ajnam.h"
35 #include "ajutil.h"
36 
37 #ifndef WIN32
38 #ifndef __VMS
39 #include <termios.h>
40 #endif
41 #include <sys/file.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <unistd.h>
45 #include <locale.h>
46 #include <pwd.h>
47 #include <fcntl.h>
48 #else
49 #include "win32.h"
50 #include <direct.h>
51 #include <stdio.h>
52 #include <io.h>
53 #define open     _open
54 #define close    _close
55 #define read     _read
56 #define write    _write
57 #define strnicmp _strnicmp
58 #define fdopen   _fdopen
59 #define rmdir    _rmdir
60 
61 #pragma warning(disable:4142)    /* benign redefinition of type */
62 #include <ShlObj.h>
63 #include <Sddl.h>
64 #endif
65 
66 #include <errno.h>
67 
68 
69 static AjPStr sysTname = NULL;
70 static AjPStr sysFname = NULL;
71 static AjPStr sysTokRets = NULL;
72 static AjPStr sysTokSou  = NULL;
73 static const char *sysTokp = NULL;
74 static AjPStr sysUserPath = NULL;
75 
76 #ifndef WIN32
77 static void sysTimeoutAbort(int sig);
78 #else
79 static void CALLBACK sysTimeoutAbort(LPVOID arg, DWORD low, DWORD high);
80 #endif
81 
82 
83 
84 
85 /* @filesection ajutil ********************************************************
86 **
87 ** @nam1rule aj   Function belongs to the AJAX library.
88 **
89 */
90 
91 
92 
93 
94 /* @datasection [none] System utility functions *******************************
95 **
96 ** @nam2rule Sys  Function belongs to the AJAX ajsys library.
97 **
98 */
99 
100 
101 
102 
103 /* @section Argument list manipulation functions ******************************
104 **
105 ** Function for manipulating argument list.
106 **
107 ** @fdata [none]
108 **
109 ** @nam3rule  Arglist      Function for manipulating argument list.
110 ** @nam4rule  ArglistBuild Generates a program name and argument list from a
111 **                         command line string.
112 ** @nam4rule  ArglistFree   Free memory in an argument list allocated by
113 **                         ajSysArglistBuild.
114 ** @suffix    C            Accept C character string parameters
115 ** @suffix    S            Accept string object parameters
116 **
117 ** @argrule C       cmdlinetxt [const char*] Original command line
118 ** @argrule S       cmdline    [const AjPStr] Original command line
119 ** @argrule Build   Pname      [char**] Returned program name
120 ** @argrule Arglist PParglist  [char***] Returns argument array
121 **
122 ** @valrule Build [AjBool] True on success
123 ** @valrule Free [void]
124 **
125 ** @fcategory misc
126 **
127 ******************************************************************************/
128 
129 
130 
131 
132 /* @func ajSysArglistBuildC ***************************************************
133 **
134 ** Generates a program name and argument list from a command line string.
135 **
136 ** @param [r] cmdlinetxt [const char*] Command line.
137 ** @param [w] Pname [char**] Program name.
138 ** @param [w] PParglist [char***] Argument list.
139 ** @return [AjBool] ajTrue on success.
140 **
141 ** @release 6.3.0
142 ** @@
143 ******************************************************************************/
144 
ajSysArglistBuildC(const char * cmdlinetxt,char ** Pname,char *** PParglist)145 AjBool ajSysArglistBuildC(const char* cmdlinetxt,
146                           char** Pname, char*** PParglist)
147 {
148     static AjPRegexp argexp = NULL;
149     AjPStr tmpline          = NULL;
150     const char* cp;
151     ajint ipos = 0;
152     ajint iarg = 0;
153     ajint ilen = 0;
154     ajint i;
155     char** al;
156     AjPStr argstr = NULL;
157 
158     if(!argexp)
159 	argexp = ajRegCompC("^[ \t]*(\"([^\"]*)\"|'([^']*)'|([^ \t]+))");
160 
161     ajDebug("ajSysArglistBuildC '%s'\n", cmdlinetxt);
162 
163     ajStrAssignC(&tmpline, cmdlinetxt);
164 
165     cp   = cmdlinetxt;
166     ipos = 0;
167     while(ajRegExecC(argexp, &cp[ipos]))
168     {
169 	ipos += ajRegLenI(argexp, 0);
170 	iarg++;
171     }
172 
173     AJCNEW(*PParglist, iarg+1);
174     al   = *PParglist;
175     ipos = 0;
176     iarg = 0;
177     while(ajRegExecC(argexp, &cp[ipos]))
178     {
179 	ilen = ajRegLenI(argexp, 0);
180 	ajStrDelStatic(&argstr);
181 	for(i=2;i<5;i++)
182 	{
183 	    if(ajRegLenI(argexp, i))
184 	    {
185 		ajRegSubI(argexp, i, &argstr);
186 		ajDebug("parsed [%d] '%S'\n", i, argstr);
187 		break;
188 	    }
189 	}
190 	ipos += ilen;
191 
192 	if(!iarg)
193 	    *Pname = ajCharNewS(argstr);
194 
195 	al[iarg] = ajCharNewS(argstr);
196 	iarg++;
197     }
198 
199     al[iarg] = NULL;
200 
201     ajRegFree(&argexp);
202     argexp = NULL;
203     ajStrDel(&tmpline);
204     ajStrDel(&argstr);
205 
206     ajDebug("ajSysArglistBuildC %d args for '%s'\n", iarg, *Pname);
207 
208     return ajTrue;
209 }
210 
211 
212 
213 
214 /* @func ajSysArglistBuildS ***************************************************
215 **
216 ** Generates a program name and argument list from a command line string.
217 **
218 ** @param [r] cmdline [const AjPStr] Command line.
219 ** @param [w] Pname [char**] Program name.
220 ** @param [w] PParglist [char***] Argument list.
221 ** @return [AjBool] ajTrue on success.
222 **
223 ** @release 6.3.0
224 ** @@
225 ******************************************************************************/
226 
ajSysArglistBuildS(const AjPStr cmdline,char ** Pname,char *** PParglist)227 AjBool ajSysArglistBuildS(const AjPStr cmdline, char** Pname, char*** PParglist)
228 {
229     return ajSysArglistBuildC(MAJSTRGETPTR(cmdline), Pname, PParglist);
230 }
231 
232 
233 
234 
235 /* @func ajSysArglistFree *****************************************************
236 **
237 ** Free memory in an argument list allocated by ajSysArgList
238 **
239 ** @param [w] PParglist [char***] Argument list.
240 ** @return [void]
241 **
242 ** @release 5.0.0
243 ** @@
244 ******************************************************************************/
245 
ajSysArglistFree(char *** PParglist)246 void ajSysArglistFree(char*** PParglist)
247 {
248     char** ca;
249     ajint i;
250 
251     ca = *PParglist;
252 
253     i = 0;
254     while(ca[i])
255     {
256 	AJFREE(ca[i]);
257 	++i;
258     }
259 
260     AJFREE(*PParglist);
261 
262     return;
263 }
264 
265 
266 
267 
268 /* @section System cast functions *********************************************
269 **
270 ** Function for casting one datatype to another.
271 **
272 ** @fdata [none]
273 ** @fcategory misc
274 **
275 ** @nam3rule  Cast         Function for casting one datatype to another.
276 ** @nam4rule  CastItoc     Convert Int to Char (for fussy compilers)
277 ** @nam4rule  CastItouc    Convert Int to Unsigned Char (for fussy compilers).
278 **
279 ** @argrule * v [ajint] Character as an integer
280 **
281 ** @valrule *Itoc [char] Character
282 ** @valrule *Itouc [unsigned char] Unsigned character
283 **
284 ******************************************************************************/
285 
286 
287 
288 
289 /* @func ajSysCastItoc ********************************************************
290 **
291 ** Convert Int to Char
292 ** Needed for very fussy compilers i.e. Digital C
293 **
294 ** @param [r] v [ajint] integer
295 ** @return [char] Character cast
296 **
297 ** @release 5.0.0
298 ** @@
299 ******************************************************************************/
300 
ajSysCastItoc(ajint v)301 char ajSysCastItoc(ajint v)
302 {
303     char c;
304 
305     c = (char) v;
306     return c;
307 }
308 
309 
310 
311 
312 /* @func ajSysCastItouc *******************************************************
313 **
314 ** Convert Int to Unsigned Char
315 ** Needed for very fussy compilers i.e. Digital C
316 **
317 ** @param [r] v [ajint] integer
318 ** @return [unsigned char] Unsigned character cast
319 **
320 ** @release 5.0.0
321 ** @@
322 ******************************************************************************/
323 
ajSysCastItouc(ajint v)324 unsigned char ajSysCastItouc(ajint v)
325 {
326     char c;
327 
328     c = (unsigned char) v;
329     return c;
330 }
331 
332 
333 
334 
335 /* @section System functions for files ****************************************
336 **
337 ** System functions for files.
338 **
339 ** @fdata [none]
340 ** @fcategory misc
341 **
342 ** @nam3rule  File           System functions for files.
343 ** @nam4rule  FileRmrf       Recursively deletes a directory tree
344 ** @nam4rule  FileWhich      Searches $PATH sequentially for a user-EXECUTABLE
345 **                           file.
346 ** @nam5rule  FileWhichEnv   Uses environment to extract the PATH list.
347 ** @nam4rule  FileUnlink     Deletes a file or link
348 ** @nam3rule  Get            Return attribute
349 ** @nam4rule  GetHomedir     Return home directory
350 ** @nam5rule  GetHomedirFrom Get home directory from parameter
351 ** @nam6rule  FromName       Get home directory for a named user
352 **
353 ** @suffix    C            Accept C character string parameters
354 ** @suffix    S            Accept string object parameters
355 **
356 ** @argrule RmrfC path [const char*] Directory name
357 ** @argrule RmrfS path [const AjPStr] Directory name
358 ** @argrule UnlinkC filename [const char*] File name
359 ** @argrule UnlinkS filename [const AjPStr] File name
360 ** @argrule Which Pfilename [AjPStr*] File name (updated when found)
361 ** @argrule Env env [char* const[]] File name (updated when found)
362 ** @argrule FromName username [const char*] Username
363 **
364 ** @valrule Homedir  [char*]  Home directory name
365 ** @valrule File     [AjBool]  True if operation is successful.
366 **
367 ******************************************************************************/
368 
369 
370 
371 
372 /* @func ajSysFileRmrfC *******************************************************
373 **
374 ** Forcibly delete a directory tree
375 **
376 ** @param [r] path [const char*] Directory path
377 ** @return [AjBool] true if deleted false otherwise
378 **
379 ** @release 6.3.0
380 ** @@
381 ******************************************************************************/
382 
ajSysFileRmrfC(const char * path)383 AjBool ajSysFileRmrfC(const char *path)
384 {
385     AjPList flist = NULL;
386 
387     AjPStr wild  = NULL;
388     AjPStr fname = NULL;
389     AjPStr dirpath = NULL;
390     const char *pdir = NULL;
391 
392     AjBool ret;
393 
394 
395     if(ajCharMatchC(path,".") || ajCharMatchC(path,".."))
396         return ajFalse;
397 
398     flist =  ajListNew();
399     wild  =  ajStrNewC("*");
400 
401     dirpath = ajStrNewC(path);
402 
403     ret = ajTrue;
404 
405     if(!ajFilenameExistsDir(dirpath))
406     {
407         ajListFree(&flist);
408         ajStrDel(&wild);
409         ajStrDel(&dirpath);
410 
411         return ajFalse;
412     }
413 
414     ajFilelistAddPathWildDir(flist, dirpath, wild);
415 
416     while(ajListPop(flist, (void **) &fname))
417     {
418         if(ajFilenameExistsDir(fname))
419         {
420             pdir = ajStrGetPtr(fname);
421             ret = ajSysFileRmrfC(pdir);
422 
423             if(!ret)
424                 break;
425 
426         }
427         else
428         {
429             ret = ajSysFileUnlinkS(fname);
430 
431             if(!ret)
432                 break;
433         }
434 
435         ajStrDel(&fname);
436     }
437 
438     if(!(ajCharMatchC(path,".") || ajCharMatchC(path,"..")))
439         if(rmdir(path))
440             ret  = ajFalse;
441 
442     while(ajListPop(flist, (void **) &fname))
443         ajStrDel(&fname);
444 
445     ajStrDel(&wild);
446     ajStrDel(&dirpath);
447 
448     ajListFree(&flist);
449 
450     return ret;
451 }
452 
453 
454 
455 
456 /* @func ajSysFileRmrfS *******************************************************
457 **
458 ** Forcibly delete a directory tree
459 **
460 ** @param [r] path [const AjPStr] Directory path
461 ** @return [AjBool] true if deleted false otherwise
462 **
463 ** @release 6.5.0
464 ** @@
465 ******************************************************************************/
466 
ajSysFileRmrfS(const AjPStr path)467 AjBool ajSysFileRmrfS(const AjPStr path)
468 {
469     return ajSysFileRmrfC(MAJSTRGETPTR(path));
470 }
471 
472 
473 
474 
475 /* @func ajSysFileUnlinkC *****************************************************
476 **
477 ** Deletes a file or link
478 **
479 ** @param [r] filename [const char*] Filename in AjStr.
480 ** @return [AjBool] true if deleted false otherwise
481 **
482 ** @release 6.3.0
483 ** @@
484 ******************************************************************************/
485 
ajSysFileUnlinkC(const char * filename)486 AjBool ajSysFileUnlinkC(const char* filename)
487 {
488     ajDebug("ajSysFileUnlinkC '%s'\n", filename);
489 
490 #ifndef WIN32
491     if(!unlink(filename))
492 	return ajTrue;
493 
494     ajErr("File '%s' remove failed, error:%d '%s'", filename,
495           errno, strerror(errno));
496 #else
497     if(DeleteFile(filename))
498 	return ajTrue;
499 #endif
500     ajDebug("ajSysFileUnlinkC failed to delete '%s'\n", filename);
501 
502     return ajFalse;
503 }
504 
505 
506 
507 
508 /* @func ajSysFileUnlinkS *****************************************************
509 **
510 ** Deletes a file or link
511 **
512 ** @param [r] filename [const AjPStr] Filename in AjStr.
513 ** @return [AjBool] true if deleted false otherwise
514 **
515 ** @release 6.3.0
516 ** @@
517 ******************************************************************************/
518 
ajSysFileUnlinkS(const AjPStr filename)519 AjBool ajSysFileUnlinkS(const AjPStr filename)
520 {
521     return ajSysFileUnlinkC(MAJSTRGETPTR(filename));
522 }
523 
524 
525 
526 
527 /* @func ajSysFileWhich *******************************************************
528 **
529 ** Gets the Basename of a file then searches $PATH sequentially until it
530 ** finds a user-EXECUTABLE file of the same name.
531 **
532 ** @param [u] Pfilename [AjPStr*] Filename in AjStr, replaced by full pathname
533 ** @return [AjBool] True if executable found, false otherwise
534 **
535 ** @release 5.0.0
536 ** @@
537 ******************************************************************************/
538 
ajSysFileWhich(AjPStr * Pfilename)539 AjBool ajSysFileWhich(AjPStr *Pfilename)
540 {
541     char *p;
542 
543     if(!ajStrGetLen(sysUserPath))
544         ajStrAssignC(&sysUserPath, getenv("PATH"));
545 
546     if(!ajStrGetLen(sysUserPath))
547         return ajFalse;
548 
549     p = ajStrGetuniquePtr(&sysUserPath);
550 
551     if(!ajNamGetValueS(*Pfilename, &sysTname))
552         ajStrAssignS(&sysTname, *Pfilename);
553 
554     if(ajFilenameExistsExec(sysTname))
555     {
556         ajStrAssignS(Pfilename,sysTname);
557         ajStrDelStatic(&sysTname);
558         return ajTrue;
559     }
560 
561     if(!sysFname)
562 	sysFname = ajStrNew();
563 
564     p=ajSysFuncStrtok(p,PATH_SEPARATOR);
565 
566     if(p==NULL)
567     {
568 	ajStrDelStatic(&sysFname);
569 	ajStrDelStatic(&sysTname);
570 	return ajFalse;
571     }
572 
573 
574     while(1)
575     {
576 #if !defined(WIN32) && !defined(__CYGWIN__)
577 	ajFmtPrintS(&sysFname,"%s%s%S",p,SLASH_STRING,sysTname);
578 #else
579 	ajFmtPrintS(&sysFname,"%s%s%S.exe",p,SLASH_STRING,sysTname);
580 #endif
581 
582 	if(ajFilenameExistsExec(sysFname))
583 	{
584 	    ajStrAssignS(Pfilename,sysFname);
585 	    break;
586 	}
587 
588 	if((p = ajSysFuncStrtok(NULL,PATH_SEPARATOR))==NULL)
589         {
590 	    ajStrDelStatic(&sysFname);
591 	    ajStrDelStatic(&sysTname);
592 	    return ajFalse;
593         }
594     }
595 
596     ajStrDelStatic(&sysFname);
597     ajStrDelStatic(&sysTname);
598 
599     return ajTrue;
600 }
601 
602 
603 
604 
605 /* @func ajSysFileWhichEnv ****************************************************
606 **
607 ** Gets the Basename of a file then searches $PATH sequentially until it
608 ** finds a user-EXECUTABLE file of the same name. Reentrant.
609 **
610 ** @param [u] Pfilename [AjPStr*] Filename in AjStr, replaced by full pathname
611 ** @param [r] env [char* const[]] Environment
612 ** @return [AjBool] True if executable found, false otherwise
613 **
614 ** @release 5.0.0
615 ** @@
616 ******************************************************************************/
617 
ajSysFileWhichEnv(AjPStr * Pfilename,char * const env[])618 AjBool ajSysFileWhichEnv(AjPStr *Pfilename, char * const env[])
619 {
620     ajint count;
621     char *p = NULL;
622     const char *cp;
623     AjPStr tname = NULL;
624     AjPStr fname = NULL;
625     AjPStr path  = NULL;
626     const char   *save = NULL;
627     AjPStr buf   = NULL;
628     AjPStr tmp   = NULL;
629 
630 
631     buf   = ajStrNew();
632     tname = ajStrNew();
633     tmp   = ajStrNew();
634     ajStrAssignS(&tname,*Pfilename);
635 
636     fname = ajStrNew();
637     path  = ajStrNew();
638 
639     ajFilenameTrimPath(&tname);
640 
641 #ifdef WIN32
642     ajStrAppendC(&tname,".exe");
643 #endif
644 
645     ajDebug("ajSysFileWhichEnv '%S' => %S\n", *Pfilename, tname);
646 
647     count = 0;
648     while(env[count]!=NULL)
649     {
650 	if(!(*env[count]))
651 	    break;
652 
653 	/*ajDebug("  env[%d] '%s'\n", count, env[count]);*/
654 
655 #ifndef WIN32
656 	if(!strncmp("PATH=",env[count],5))
657 #else
658 	if(!strnicmp("PATH=",env[count],5))
659 #endif
660 	    break;
661 
662 	++count;
663     }
664 
665    /* ajDebug("PATH  env[%d] '%s'\n", count, env[count]);*/
666 
667     if(env[count]==NULL || !(*env[count]))
668     {
669 	ajStrDel(&fname);
670 	ajStrDel(&tname);
671 	ajStrDel(&path);
672 	ajStrDel(&buf);
673 	ajStrDel(&tmp);
674 	return ajFalse;
675     }
676 
677     ajStrAssignC(&path, env[count]);
678     cp = ajStrGetPtr(path);
679     cp += 5;
680     ajStrAssignC(&tmp,cp);
681 
682     /*ajDebug("tmp '%S' save '%S' buf '%S'\n", tmp, save, buf);*/
683 
684     p = ajSysFuncStrtokR(ajStrGetuniquePtr(&tmp),PATH_SEPARATOR,&save,&buf);
685 
686     if(p==NULL)
687     {
688 	ajStrDel(&fname);
689 	ajStrDel(&tname);
690 	ajStrDel(&path);
691 	ajStrDel(&buf);
692 	ajStrDel(&tmp);
693 	return ajFalse;
694     }
695 
696 
697     ajFmtPrintS(&fname,"%s%s%S",p,SLASH_STRING,tname);
698 
699     while(!ajFilenameExistsExec(fname))
700     {
701 	if((p = ajSysFuncStrtokR(NULL,PATH_SEPARATOR,&save,&buf))==NULL)
702 	{
703 	    ajStrDel(&fname);
704 	    ajStrDel(&tname);
705 	    ajStrDel(&path);
706 	    ajStrDel(&buf);
707 	    ajStrDel(&tmp);
708 	    return ajFalse;
709 	}
710 
711 	ajFmtPrintS(&fname,"%s%s%S",p,SLASH_STRING,tname);
712     }
713 
714 
715     ajStrAssignS(Pfilename,fname);
716     ajDebug("ajSysFileWhichEnv returns '%S'\n", *Pfilename);
717 
718     ajStrDel(&fname);
719     ajStrDel(&tname);
720     ajStrDel(&path);
721     ajStrDel(&buf);
722     ajStrDel(&tmp);
723 
724     return ajTrue;
725 }
726 
727 
728 
729 
730 /* @func ajSysGetHomedir ******************************************************
731 **
732 ** Get the home directory of the current user
733 **
734 ** @return [char*] Home directory or NULL
735 **
736 ** @release 6.3.0
737 ** @@
738 ******************************************************************************/
739 
ajSysGetHomedir(void)740 char* ajSysGetHomedir(void)
741 {
742     char *hdir = NULL;
743 #ifndef WIN32
744     char *p = NULL;
745 
746     if(!(p = getenv("HOME")))
747         return NULL;
748 
749     hdir = ajCharNewC(p);
750 #else
751     TCHAR wpath[MAX_PATH];
752     HRESULT ret;
753 
754     /* Replace with SHGetKnownFolderPath when XP is no longer supported */
755     ret = SHGetFolderPath(NULL,CSIDL_PROFILE,NULL,0,wpath);
756 
757     if(ret != S_OK)
758         return NULL;
759 
760     hdir = ajCharNewC(wpath);
761 #endif
762 
763     return hdir;
764 }
765 
766 
767 
768 
769 /* @func ajSysGetHomedirFromName **********************************************
770 **
771 ** Get a home directory location from  a username
772 **
773 ** @param [r] username [const char*] Username
774 ** @return [char*] Home directory or NULL
775 **
776 ** @release 6.3.0
777 ** @@
778 ******************************************************************************/
779 
ajSysGetHomedirFromName(const char * username)780 char* ajSysGetHomedirFromName(const char *username)
781 {
782     char *hdir = NULL;
783 #ifndef WIN32
784     struct passwd *pass = NULL;
785 
786 
787     pass = getpwnam(username);
788 
789     if(!pass)
790         return NULL;
791 
792     hdir = ajCharNewC(pass->pw_dir);
793 #else
794     LPTSTR domainname = NULL;
795     LPTSTR localsvr   = NULL;
796     DWORD dnsize  = 0;
797     PSID psid     = NULL;
798     DWORD sidsize = 0;
799 
800     SID_NAME_USE sidtype;
801 
802     LPTSTR strsid = NULL;
803     AjPStr subkey = NULL;
804 
805     DWORD hdbuffsize = MAX_PATH;
806     char hdbuff[MAX_PATH];
807 
808     LONG ret;
809     HKEY hkey = NULL;
810 
811     if(!LookupAccountName(localsvr, username, psid, &sidsize, domainname,
812 			  &dnsize, &sidtype))
813     {
814         if(GetLastError() == ERROR_NONE_MAPPED)
815         {
816             ajWarn("No Windows username found for '%s'", username);
817             return NULL;
818         }
819         else if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
820         {
821             psid = (LPTSTR) LocalAlloc(LPTR,sidsize * sizeof(TCHAR));
822             if(!psid)
823             {
824                 ajWarn("ajSysLookupAccount: SID allocation failure");
825                 return NULL;
826             }
827 
828             domainname = (LPTSTR) LocalAlloc(LPTR, dnsize * sizeof(TCHAR));
829             if(!domainname)
830             {
831                 ajWarn("ajSysLookupAccount: Domain allocation failure");
832                 LocalFree(psid);
833                 return NULL;
834             }
835 
836             if(!LookupAccountName(localsvr, username, psid, &sidsize,
837 				  domainname, &dnsize, &sidtype))
838             {
839                 ajWarn("LookupAccountName failed with %d", GetLastError());
840                 LocalFree(psid);
841                 LocalFree(domainname);
842                 return NULL;
843             }
844         }
845         else
846         {
847             ajWarn("General LookupAccountName failure with %d", GetLastError());
848             return NULL;
849         }
850     }
851 
852 
853     if(!ConvertSidToStringSid(psid, &strsid))
854     {
855         LocalFree(psid);
856 
857         return NULL;
858     }
859 
860     LocalFree(psid);
861 
862     subkey = ajStrNew();
863 
864     ajFmtPrintS(&subkey,"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"
865                 "ProfileList\\%s",strsid);
866 
867     LocalFree(strsid);
868 
869     ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,ajStrGetPtr(subkey),(DWORD) 0,
870 		       KEY_QUERY_VALUE,&hkey);
871 
872     ajStrDel(&subkey);
873 
874     if(ret != ERROR_SUCCESS)
875         return NULL;
876 
877     ret = RegQueryValueEx(hkey,"ProfileImagePath",NULL,NULL,(LPBYTE)hdbuff,
878 			  &hdbuffsize);
879 
880     if(ret != ERROR_SUCCESS)
881         return NULL;
882 
883     ret = RegCloseKey(hkey);
884 
885     if(ret != ERROR_SUCCESS)
886         return NULL;
887 
888     hdir = ajCharNewC(hdbuff);
889 #endif
890 
891 
892     return hdir;
893 }
894 
895 
896 
897 
898 /* @section Wrappers to commands **********************************************
899 **
900 ** Functions for invoking commands
901 **
902 ** @fdata [none]
903 ** @fcategory misc
904 **
905 ** @nam3rule  Command          Execute the equivalent of a command
906 ** @nam4rule  CommandClear     Execute a clear screen command
907 ** @nam4rule  CommandCopy      Execute a copy command
908 ** @nam4rule  CommandMakedir   Execute a make directory command
909 ** @nam4rule  CommandRemove    Execute a remove file command
910 ** @nam4rule  CommandRemovedir Execute a remove directory command
911 ** @nam4rule  CommandRename    Execute a fle rename command
912 ** @suffix    C            Accept C character string parameters
913 ** @suffix    S            Accept string object parameters
914 **
915 ** @argrule C name [const char*] Filename or directory name
916 ** @argrule S strname [const AjPStr] Filename or directory name
917 ** @argrule CopyC name2 [const char*] Destination filename
918 ** @argrule CopyS strname2 [const AjPStr] Destination filename
919 ** @argrule RenameC name2 [const char*] Destination filename
920 ** @argrule RenameS strname2 [const AjPStr] Destination filename
921 **
922 ** @valrule * [AjBool] True on success
923 **
924 ******************************************************************************/
925 
926 
927 
928 
929 /* @func ajSysCommandCopyC ****************************************************
930 **
931 ** Copy a file
932 **
933 ** @param [r] name  [const char*] Source filename
934 ** @param [r] name2 [const char*] Target filename
935 ** @return [AjBool] True on success
936 **
937 **
938 ** @release 6.3.0
939 ******************************************************************************/
940 
ajSysCommandCopyC(const char * name,const char * name2)941 AjBool ajSysCommandCopyC(const char* name, const char* name2)
942 {
943     int from;
944     int to;
945     int n;
946     int nw;
947     char cbuf[1024];
948     char *buf;
949 
950     from = open(name, O_RDONLY);
951     if(from < 0)
952     {
953         ajErr("Unable to copy '%s' error %d: %s",
954               name, errno, strerror(errno));
955         return ajFalse;
956     }
957 
958     to = open(name2, O_WRONLY|O_CREAT, 0644);
959     if(to < 0)
960     {
961         ajErr("Unable to copy to '%s' error %d: %s",
962               name2, errno, strerror(errno));
963         return ajFalse;
964     }
965 
966     while((n = read(from, cbuf, sizeof(cbuf))) > 0)
967     {
968         buf = cbuf;
969         do
970         {
971             nw = write(to, buf, n);
972             if(nw == n)
973                 break;
974             if(nw > 0)
975             {
976                 buf += nw;
977                 n -= nw;
978             }
979         } while (nw >= 0 || errno == EINTR);
980         if(nw < 0)
981         {
982             ajErr("Write to %s failed, error:%d %s",
983                   name2, errno, strerror(errno));
984             return ajFalse;
985         }
986     }
987 
988     close(from);
989     close(to);
990 
991     return ajTrue;
992 }
993 
994 
995 
996 
997 /* @func ajSysCommandCopyS ****************************************************
998 **
999 ** Copy a file
1000 **
1001 ** @param [r] strname  [const AjPStr] Source filename
1002 ** @param [r] strname2 [const AjPStr] Target filename
1003 ** @return [AjBool] True on success
1004 **
1005 **
1006 ** @release 6.3.0
1007 ******************************************************************************/
1008 
ajSysCommandCopyS(const AjPStr strname,const AjPStr strname2)1009 AjBool ajSysCommandCopyS(const AjPStr strname, const AjPStr strname2)
1010 {
1011     return ajSysCommandCopyC(MAJSTRGETPTR(strname), MAJSTRGETPTR(strname2));
1012 }
1013 
1014 
1015 
1016 
1017 /* @func ajSysCommandMakedirC *************************************************
1018 **
1019 ** Delete a file
1020 **
1021 ** @param [r] name [const char*] Directory
1022 ** @return [AjBool] True on success
1023 **
1024 **
1025 ** @release 6.3.0
1026 ******************************************************************************/
1027 
ajSysCommandMakedirC(const char * name)1028 AjBool ajSysCommandMakedirC(const char* name)
1029 {
1030 #ifndef WIN32
1031     if(!mkdir(name, 0775))
1032         return ajTrue;
1033 #else
1034     if(!_mkdir(name))
1035         return ajTrue;
1036 #endif
1037 
1038     ajErr("Unable to make directory '%s' (%d): %s",
1039           name, errno, strerror(errno));
1040 
1041     return ajFalse;
1042 }
1043 
1044 
1045 
1046 
1047 /* @func ajSysCommandMakedirS *************************************************
1048 **
1049 ** Delete a file
1050 **
1051 ** @param [r] strname [const AjPStr] Directory
1052 ** @return [AjBool] True on success
1053 **
1054 **
1055 ** @release 6.3.0
1056 ******************************************************************************/
1057 
ajSysCommandMakedirS(const AjPStr strname)1058 AjBool ajSysCommandMakedirS(const AjPStr strname)
1059 {
1060     return ajSysCommandMakedirC(MAJSTRGETPTR(strname));
1061 }
1062 
1063 
1064 
1065 
1066 /* @func ajSysCommandRemoveC **************************************************
1067 **
1068 ** Delete a file
1069 **
1070 ** @param [r] name [const char*] Filename
1071 ** @return [AjBool] True on success
1072 **
1073 **
1074 ** @release 6.3.0
1075 ******************************************************************************/
1076 
ajSysCommandRemoveC(const char * name)1077 AjBool ajSysCommandRemoveC(const char* name)
1078 {
1079     return ajSysFileUnlinkC(name);
1080 }
1081 
1082 
1083 
1084 
1085 /* @func ajSysCommandRemoveS **************************************************
1086 **
1087 ** Delete a file
1088 **
1089 ** @param [r] strname [const AjPStr] Filename
1090 ** @return [AjBool] True on success
1091 **
1092 **
1093 ** @release 6.3.0
1094 ******************************************************************************/
1095 
ajSysCommandRemoveS(const AjPStr strname)1096 AjBool ajSysCommandRemoveS(const AjPStr strname)
1097 {
1098     return ajSysFileUnlinkC(MAJSTRGETPTR(strname));
1099 }
1100 
1101 
1102 
1103 
1104 /* @func ajSysCommandRemovedirC ***********************************************
1105 **
1106 ** Delete a file
1107 **
1108 ** @param [r] name [const char*] Directory
1109 ** @return [AjBool] True on success
1110 **
1111 **
1112 ** @release 6.3.0
1113 ******************************************************************************/
1114 
ajSysCommandRemovedirC(const char * name)1115 AjBool ajSysCommandRemovedirC(const char* name)
1116 {
1117     AjPStr cmdstr = NULL;
1118     AjBool ret;
1119 
1120     ret = ajTrue;
1121 
1122     cmdstr = ajStrNewC(name);
1123     if(!ajFilenameExistsDir(cmdstr))
1124     {
1125         if(!ajFilenameExists(cmdstr))
1126             ajErr("Unable to remove directory '%S' not found", cmdstr);
1127         else
1128             ajErr("Unable to remove directory '%S' not a directory", cmdstr);
1129 
1130         return ajFalse;
1131     }
1132 
1133     ret = ajSysFileRmrfC(name);
1134 
1135     ajStrDel(&cmdstr);
1136 
1137     return ret;
1138 }
1139 
1140 
1141 
1142 
1143 /* @func ajSysCommandRemovedirS ***********************************************
1144 **
1145 ** Delete a file
1146 **
1147 ** @param [r] strname [const AjPStr] Directory
1148 ** @return [AjBool] True on success
1149 **
1150 **
1151 ** @release 6.3.0
1152 ******************************************************************************/
1153 
ajSysCommandRemovedirS(const AjPStr strname)1154 AjBool ajSysCommandRemovedirS(const AjPStr strname)
1155 {
1156     return ajSysCommandRemovedirC(MAJSTRGETPTR(strname));
1157 }
1158 
1159 
1160 
1161 
1162 /* @func ajSysCommandRenameC **************************************************
1163 **
1164 ** Rename a file
1165 **
1166 ** @param [r] name  [const char*] Source filename
1167 ** @param [r] name2 [const char*] Target filename
1168 ** @return [AjBool] True on success
1169 **
1170 **
1171 ** @release 6.3.0
1172 ******************************************************************************/
1173 
ajSysCommandRenameC(const char * name,const char * name2)1174 AjBool ajSysCommandRenameC(const char* name, const char* name2)
1175 {
1176     if(!rename(name, name2))
1177         return ajTrue;
1178 
1179     ajErr("File rename failed (%d): %s",
1180           errno, strerror(errno));
1181 
1182     return ajFalse;
1183 }
1184 
1185 
1186 
1187 
1188 /* @func ajSysCommandRenameS **************************************************
1189 **
1190 ** Rename a file
1191 **
1192 ** @param [r] strname  [const AjPStr] Source filename
1193 ** @param [r] strname2 [const AjPStr] Target filename
1194 ** @return [AjBool] True on success
1195 **
1196 **
1197 ** @release 6.3.0
1198 ******************************************************************************/
1199 
ajSysCommandRenameS(const AjPStr strname,const AjPStr strname2)1200 AjBool ajSysCommandRenameS(const AjPStr strname, const AjPStr strname2)
1201 {
1202     return ajSysCommandRenameC(MAJSTRGETPTR(strname), MAJSTRGETPTR(strname2));
1203 }
1204 
1205 
1206 
1207 
1208 /* @section Wrappers to C functions *******************************************
1209 **
1210 ** Functions for calling or substituting C-functions.
1211 **
1212 ** @fdata [none]
1213 ** @fcategory misc
1214 **
1215 ** @nam3rule  Func         Replacement for C-function.
1216 ** @nam4rule  FuncStrtok   strtok that doesn't corrupt the source string
1217 ** @nam5rule  FuncStrtokR  Reentrant version.
1218 ** @nam4rule  FuncFgets    An fgets replacement that will cope with Mac OSX
1219 **                          files
1220 ** @nam4rule  FuncFopen    An fopen replacement to cope with cygwin and windows
1221 ** @nam4rule  FuncFdopen   Calls non-ANSI fdopen.
1222 ** @nam4rule  FuncSocket   A socket function fore UNIX and Windows
1223 ** @nam4rule  FuncStrdup   Duplicate BSD strdup function for very strict ANSI
1224 ** @nam3rule  System       Execute a command line as if from the C shell
1225 ** @nam4rule  SystemEnv    Execute command line and pass the environment
1226 **                         received from main to extract the PATH list
1227 ** @nam4rule  SystemOut    Execute command line and write standard output to
1228 **                         a named file
1229 ** @suffix    C            Accept C character string parameters
1230 ** @suffix    S            Accept string object parameters
1231 **
1232 ** @argrule Fdopen filedes [ajint] file descriptor
1233 ** @argrule Fdopen mode [const char*] file mode
1234 ** @argrule Fgets buf [char*] buffer
1235 ** @argrule Fgets size [int] maximum length to read
1236 ** @argrule Fgets fp [FILE*] stream
1237 ** @argrule Fopen name [const char*] Name of file to open
1238 ** @argrule Fopen flags [const char*] Read/write/append flags
1239 ** @argrule Socket domain [int] Domain
1240 ** @argrule Socket type [int] Type
1241 ** @argrule Socket protocol [int] Protocol
1242 ** @argrule Strdup dupstr [const char*] String to duplicate
1243 ** @argrule Strtok srcstr [const char*] source string
1244 ** @argrule Strtok delimstr [const char*] delimiter string
1245 ** @argrule R ptrptr [const char**] Saved pointer
1246 ** @argrule R buf [AjPStr*] Independent buffer provided by caller
1247 ** @argrule System cmdline [const AjPStr] The command line
1248 ** @argrule SystemEnv env [char* const[]] Environment variables and values
1249 ** @argrule SystemOut outfname [const AjPStr] The output file name
1250 **
1251 ** @valrule Fdopen [FILE*] C open file
1252 ** @valrule Fgets [char*] Buffer on success
1253 ** @valrule Fopen [FILE*] C open file
1254 ** @valrule Strdup [char*] New string
1255 ** @valrule Strtok [char*] New string
1256 ** @valrule Socket [SOCKRET] Socketvoid
1257 ** @valrule System [void]
1258 **
1259 ******************************************************************************/
1260 
1261 
1262 
1263 
1264 /* @func ajSysFuncFdopen ******************************************************
1265 **
1266 ** Place non-ANSI fdopen here
1267 **
1268 ** @param [r] filedes [ajint] file descriptor
1269 ** @param [r] mode [const char*] file mode
1270 ** @return [FILE*] file pointer
1271 **
1272 ** @release 5.0.0
1273 ** @@
1274 ******************************************************************************/
1275 
ajSysFuncFdopen(ajint filedes,const char * mode)1276 FILE* ajSysFuncFdopen(ajint filedes, const char *mode)
1277 {
1278     FILE *ret;
1279 
1280     ret = fdopen(filedes,mode);
1281     if(ret)
1282         errno = 0;              /* set to "Illegal seek" on some systems */
1283 
1284     return ret;
1285 }
1286 
1287 
1288 
1289 
1290 /* @func ajSysFuncFgets *******************************************************
1291 **
1292 ** An fgets replacement that will cope with Mac OSX <CR> files
1293 **
1294 ** @param [w] buf [char*] buffer
1295 ** @param [r] size [int] maximum length to read
1296 ** @param [u] fp [FILE*] stream
1297 **
1298 ** @return [char*] buf or NULL
1299 **
1300 ** @release 5.0.0
1301 ** @@
1302 ******************************************************************************/
1303 
ajSysFuncFgets(char * buf,int size,FILE * fp)1304 char* ajSysFuncFgets(char *buf, int size, FILE *fp)
1305 {
1306 #ifdef __ppc__
1307     int c = 0;
1308     char *p;
1309     int cnt;
1310 
1311     p = buf;
1312     if(!size || size<0)
1313         return NULL;
1314 
1315     cnt = 0;
1316 
1317     while(cnt!=size-1)
1318     {
1319 	c = getc(fp);
1320 	if(c==EOF || c=='\r' || c=='\n')
1321 	    break;
1322         *(p++) = c;
1323         ++cnt;
1324     }
1325 
1326 
1327     *p ='\0';
1328 
1329     if(c==EOF && !cnt)
1330 	return NULL;
1331 
1332     if(cnt == size-1)
1333         return buf;
1334 
1335     if(c=='\r' || c=='\n')
1336     {
1337 	if(c=='\r' && cnt<size-2)
1338 	{
1339 	    if((c=getc(fp)) == '\n')
1340 		*(p++) = '\r';
1341 	    else
1342 		ungetc(c,fp);
1343 	}
1344 	*(p++) = '\n';
1345     }
1346 
1347     *p = '\0';
1348 
1349     return buf;
1350 #else
1351     return fgets(buf,size,fp);
1352 #endif
1353 }
1354 
1355 
1356 
1357 
1358 /* @func ajSysFuncFopen *******************************************************
1359 **
1360 ** An fopen replacement to cope with cygwin and windows
1361 **
1362 ** @param [r] name [const char*] file to open
1363 ** @param [r] flags [const char*] r/w/a flags
1364 **
1365 ** @return [FILE*] file or NULL
1366 **
1367 ** @release 5.0.0
1368 ** @@
1369 ******************************************************************************/
1370 
ajSysFuncFopen(const char * name,const char * flags)1371 FILE* ajSysFuncFopen(const char *name, const char *flags)
1372 {
1373     FILE   *ret  = NULL;
1374 #ifdef __CYGWIN__
1375     AjPStr fname = NULL;
1376 #endif
1377 
1378 #ifdef __CYGWIN__
1379     if(*(name+1) == ':')
1380     {
1381 	fname = ajStrNew();
1382 	ajFmtPrintS(&fname,"/cygdrive/%c/%s",*name,name+2);
1383 	ret = fopen(ajStrGetPtr(fname),flags);
1384 	ajStrDel(&fname);
1385     }
1386     else
1387       ret = fopen(name,flags);
1388 #else
1389 	ret = fopen(name,flags);
1390 #endif
1391 
1392 	return ret;
1393 }
1394 
1395 
1396 
1397 
1398 /* @func ajSysFuncSocket ******************************************************
1399 **
1400 ** Socket function coping with UNIX and WIN32
1401 **
1402 ** @param [r] domain [int] Domain
1403 ** @param [r] type [int] Type
1404 ** @param [r] protocol [int] Protocol
1405 ** @return [SOCKRET] Universal (UNIX/WIN32) socket value
1406 **
1407 ** @release 6.3.0
1408 ** @@
1409 ******************************************************************************/
1410 
ajSysFuncSocket(int domain,int type,int protocol)1411 SOCKRET ajSysFuncSocket(int domain, int type, int protocol)
1412 {
1413     SOCKRET ret;
1414 
1415 #ifndef WIN32
1416     ret = socket(domain, type, protocol);
1417 #else
1418     ret = WSASocket(domain, type, protocol,NULL,0,0);
1419 #endif
1420 
1421     return ret;
1422 }
1423 
1424 
1425 
1426 
1427 /* @func ajSysFuncStrdup ******************************************************
1428 **
1429 ** Duplicate BSD strdup function for very strict ANSI compilers
1430 **
1431 ** @param [r] dupstr [const char*] string to duplicate
1432 ** @return [char*] Text string as for strdup
1433 **
1434 ** @release 5.0.0
1435 ** @@
1436 ******************************************************************************/
1437 
ajSysFuncStrdup(const char * dupstr)1438 char* ajSysFuncStrdup(const char *dupstr)
1439 {
1440     static char *p;
1441 
1442     AJCNEW(p, strlen(dupstr)+1);
1443     strcpy(p,dupstr);
1444 
1445     return p;
1446 }
1447 
1448 
1449 
1450 
1451 /* @func ajSysFuncStrtok ******************************************************
1452 **
1453 ** strtok that doesn't corrupt the source string
1454 **
1455 ** @param [r] srcstr [const char*] source string
1456 ** @param [r] delimstr [const char*] delimiter string
1457 **
1458 ** @return [char*] pointer or NULL when nothing is found
1459 **
1460 ** @release 5.0.0
1461 ** @@
1462 ******************************************************************************/
1463 
ajSysFuncStrtok(const char * srcstr,const char * delimstr)1464 char* ajSysFuncStrtok(const char *srcstr, const char *delimstr)
1465 {
1466     ajint len;
1467 
1468     if(srcstr)
1469     {
1470 	if(!sysTokRets)
1471 	{
1472 	    sysTokSou  = ajStrNew();
1473 	    sysTokRets = ajStrNew();
1474 	}
1475 	ajStrAssignC(&sysTokSou,srcstr);
1476 	sysTokp = ajStrGetPtr(sysTokSou);
1477     }
1478 
1479     if(!*sysTokp)
1480 	return NULL;
1481 
1482     len = strspn(sysTokp,delimstr);		/* skip over delimiters */
1483     sysTokp += len;
1484     if(!*sysTokp)
1485 	return NULL;
1486 
1487     len = strcspn(sysTokp,delimstr);		/* count non-delimiters */
1488     ajStrAssignSubC(&sysTokRets,sysTokp,0,len-1);
1489     sysTokp += len;		  /* skip over first delimiter only */
1490 
1491     return ajStrGetuniquePtr(&sysTokRets);
1492 }
1493 
1494 
1495 
1496 
1497 /* @func ajSysFuncStrtokR *****************************************************
1498 **
1499 ** Reentrant strtok that doesn't corrupt the source string.
1500 ** This function uses a string buffer provided by the caller.
1501 **
1502 ** @param [u] srcstr  [const char*] source string
1503 ** @param [r] delimstr [const char*] delimiter string
1504 ** @param [u] ptrptr [const char**] ptr save
1505 ** @param [w] buf [AjPStr*] result buffer
1506 **
1507 ** @return [char*] pointer or NULL
1508 **
1509 ** @release 5.0.0
1510 ** @@
1511 ******************************************************************************/
1512 
ajSysFuncStrtokR(const char * srcstr,const char * delimstr,const char ** ptrptr,AjPStr * buf)1513 char* ajSysFuncStrtokR(const char *srcstr, const char *delimstr,
1514 		       const char **ptrptr,AjPStr *buf)
1515 {
1516     const char *p;
1517     ajint len;
1518 
1519     if(!*buf)
1520 	*buf = ajStrNew();
1521 
1522     if(srcstr!=NULL)
1523 	p = srcstr;
1524     else
1525 	p = *ptrptr;
1526 
1527     if(!*p)
1528 	return NULL;
1529 
1530     len = strspn(p,delimstr);			/* skip over delimiters */
1531     p += len;
1532     if(!*p)
1533 	return NULL;
1534 
1535     len = strcspn(p,delimstr);			/* count non-delimiters */
1536     ajStrAssignSubC(buf,p,0,len-1);
1537     p += len;			       /* skip to first delimiter */
1538 
1539     *ptrptr = p;
1540 
1541     return ajStrGetuniquePtr(buf);
1542 }
1543 
1544 
1545 
1546 
1547 /* @section executing commands ************************************************
1548 **
1549 ** Functions for executing commands
1550 **
1551 ** @fdata [none]
1552 ** @fcategory misc
1553 **
1554 ** @nam3rule  Exec          Execute the equivalent of a command
1555 ** @nam4rule  Env           Execute under local environment
1556 ** @nam4rule  Locale        Execute under defined locale
1557 ** @nam4rule  Outname       Write to output file
1558 ** @nam4rule  Redirect      Redirect standard input and output
1559 **
1560 ** @suffix    Append       Append to output file
1561 ** @suffix    Err          Write standard error to output file
1562 ** @suffix    Path         Look for progam name in current PATH
1563 ** @suffix    C            Accept C character string parameters
1564 ** @suffix    S            Accept string object parameters
1565 **
1566 ** @argrule   C        cmdlinetxt  [const char*] The command line
1567 ** @argrule   S        cmdline     [const AjPStr] The command line
1568 ** @argrule   Env      env         [char* const[]] The environment
1569 ** @argrule   LocaleC  localetxt   [const char*] The locale value
1570 ** @argrule   LocaleS  localestr   [const AjPStr] The locale value
1571 ** @argrule   AppendC  outfnametxt [const char*] The output file name
1572 ** @argrule   AppendS  outfname    [const AjPStr] The output file name
1573 ** @argrule   ErrC     outfnametxt [const char*] The output file name
1574 ** @argrule   ErrS     outfname    [const AjPStr] The output file name
1575 ** @argrule   OutnameC outfnametxt [const char*] The output file name
1576 ** @argrule   OutnameS outfname    [const AjPStr] The output file name
1577 ** @argrule   Redirect pipeto      [int**] pipes to the process
1578 ** @argrule   Redirect pipefrom    [int**] pipes from the process
1579 **
1580 ** @valrule Exec [ajint] Exit status
1581 ** @valrule *Redirect [AjBool] True on success
1582 **
1583 ******************************************************************************/
1584 
1585 
1586 
1587 
1588 /* @func ajSysExecC ***********************************************************
1589 **
1590 ** Exec a command line as if from the C shell
1591 **
1592 ** The exec'd program is passed a new argv array in argptr
1593 **
1594 ** @param [r] cmdlinetxt [const char*] The command line
1595 ** @return [ajint] Exit status
1596 **
1597 ** @release 6.3.0
1598 ** @@
1599 ******************************************************************************/
1600 
ajSysExecC(const char * cmdlinetxt)1601 ajint ajSysExecC(const char* cmdlinetxt)
1602 {
1603 #ifndef WIN32
1604     pid_t pid;
1605     pid_t retval;
1606     ajint status = 0;
1607     char *pgm;
1608     char **argptr;
1609     ajint i;
1610 
1611     AjPStr pname = NULL;
1612 
1613     ajDebug("ajSysExecC '%s'\n", cmdlinetxt);
1614 
1615     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
1616 	return -1;
1617 
1618     pname = ajStrNewC(pgm);
1619 
1620     pid=fork();
1621 
1622     if(pid==-1)
1623 	ajFatal("System fork failed");
1624 
1625     if(pid)
1626     {
1627 	while((retval=waitpid(pid,&status,0))!=pid)
1628 	{
1629 	    if(retval == -1)
1630 		if(errno != EINTR)
1631 		    break;
1632 	}
1633     }
1634     else
1635     {
1636 	execv(ajStrGetPtr(pname), argptr);
1637 	ajExitAbort();			/* just in case */
1638     }
1639 
1640     ajStrDel(&pname);
1641 
1642     i = 0;
1643     while(argptr[i])
1644     {
1645 	AJFREE(argptr[i]);
1646 	++i;
1647     }
1648     AJFREE(argptr);
1649 
1650     AJFREE(pgm);
1651 
1652 #else
1653     PROCESS_INFORMATION procInfo;
1654     STARTUPINFO startInfo;
1655     ajint status = 0;
1656 
1657     ajDebug ("Launching process '%s'\n", cmdlinetxt);
1658 
1659     ZeroMemory(&startInfo, sizeof(startInfo));
1660     startInfo.cb = sizeof(startInfo);
1661 
1662     if(!CreateProcess(NULL, (char *)cmdlinetxt, NULL, NULL, FALSE,
1663                       CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo))
1664       ajFatal("CreateProcess failed: %s", cmdlinetxt);
1665 
1666     if(!WaitForSingleObject(procInfo.hProcess, INFINITE))
1667         status = 0;
1668     else
1669         status = -1;
1670 
1671     CloseHandle(procInfo.hProcess);
1672     CloseHandle(procInfo.hThread);
1673 
1674 #endif
1675 
1676     return status;
1677 }
1678 
1679 
1680 
1681 
1682 /* @func ajSysExecS ***********************************************************
1683 **
1684 ** Exec a command line as if from the C shell
1685 **
1686 ** The exec'd program is passed a new argv array in argptr
1687 **
1688 ** @param [r] cmdline [const AjPStr] The command line
1689 ** @return [ajint] Exit status
1690 **
1691 ** @release 6.3.0
1692 ** @@
1693 ******************************************************************************/
1694 
ajSysExecS(const AjPStr cmdline)1695 ajint ajSysExecS(const AjPStr cmdline)
1696 {
1697     return ajSysExecC(MAJSTRGETPTR(cmdline));
1698 }
1699 
1700 
1701 
1702 
1703 /* @func ajSysExecEnvC ********************************************************
1704 **
1705 ** Exec a command line as if from the C shell
1706 **
1707 ** This routine must be passed the environment received from
1708 ** main(ajint argc, char **argv, char **env)
1709 ** The environment is used to extract the PATH list (see ajWhich)
1710 **
1711 ** Note that the environment is passed through unaltered. The exec'd
1712 ** program is passed a new argv array
1713 **
1714 ** @param [r] cmdlinetxt [const char*] The command line
1715 ** @param [r] env [char* const[]] The environment
1716 ** @return [ajint] Exit status
1717 **
1718 ** @release 6.3.0
1719 ** @@
1720 ******************************************************************************/
1721 
ajSysExecEnvC(const char * cmdlinetxt,char * const env[])1722 ajint ajSysExecEnvC(const char* cmdlinetxt, char * const env[])
1723 {
1724     ajint status = 0;
1725 
1726 #ifndef WIN32
1727     pid_t pid;
1728     pid_t retval;
1729     char *pgm = NULL;
1730     char **argptr = NULL;
1731     ajint i;
1732 
1733     AjPStr pname = NULL;
1734 
1735     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
1736 	return -1;
1737 
1738     pname = ajStrNew();
1739 
1740     ajDebug("ajSysSystemEnv '%s' %s \n", pgm, cmdlinetxt);
1741     ajStrAssignC(&pname, pgm);
1742     if(!ajSysFileWhichEnv(&pname, env))
1743 	ajFatal("cannot find program '%S'", pname);
1744 
1745     ajDebug("ajSysSystemEnv %S = %s\n", pname, cmdlinetxt);
1746     for (i=0;argptr[i]; i++)
1747     {
1748 	ajDebug("%4d '%s'\n", i, argptr[i]);
1749     }
1750 
1751     pid = fork();
1752     if(pid==-1)
1753 	ajFatal("System fork failed");
1754 
1755     if(pid)
1756     {
1757 	while((retval=waitpid(pid,&status,0))!=pid)
1758 	{
1759 	    if(retval == -1)
1760 		if(errno != EINTR)
1761 		    break;
1762 	}
1763     }
1764     else
1765     {
1766 	execve(ajStrGetPtr(pname), argptr, env);
1767 	ajExitAbort();			/* just in case */
1768     }
1769 
1770     ajStrDel(&pname);
1771 
1772     i = 0;
1773     while(argptr[i])
1774     {
1775 	AJFREE(argptr[i]);
1776 	++i;
1777     }
1778     AJFREE(argptr);
1779 
1780     AJFREE(pgm);
1781 
1782 #endif
1783 
1784     return status;
1785 }
1786 
1787 
1788 
1789 
1790 /* @func ajSysExecEnvS ********************************************************
1791 **
1792 ** Exec a command line as if from the C shell
1793 **
1794 ** This routine must be passed the environment received from
1795 ** main(ajint argc, char **argv, char **env)
1796 ** The environment is used to extract the PATH list (see ajWhich)
1797 **
1798 ** Note that the environment is passed through unaltered. The exec'd
1799 ** program is passed a new argv array
1800 **
1801 ** @param [r] cmdline [const AjPStr] The command line
1802 ** @param [r] env [char* const[]] The environment
1803 ** @return [ajint] Exit status
1804 **
1805 ** @release 6.3.0
1806 ** @@
1807 ******************************************************************************/
1808 
ajSysExecEnvS(const AjPStr cmdline,char * const env[])1809 ajint ajSysExecEnvS(const AjPStr cmdline, char * const env[])
1810 {
1811     return ajSysExecEnvC(MAJSTRGETPTR(cmdline), env);
1812 }
1813 
1814 
1815 
1816 
1817 /* @func ajSysExecLocaleC *****************************************************
1818 **
1819 ** Exec a command line as if from the C shell with a defined locale
1820 ** variable.
1821 **
1822 ** The exec'd program is passed a new argv array in argptr
1823 **
1824 ** @param [r] cmdlinetxt [const char*] The command line
1825 ** @param [r] localetxt [const char*] The locale value
1826 ** @return [ajint] Exit status
1827 **
1828 ** @release 6.3.0
1829 ** @@
1830 ******************************************************************************/
1831 
ajSysExecLocaleC(const char * cmdlinetxt,const char * localetxt)1832 ajint ajSysExecLocaleC(const char* cmdlinetxt, const char* localetxt)
1833 {
1834 #ifndef WIN32
1835     pid_t pid;
1836     pid_t retval;
1837     ajint status = 0;
1838     char *pgm;
1839     char **argptr;
1840     ajint i;
1841 
1842     AjPStr pname = NULL;
1843 
1844     ajDebug("ajSysExecLocaleC '%s' '%s'\n", cmdlinetxt, localetxt);
1845 
1846     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
1847 	return -1;
1848 
1849     pname = ajStrNewC(pgm);
1850 
1851     pid=fork();
1852 
1853     if(pid==-1)
1854 	ajFatal("System fork failed");
1855 
1856     if(pid)
1857     {
1858 	while((retval=waitpid(pid,&status,0))!=pid)
1859 	{
1860 	    if(retval == -1)
1861 		if(errno != EINTR)
1862 		    break;
1863 	}
1864     }
1865     else
1866     {
1867         setlocale(LC_ALL, localetxt);
1868 	execv(ajStrGetPtr(pname), argptr);
1869 	ajExitAbort();			/* just in case */
1870     }
1871 
1872     ajStrDel(&pname);
1873 
1874     i = 0;
1875     while(argptr[i])
1876     {
1877 	AJFREE(argptr[i]);
1878 	++i;
1879     }
1880     AJFREE(argptr);
1881 
1882     AJFREE(pgm);
1883 
1884 #else
1885     PROCESS_INFORMATION procInfo;
1886     STARTUPINFO startInfo;
1887     ajint status = 0;
1888 
1889     ajDebug ("Launching process '%s'\n", cmdlinetxt);
1890 
1891     ZeroMemory(&startInfo, sizeof(startInfo));
1892     startInfo.cb = sizeof(startInfo);
1893 
1894     if(!CreateProcess(NULL, (char *)cmdlinetxt, NULL, NULL, FALSE,
1895                       CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo))
1896       ajFatal("CreateProcess failed: %s", cmdlinetxt);
1897 
1898     if(!WaitForSingleObject(procInfo.hProcess, INFINITE))
1899         status = 0;
1900     else
1901         status = -1;
1902 
1903     CloseHandle(procInfo.hProcess);
1904     CloseHandle(procInfo.hThread);
1905 
1906 #endif
1907 
1908     return status;
1909 }
1910 
1911 
1912 
1913 
1914 /* @func ajSysExecLocaleS *****************************************************
1915 **
1916 ** Exec a command line as if from the C shell with a defined locale
1917 ** variable.
1918 **
1919 ** The exec'd program is passed a new argv array in argptr
1920 **
1921 ** @param [r] cmdline [const AjPStr] The command line
1922 ** @param [r] localestr [const AjPStr] The locale value
1923 ** @return [ajint] Exit status
1924 **
1925 ** @release 6.3.0
1926 ** @@
1927 ******************************************************************************/
1928 
ajSysExecLocaleS(const AjPStr cmdline,const AjPStr localestr)1929 ajint ajSysExecLocaleS(const AjPStr cmdline, const AjPStr localestr)
1930 {
1931     return ajSysExecLocaleC(MAJSTRGETPTR(cmdline), MAJSTRGETPTR(localestr));
1932 }
1933 
1934 
1935 
1936 
1937 /* @func ajSysExecOutnameC ****************************************************
1938 **
1939 ** Exec a command line as if from the C shell with standard output redirected
1940 ** to and overwriting a named file
1941 **
1942 ** The exec'd program is passed a new argv array in argptr
1943 **
1944 ** @param [r] cmdlinetxt [const char*] The command line
1945 ** @param [r] outfnametxt [const char*] The output file name
1946 ** @return [ajint] Exit status
1947 **
1948 ** @release 6.3.0
1949 ** @@
1950 ******************************************************************************/
1951 
ajSysExecOutnameC(const char * cmdlinetxt,const char * outfnametxt)1952 ajint ajSysExecOutnameC(const char* cmdlinetxt, const char* outfnametxt)
1953 {
1954 #ifndef WIN32
1955     pid_t pid;
1956     pid_t retval;
1957     ajint status;
1958     char *pgm;
1959     char **argptr;
1960     ajint i;
1961 
1962     AjPStr pname = NULL;
1963 
1964     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
1965 	return -1;
1966 
1967     pname = ajStrNew();
1968 
1969     ajStrAssignC(&pname, pgm);
1970 
1971     if(!ajSysFileWhich(&pname))
1972 	ajFatal("cannot find program '%S'", pname);
1973 
1974     fflush(stdout);
1975 
1976     pid=fork();
1977 
1978     if(pid==-1)
1979 	ajFatal("System fork failed");
1980 
1981     if(pid)
1982     {
1983 	while((retval=waitpid(pid,&status,0))!=pid)
1984 	{
1985 	    if(retval == -1)
1986 		if(errno != EINTR)
1987 		    break;
1988 	}
1989     }
1990     else
1991     {
1992 	/* this is the child process */
1993 
1994 	if(!freopen(outfnametxt, "wb", stdout))
1995 	    ajErr("Failed to redirect standard output to '%s'", outfnametxt);
1996 	execv(ajStrGetPtr(pname), argptr);
1997 	ajExitAbort();			/* just in case */
1998     }
1999 
2000     ajStrDel(&pname);
2001 
2002     i = 0;
2003     while(argptr[i])
2004     {
2005 	AJFREE(argptr[i]);
2006 	++i;
2007     }
2008     AJFREE(argptr);
2009 
2010     AJFREE(pgm);
2011 
2012 #else
2013 
2014     PROCESS_INFORMATION pinf;
2015     STARTUPINFO si;
2016     HANDLE fp;
2017     SECURITY_ATTRIBUTES sa;
2018     ajint status = 0;
2019 
2020     ajDebug ("Launching process '%s'\n", cmdlinetxt);
2021 
2022     fflush(stdout);
2023 
2024     ZeroMemory(&si, sizeof(si));
2025     si.cb = sizeof(si);
2026     si.dwFlags |= STARTF_USESTDHANDLES;
2027 
2028 
2029     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2030     sa.bInheritHandle = TRUE;
2031     sa.lpSecurityDescriptor = NULL;
2032 
2033     fp = CreateFile(TEXT(outfnametxt), GENERIC_WRITE, 0 , &sa,
2034 		    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2035 
2036     if(fp == INVALID_HANDLE_VALUE)
2037         ajFatal("Cannot open file %s\n",outfnametxt);
2038 
2039 
2040     si.hStdOutput = fp;
2041     si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
2042     si.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
2043 
2044 
2045     if(!CreateProcess(NULL, (char *) cmdlinetxt, NULL, NULL, TRUE,
2046                       CREATE_NO_WINDOW, NULL, NULL, &si, &pinf))
2047     {
2048       ajFatal("CreateProcess failed: %s", cmdlinetxt);
2049     }
2050 
2051     if(!WaitForSingleObject(pinf.hProcess, INFINITE))
2052         status = 0;
2053     else
2054         status = -1;
2055 
2056     CloseHandle(pinf.hProcess);
2057     CloseHandle(pinf.hThread);
2058 #endif
2059 
2060     return status;
2061 }
2062 
2063 
2064 
2065 
2066 /* @func ajSysExecOutnameS ****************************************************
2067 **
2068 ** Exec a command line as if from the C shell with standard output redirected
2069 ** to and overwriting a named file
2070 **
2071 ** The exec'd program is passed a new argv array in argptr
2072 **
2073 ** @param [r] cmdline [const AjPStr] The command line
2074 ** @param [r] outfname [const AjPStr] The output file name
2075 ** @return [ajint] Exit status
2076 **
2077 ** @release 6.3.0
2078 ** @@
2079 ******************************************************************************/
2080 
ajSysExecOutnameS(const AjPStr cmdline,const AjPStr outfname)2081 ajint ajSysExecOutnameS(const AjPStr cmdline, const AjPStr outfname)
2082 {
2083     return ajSysExecOutnameC(MAJSTRGETPTR(cmdline), MAJSTRGETPTR(outfname));
2084 }
2085 
2086 
2087 
2088 
2089 /* @func ajSysExecOutnameAppendC **********************************************
2090 **
2091 ** Exec a command line as if from the C shell with standard output redirected
2092 ** and appended to a named file
2093 **
2094 ** The exec'd program is passed a new argv array in argptr
2095 **
2096 ** @param [r] cmdlinetxt [const char*] The command line
2097 ** @param [r] outfnametxt [const char*] The output file name
2098 ** @return [ajint] Exit status
2099 **
2100 ** @release 6.3.0
2101 ** @@
2102 ******************************************************************************/
2103 
ajSysExecOutnameAppendC(const char * cmdlinetxt,const char * outfnametxt)2104 ajint ajSysExecOutnameAppendC(const char* cmdlinetxt, const char* outfnametxt)
2105 {
2106 #ifndef WIN32
2107     pid_t pid;
2108     pid_t retval;
2109     ajint status;
2110     char *pgm;
2111     char **argptr;
2112     ajint i;
2113 
2114     AjPStr pname = NULL;
2115 
2116     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
2117 	return -1;
2118 
2119     fflush(stdout);
2120 
2121     pname = ajStrNew();
2122 
2123     ajStrAssignC(&pname, pgm);
2124 
2125     if(!ajSysFileWhich(&pname))
2126 	ajFatal("cannot find program '%S'", pname);
2127 
2128     fflush(stdout);
2129 
2130     pid=fork();
2131 
2132     if(pid==-1)
2133 	ajFatal("System fork failed");
2134 
2135     if(pid)
2136     {
2137 	while((retval=waitpid(pid,&status,0))!=pid)
2138 	{
2139 	    if(retval == -1)
2140 		if(errno != EINTR)
2141 		    break;
2142 	}
2143     }
2144     else
2145     {
2146 	/* this is the child process */
2147 
2148 	if(!freopen(outfnametxt, "ab", stdout))
2149 	    ajErr("Failed to redirect standard output to '%s'", outfnametxt);
2150 	execv(ajStrGetPtr(pname), argptr);
2151 	ajExitAbort();			/* just in case */
2152     }
2153 
2154     ajStrDel(&pname);
2155 
2156     i = 0;
2157     while(argptr[i])
2158     {
2159 	AJFREE(argptr[i]);
2160 	++i;
2161     }
2162     AJFREE(argptr);
2163 
2164     AJFREE(pgm);
2165 
2166 #else
2167 
2168     PROCESS_INFORMATION pinf;
2169     STARTUPINFO si;
2170     HANDLE fp;
2171     SECURITY_ATTRIBUTES sa;
2172     ajint status = 0;
2173 
2174     ajDebug ("Launching process '%s'\n", cmdlinetxt);
2175 
2176     fflush(stdout);
2177 
2178     ZeroMemory(&si, sizeof(si));
2179     si.cb = sizeof(si);
2180     si.dwFlags |= STARTF_USESTDHANDLES;
2181 
2182 
2183     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2184     sa.bInheritHandle = TRUE;
2185     sa.lpSecurityDescriptor = NULL;
2186 
2187     fp = CreateFile(TEXT(outfnametxt), GENERIC_WRITE, 0 , &sa,
2188 		    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2189 
2190     if(fp == INVALID_HANDLE_VALUE)
2191         ajFatal("Cannot open file %s\n",outfnametxt);
2192 
2193     SetFilePointer(fp, 0, NULL, FILE_END);
2194 
2195     si.hStdOutput = fp;
2196     si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
2197     si.hStdError  = GetStdHandle(STD_ERROR_HANDLE);
2198 
2199 
2200     if(!CreateProcess(NULL, (char *) cmdlinetxt, NULL, NULL, TRUE,
2201                       CREATE_NO_WINDOW, NULL, NULL, &si, &pinf))
2202     {
2203       ajFatal("CreateProcess failed: %s", cmdlinetxt);
2204     }
2205 
2206     if(!WaitForSingleObject(pinf.hProcess, INFINITE))
2207         status = 0;
2208     else
2209         status = -1;
2210 
2211     CloseHandle(pinf.hProcess);
2212     CloseHandle(pinf.hThread);
2213 
2214 #endif
2215 
2216     return status;
2217 }
2218 
2219 
2220 
2221 
2222 /* @func ajSysExecOutnameAppendS **********************************************
2223 **
2224 ** Exec a command line as if from the C shell with standard output redirected
2225 ** and appended to a named file
2226 **
2227 ** The exec'd program is passed a new argv array in argptr
2228 **
2229 ** @param [r] cmdline [const AjPStr] The command line
2230 ** @param [r] outfname [const AjPStr] The output file name
2231 ** @return [ajint] Exit status
2232 **
2233 ** @release 6.3.0
2234 ** @@
2235 ******************************************************************************/
2236 
ajSysExecOutnameAppendS(const AjPStr cmdline,const AjPStr outfname)2237 ajint ajSysExecOutnameAppendS(const AjPStr cmdline, const AjPStr outfname)
2238 {
2239     return ajSysExecOutnameAppendC(MAJSTRGETPTR(cmdline),
2240                                    MAJSTRGETPTR(outfname));
2241 }
2242 
2243 
2244 
2245 
2246 /* @func ajSysExecOutnameErrC *************************************************
2247 **
2248 ** Exec a command line as if from the C shell with standard output and
2249 ** standard error redirected to and overwriting a named file
2250 **
2251 ** The exec'd program is passed a new argv array in argptr
2252 **
2253 ** @param [r] cmdlinetxt [const char*] The command line
2254 ** @param [r] outfnametxt [const char*] The output file name
2255 ** @return [ajint] Exit status
2256 **
2257 ** @release 6.3.0
2258 ** @@
2259 ******************************************************************************/
2260 
ajSysExecOutnameErrC(const char * cmdlinetxt,const char * outfnametxt)2261 ajint ajSysExecOutnameErrC(const char* cmdlinetxt, const char* outfnametxt)
2262 {
2263 #ifndef WIN32
2264     pid_t pid;
2265     pid_t retval;
2266     ajint status;
2267     char *pgm;
2268     char **argptr;
2269     ajint i;
2270     ajint id;
2271 
2272     AjPStr pname = NULL;
2273 
2274     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
2275 	return -1;
2276 
2277     pname = ajStrNew();
2278 
2279     ajStrAssignC(&pname, pgm);
2280 
2281     if(!ajSysFileWhich(&pname))
2282 	ajFatal("cannot find program '%S'", pname);
2283 
2284     fflush(stdout);
2285     fflush(stderr);
2286 
2287     pid=fork();
2288 
2289     if(pid==-1)
2290 	ajFatal("System fork failed");
2291 
2292     if(pid)
2293     {
2294 	while((retval=waitpid(pid,&status,0))!=pid)
2295 	{
2296 	    if(retval == -1)
2297 		if(errno != EINTR)
2298 		    break;
2299 	}
2300     }
2301     else
2302     {
2303 	/* this is the child process */
2304 
2305 	if(!freopen(outfnametxt, "wb", stdout))
2306 	    ajErr("Failed to redirect standard output to '%s'", outfnametxt);
2307         close(STDERR_FILENO);
2308         id = dup(fileno(stdout));
2309         if(id < 0)
2310             ajErr("Failed to duplicate file descriptor stdout, error:%d %s",
2311                   errno, strerror(errno));
2312 	execv(ajStrGetPtr(pname), argptr);
2313 	ajExitAbort();			/* just in case */
2314     }
2315 
2316     ajStrDel(&pname);
2317 
2318     i = 0;
2319     while(argptr[i])
2320     {
2321 	AJFREE(argptr[i]);
2322 	++i;
2323     }
2324     AJFREE(argptr);
2325 
2326     AJFREE(pgm);
2327 
2328 #else
2329 
2330     PROCESS_INFORMATION pinf;
2331     STARTUPINFO si;
2332     HANDLE fp;
2333     SECURITY_ATTRIBUTES sa;
2334     ajint status = 0;
2335 
2336     ajDebug ("Launching process '%s'\n", cmdlinetxt);
2337 
2338     fflush(stdout);
2339     fflush(stderr);
2340 
2341     ZeroMemory(&si, sizeof(si));
2342     si.cb = sizeof(si);
2343     si.dwFlags |= STARTF_USESTDHANDLES;
2344 
2345 
2346     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2347     sa.bInheritHandle = TRUE;
2348     sa.lpSecurityDescriptor = NULL;
2349 
2350     fp = CreateFile(TEXT(outfnametxt), GENERIC_WRITE, 0 , &sa,
2351 		    CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
2352 
2353     if(fp == INVALID_HANDLE_VALUE)
2354         ajFatal("Cannot open file %s\n",outfnametxt);
2355 
2356 
2357     si.hStdOutput = fp;
2358     si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
2359     si.hStdError  = fp;
2360 
2361 
2362     if(!CreateProcess(NULL, (char *) cmdlinetxt, NULL, NULL, TRUE,
2363                       CREATE_NO_WINDOW, NULL, NULL, &si, &pinf))
2364     {
2365       ajFatal("CreateProcess failed: %s", cmdlinetxt);
2366     }
2367 
2368     if(!WaitForSingleObject(pinf.hProcess, INFINITE))
2369         status = 0;
2370     else
2371         status = -1;
2372 
2373     CloseHandle(pinf.hProcess);
2374     CloseHandle(pinf.hThread);
2375 #endif
2376 
2377     return status;
2378 }
2379 
2380 
2381 
2382 
2383 /* @func ajSysExecOutnameErrS *************************************************
2384 **
2385 ** Exec a command line as if from the C shell with standard output and
2386 ** standard error redirected to and overwriting a named file
2387 **
2388 ** The exec'd program is passed a new argv array in argptr
2389 **
2390 ** @param [r] cmdline [const AjPStr] The command line
2391 ** @param [r] outfname [const AjPStr] The output file name
2392 ** @return [ajint] Exit status
2393 **
2394 ** @release 6.3.0
2395 ** @@
2396 ******************************************************************************/
2397 
ajSysExecOutnameErrS(const AjPStr cmdline,const AjPStr outfname)2398 ajint ajSysExecOutnameErrS(const AjPStr cmdline, const AjPStr outfname)
2399 {
2400     return ajSysExecOutnameErrC(MAJSTRGETPTR(cmdline), MAJSTRGETPTR(outfname));
2401 }
2402 
2403 
2404 
2405 
2406 /* @func ajSysExecOutnameErrAppendC *******************************************
2407 **
2408 ** Exec a command line as if from the C shell with standard output and
2409 ** standard error redirected and appended to a named file
2410 **
2411 ** The exec'd program is passed a new argv array in argptr
2412 **
2413 ** @param [r] cmdlinetxt [const char*] The command line
2414 ** @param [r] outfnametxt [const char*] The output file name
2415 ** @return [ajint] Exit status
2416 **
2417 ** @release 6.3.0
2418 ** @@
2419 ******************************************************************************/
2420 
ajSysExecOutnameErrAppendC(const char * cmdlinetxt,const char * outfnametxt)2421 ajint ajSysExecOutnameErrAppendC(const char* cmdlinetxt,
2422                                  const char* outfnametxt)
2423 {
2424 #ifndef WIN32
2425     pid_t pid;
2426     pid_t retval;
2427     ajint status = 0;
2428     char *pgm;
2429     char **argptr;
2430     ajint i;
2431     int id;
2432 
2433     AjPStr pname = NULL;
2434 
2435     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
2436 	return -1;
2437 
2438     pname = ajStrNew();
2439 
2440     ajStrAssignC(&pname, pgm);
2441 
2442     if(!ajSysFileWhich(&pname))
2443 	ajFatal("cannot find program '%S'", pname);
2444 
2445     fflush(stdout);
2446 
2447     pid=fork();
2448 
2449     if(pid==-1)
2450 	ajFatal("System fork failed");
2451 
2452     if(pid)
2453     {
2454 	while((retval=waitpid(pid,&status,0))!=pid)
2455 	{
2456 	    if(retval == -1)
2457 		if(errno != EINTR)
2458 		    break;
2459 	}
2460     }
2461     else
2462     {
2463 	/* this is the child process */
2464 
2465 	if(!freopen(outfnametxt, "ab", stdout))
2466 	    ajErr("Failed to redirect standard output and error to '%s'",
2467                   outfnametxt);
2468         close(STDERR_FILENO);
2469         id = dup(fileno(stdout));
2470         if(id < 0)
2471             ajErr("Failed to duplicate file descriptor stdout, error:%d %s",
2472                   errno, strerror(errno));
2473 	execv(ajStrGetPtr(pname), argptr);
2474 	ajExitAbort();			/* just in case */
2475     }
2476 
2477     ajStrDel(&pname);
2478 
2479     i = 0;
2480     while(argptr[i])
2481     {
2482 	AJFREE(argptr[i]);
2483 	++i;
2484     }
2485     AJFREE(argptr);
2486 
2487     AJFREE(pgm);
2488 
2489 #else
2490 
2491     PROCESS_INFORMATION pinf;
2492     STARTUPINFO si;
2493     HANDLE fp;
2494     SECURITY_ATTRIBUTES sa;
2495     ajint status = -1;
2496 
2497     ajDebug ("Launching process '%s'\n", cmdlinetxt);
2498 
2499     ZeroMemory(&si, sizeof(si));
2500     si.cb = sizeof(si);
2501     si.dwFlags |= STARTF_USESTDHANDLES;
2502 
2503 
2504     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2505     sa.bInheritHandle = TRUE;
2506     sa.lpSecurityDescriptor = NULL;
2507 
2508     fp = CreateFile(TEXT(outfnametxt), GENERIC_WRITE, 0 , &sa,
2509 		    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
2510 
2511     if(fp == INVALID_HANDLE_VALUE)
2512         ajFatal("Cannot open file %s\n",outfnametxt);
2513 
2514     SetFilePointer(fp, 0, NULL, FILE_END);
2515 
2516     si.hStdOutput = fp;
2517     si.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
2518     si.hStdError  = fp;
2519 
2520 
2521     if(!CreateProcess(NULL, (char *) cmdlinetxt, NULL, NULL, TRUE,
2522                       CREATE_NO_WINDOW, NULL, NULL, &si, &pinf))
2523     {
2524       ajFatal("CreateProcess failed: %s", cmdlinetxt);
2525     }
2526 
2527     if(!WaitForSingleObject(pinf.hProcess, INFINITE))
2528         status = 0;
2529     else
2530         status = -1;
2531 
2532     CloseHandle(pinf.hProcess);
2533     CloseHandle(pinf.hThread);
2534 #endif
2535 
2536     return status;
2537 }
2538 
2539 
2540 
2541 
2542 /* @func ajSysExecOutnameErrAppendS *******************************************
2543 **
2544 ** Exec a command line as if from the C shell with standard output and
2545 ** standard error redirected and appended to a named file
2546 **
2547 ** The exec'd program is passed a new argv array in argptr
2548 **
2549 ** @param [r] cmdline [const AjPStr] The command line
2550 ** @param [r] outfname [const AjPStr] The output file name
2551 ** @return [ajint] Exit status
2552 **
2553 ** @release 6.3.0
2554 ** @@
2555 ******************************************************************************/
2556 
ajSysExecOutnameErrAppendS(const AjPStr cmdline,const AjPStr outfname)2557 ajint ajSysExecOutnameErrAppendS(const AjPStr cmdline, const AjPStr outfname)
2558 {
2559     return ajSysExecOutnameErrAppendC(MAJSTRGETPTR(cmdline),
2560                                       MAJSTRGETPTR(outfname));
2561 }
2562 
2563 
2564 
2565 
2566 /* @func ajSysExecPathC *******************************************************
2567 **
2568 ** Exec a command line with a test for the program name in the current path
2569 **
2570 ** The exec'd program is passed a new argv array in argptr
2571 **
2572 ** @param [r] cmdlinetxt [const char*] The command line
2573 ** @return [ajint] Exit status
2574 **
2575 ** @release 6.3.0
2576 ** @@
2577 ******************************************************************************/
2578 
ajSysExecPathC(const char * cmdlinetxt)2579 ajint ajSysExecPathC(const char* cmdlinetxt)
2580 {
2581 #ifndef WIN32
2582     pid_t pid;
2583     pid_t retval;
2584     ajint status = 0;
2585     char *pgm;
2586     char **argptr;
2587     ajint i;
2588 
2589     AjPStr pname = NULL;
2590 
2591     ajDebug("ajSysExecPathS '%s'\n", cmdlinetxt);
2592 
2593     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
2594 	return -1;
2595 
2596     pname = ajStrNewC(pgm);
2597 
2598     pid=fork();
2599 
2600     if(pid==-1)
2601 	ajFatal("System fork failed");
2602 
2603     if(pid)
2604     {
2605 	while((retval=waitpid(pid,&status,0))!=pid)
2606 	{
2607 	    if(retval == -1)
2608 		if(errno != EINTR)
2609 		    break;
2610 	}
2611     }
2612     else
2613     {
2614 	execvp(ajStrGetPtr(pname), argptr);
2615 	ajExitAbort();			/* just in case */
2616     }
2617 
2618     ajStrDel(&pname);
2619 
2620     i = 0;
2621     while(argptr[i])
2622     {
2623 	AJFREE(argptr[i]);
2624 	++i;
2625     }
2626     AJFREE(argptr);
2627 
2628     AJFREE(pgm);
2629 
2630 #else
2631     PROCESS_INFORMATION procInfo;
2632     STARTUPINFO startInfo;
2633     ajint status = 0;
2634 
2635     ajDebug ("Launching process '%s'\n", cmdlinetxt);
2636 
2637     ZeroMemory(&startInfo, sizeof(startInfo));
2638     startInfo.cb = sizeof(startInfo);
2639 
2640     if (!CreateProcess(NULL, (char *)cmdlinetxt, NULL, NULL, FALSE,
2641 		       CREATE_NO_WINDOW, NULL, NULL, &startInfo, &procInfo))
2642       ajFatal("CreateProcess failed: %s", cmdlinetxt);
2643 
2644     if(!WaitForSingleObject(procInfo.hProcess, INFINITE))
2645         status = 0;
2646     else
2647         status = -1;
2648 
2649 #endif
2650 
2651     return status;
2652 }
2653 
2654 
2655 
2656 
2657 /* @func ajSysExecPathS *******************************************************
2658 **
2659 ** Exec a command line with a test for the program name in the current path
2660 **
2661 ** The exec'd program is passed a new argv array in argptr
2662 **
2663 ** @param [r] cmdline [const AjPStr] The command line
2664 ** @return [ajint] Exit status
2665 **
2666 ** @release 6.3.0
2667 ** @@
2668 ******************************************************************************/
2669 
ajSysExecPathS(const AjPStr cmdline)2670 ajint ajSysExecPathS(const AjPStr cmdline)
2671 {
2672     return ajSysExecPathC(MAJSTRGETPTR(cmdline));
2673 }
2674 
2675 
2676 
2677 
2678 /* @func ajSysExecRedirectC ***************************************************
2679 **
2680 ** Execute an application redirecting its stdin/out to pipe fds
2681 **
2682 ** @param [r] cmdlinetxt [const char*] Command string.
2683 **                    The string may end with a trailing pipe character.
2684 ** @param [w] pipeto [int**] pipes to the process
2685 ** @param [w] pipefrom [int**] pipes from the process
2686 ** @return [AjBool] True on success
2687 **
2688 ** @release 6.3.0
2689 ** @@
2690 ******************************************************************************/
2691 
ajSysExecRedirectC(const char * cmdlinetxt,int ** pipeto,int ** pipefrom)2692 AjBool ajSysExecRedirectC(const char *cmdlinetxt, int **pipeto, int **pipefrom)
2693 {
2694     int *pipeout = NULL;
2695     int *pipein  = NULL;
2696 #ifndef WIN32
2697     pid_t pid;
2698     char *pgm = NULL;
2699     char **argptr = NULL;
2700     ajint i;
2701 #else
2702     HANDLE cstdinr;
2703     HANDLE cstdinw;
2704     HANDLE cstdoutr;
2705     HANDLE cstdoutw;
2706     HANDLE svstdin;
2707     HANDLE svstdout;
2708     BOOL ret;
2709 
2710     HANDLE cstdinwdup;
2711     HANDLE cstdoutrdup;
2712 
2713     SECURITY_ATTRIBUTES sa;
2714 
2715     PROCESS_INFORMATION pinf;
2716     STARTUPINFO sinf;
2717 #endif
2718 
2719     if(!pipeto || !pipefrom)
2720         return ajFalse;
2721 
2722     if(!*pipeto || !*pipefrom)
2723         return ajFalse;
2724 
2725     pipeout = *pipeto;
2726     pipein  = *pipefrom;
2727 
2728 #ifndef WIN32
2729 
2730     if(!ajSysArglistBuildC(cmdlinetxt, &pgm, &argptr))
2731     {
2732         ajDebug("ajSysExecWithRedirect: Cannot parse command line");
2733         return ajFalse;
2734     }
2735 
2736 
2737     if(pipe(pipeout))
2738     {
2739         ajDebug("ajSysExecRedirectC: Cannot open pipeout");
2740         return ajFalse;
2741     }
2742 
2743     if(pipe(pipein))
2744     {
2745         ajDebug("ajSysExecRedirectC: Cannot open pipein");
2746         return ajFalse;
2747     }
2748 
2749     pid = fork();
2750     if(pid < 0)
2751     {
2752         ajDebug("ajSysExecRedirectC: fork failure");
2753         return ajFalse;
2754     }
2755     else if(!pid)
2756     {
2757         /*
2758         ** CHILD PROCESS
2759         ** dup pipe read/write to stdin/stdout
2760         */
2761         dup2(pipeout[0],  fileno(stdin));
2762         dup2(pipein[1], fileno(stdout));
2763 
2764         /* close unnecessary pipe descriptors */
2765         close(pipeout[0]);
2766         close(pipeout[1]);
2767         close(pipein[0]);
2768         close(pipein[1]);
2769 
2770 	execv(pgm, argptr);
2771 
2772         ajDebug("ajSysExecRedirectC: Problem executing application");
2773         return ajFalse;
2774     }
2775 
2776     /*
2777     ** PARENT PROCESS
2778     ** Close unused pipe ends. This is especially important for the
2779     ** pipein[1] write descriptor, otherwise reading will never
2780     ** give an EOF.
2781     */
2782 
2783     ajDebug("ajSysExecRedirectC: Within the PARENT process");
2784 
2785     close(pipeout[0]);
2786     close(pipein[1]);
2787 
2788     i = 0;
2789 
2790     while(argptr[i])
2791     {
2792 	AJFREE(argptr[i]);
2793 	++i;
2794     }
2795 
2796     AJFREE(argptr);
2797     AJFREE(pgm);
2798 
2799 #else	/* WIN32 */
2800 
2801 
2802     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
2803     sa.bInheritHandle = TRUE;
2804     sa.lpSecurityDescriptor = NULL;
2805 
2806     /*
2807     ** Redirect stdout by
2808     **    Save stdout for later restoration
2809     **    Create anonymous pipe as stdout for the child
2810     **    Set stdout of parent to be write handle to  the pipe thereby
2811     **       making it inherited by the child
2812     **    Create non-inheritable duplicate of the read handle and close
2813     **       the inheritable read handle
2814     */
2815 
2816     svstdout = GetStdHandle(STD_OUTPUT_HANDLE);
2817 
2818     if (!CreatePipe(&cstdoutr, &cstdoutw, &sa, 0))
2819     {
2820         ajDebug("ajSysExecRedirectC: Couldn't open input pipe" );
2821         return ajFalse;
2822     }
2823 
2824     SetHandleInformation(cstdoutr,HANDLE_FLAG_INHERIT,0);
2825 
2826     if (!SetStdHandle(STD_OUTPUT_HANDLE, cstdoutw))
2827     {
2828         ajDebug("ajSysExecRedirectC: failure redirecting stdout");
2829         return ajFalse;
2830     }
2831 
2832     ret = DuplicateHandle(GetCurrentProcess(),
2833                           cstdoutr,
2834                           GetCurrentProcess(),
2835                           &cstdoutrdup , 0,
2836                           FALSE,
2837                           DUPLICATE_SAME_ACCESS);
2838     if(!ret)
2839     {
2840         ajDebug("ajSysExecRedirectC: DuplicateHandle failed");
2841         return ajFalse;
2842     }
2843 
2844     CloseHandle(cstdoutr);
2845 
2846     /*
2847     ** Redirect stdin by
2848     **    Save stdin for later restoration
2849     **    Create anonymous pipe as stdin for the child
2850     **    Set stdin of parent to be read handle of the pipe thereby
2851     **       making it inherited by the child
2852     **    Create non-inheritable duplicate of the write handle and close
2853     **       the inheritable write handle
2854     */
2855 
2856     svstdin = GetStdHandle(STD_INPUT_HANDLE);
2857 
2858     if(!CreatePipe(&cstdinr, &cstdinw, &sa, 0))
2859     {
2860         ajDebug("ajSysExecRedirectC: Cannot open pipeout");
2861         return ajFalse;
2862     }
2863 
2864     if (!SetStdHandle(STD_INPUT_HANDLE, cstdinr))
2865     {
2866         ajDebug("ajSysExecRedirectC: Cannot redirect stdin");
2867         return ajFalse;
2868     }
2869 
2870     ret = DuplicateHandle(GetCurrentProcess(),
2871                                cstdinw,
2872                                GetCurrentProcess(),
2873                                &cstdinwdup, 0,
2874                                FALSE,
2875                                DUPLICATE_SAME_ACCESS);
2876     if(!ret)
2877     {
2878         ajDebug("ajSysExecRedirectC: DuplicateHandle failure");
2879         return ajFalse;
2880     }
2881 
2882     CloseHandle(cstdinw);
2883 
2884     ZeroMemory(&pinf, sizeof(PROCESS_INFORMATION));
2885     ZeroMemory(&sinf, sizeof(STARTUPINFO));
2886     sinf.cb = sizeof(STARTUPINFO);
2887 
2888     ret = CreateProcess(NULL, (char *)cmdlinetxt, NULL, NULL, TRUE, 0,
2889                         NULL, NULL, &sinf, &pinf);
2890 
2891     if(ret == 0)
2892     {
2893         ajDebug("ajSysExecRedirectC: Cannot execute application: %s",
2894 		cmdlinetxt);
2895         return ajFalse;
2896     }
2897 
2898     CloseHandle(pinf.hProcess);
2899     CloseHandle(pinf.hThread);
2900 
2901 
2902     if(!SetStdHandle(STD_INPUT_HANDLE, svstdin))
2903     {
2904         ajDebug("ajSysExecRedirectC: Error restoring stdin");
2905         return ajFalse;
2906     }
2907 
2908     if(!SetStdHandle(STD_OUTPUT_HANDLE, svstdout))
2909     {
2910         ajDebug("ajSysExecRedirectC: Error restoring stdout");
2911         return ajFalse;
2912     }
2913 
2914     CloseHandle(cstdoutw);
2915 
2916     pipeout[1] = _open_osfhandle((intptr_t) cstdinwdup,
2917                                  _O_APPEND);
2918 
2919     pipein[0]  = _open_osfhandle((intptr_t) cstdoutrdup,
2920                                  _O_RDONLY);
2921 #endif
2922 
2923     return ajTrue;
2924 }
2925 
2926 
2927 
2928 
2929 /* @section executing programs ************************************************
2930 **
2931 ** Functions for executing programs
2932 **
2933 ** @fdata [none]
2934 ** @fcategory misc
2935 **
2936 ** @nam3rule  Execprog      Execute a progfam
2937 ** @suffix    Nowait        No parent wait
2938 ** @suffix    C             Accept C character string parameters
2939 ** @suffix    S             Accept string object parameters
2940 **
2941 ** @argrule   C prog    [const char*] The program name
2942 ** @argrule   S progstr [const AjPStr] The program name
2943 ** @argrule   * arg     [char* const[]] Argument list
2944 ** @argrule   * env     [char* const[]] An environment list
2945 **
2946 ** @valrule Execprog [ajint] Exit status
2947 **
2948 ******************************************************************************/
2949 
2950 
2951 
2952 
2953 /* @func ajSysExecprogNowaitC *************************************************
2954 **
2955 ** Exec a command line with no parent wait
2956 **
2957 ** This routine must be passed a program, an argument list and an environment.
2958 ** The wait handling is performed by user-supplied parent process code and
2959 ** is therefore used by the Java Native Interface software.
2960 **
2961 ** @param [r] prog[const char*] The command line
2962 ** @param [r] arg [char* const[]] Argument list
2963 ** @param [r] env [char* const[]] An environment
2964 ** @return [ajint] Exit status
2965 **
2966 ** @release 6.4.0
2967 ** @@
2968 ******************************************************************************/
2969 
ajSysExecprogNowaitC(const char * prog,char * const arg[],char * const env[])2970 ajint  ajSysExecprogNowaitC(const char *prog, char * const arg[],
2971                             char * const env[])
2972 {
2973 #ifndef WIN32
2974     if(execve(prog,arg,env) == -1)
2975         ajFatal("ajSysExecProgArgEnvNowaitC: Cannot exec application %s",
2976                 prog);
2977 #endif
2978 
2979     return 0;
2980 }
2981 
2982 
2983 
2984 
2985 /* @func ajSysExecprogNowaitS *************************************************
2986 **
2987 ** Exec a command line with no parent wait
2988 **
2989 ** This routine must be passed a program, an argument list and an environment.
2990 ** The wait handling is performed by user-supplied parent process code and
2991 ** is therefore used by the Java Native Interface software.
2992 **
2993 ** @param [r] progstr [const AjPStr] The command line
2994 ** @param [r] arg [char* const[]] Argument list
2995 ** @param [r] env [char* const[]] An environment
2996 ** @return [ajint] Exit status
2997 **
2998 ** @release 6.4.0
2999 ** @@
3000 ******************************************************************************/
3001 
ajSysExecprogNowaitS(const AjPStr progstr,char * const arg[],char * const env[])3002 ajint ajSysExecprogNowaitS(const AjPStr progstr, char * const arg[],
3003                            char * const env[])
3004 {
3005     return ajSysExecprogNowaitC(MAJSTRGETPTR(progstr), arg, env);
3006 }
3007 
3008 
3009 
3010 
3011 /* @section Miscellaneous system functions ************************************
3012 **
3013 ** Miscellaneous system functions
3014 **
3015 ** @fdata [none]
3016 ** @fcategory misc
3017 **
3018 ** @nam3rule  Canon          Sets or unsets TTY canonical mode
3019 ** @nam3rule  Socketclose    Closes a UNIX or WIN32 socket
3020 ** @nam3rule  Fd             Gets file descriptor
3021 ** @nam4rule  FdFrom         Gets file descriptor from object
3022 ** @nam5rule  FdFromSocket   Gets file descriptor from open socket
3023 ** @nam3rule  Exit           Cleans up system internals memory
3024 ** @nam3rule  Timeout        Control alarm abort timeouts
3025 ** @nam4rule  TimeoutSet     Set a timeout
3026 ** @nam4rule  TimeoutUnset   Unset a timeout
3027 **
3028 ** @argrule Canon        state [AjBool]          Canonical mode set if true
3029 ** @argrule FdFromSocket sock  [const AjOSysSocket] AJAX socket structure
3030 ** @argrule FdFromSocket mode  [const char*]     Opening mode ("r" or "a")
3031 ** @argrule Socketclose  sock  [AjOSysSocket]       AJAX socket structure
3032 ** @argrule Timeout      ts    [AjPSysTimeout]      AJAX timeout structure
3033 **
3034 ** @valrule  *  [void]
3035 ** @valrule  *FdFromSocket  [FILE*] File descriptor
3036 ** @valrule  *Timeout [int] Exit code (-1 for error, 0 =for success)
3037 **
3038 ******************************************************************************/
3039 
3040 
3041 
3042 
3043 /* @func ajSysCanon  **********************************************************
3044 **
3045 ** Sets or unsets TTY canonical mode
3046 **
3047 ** @param [r] state [AjBool] state=true sets canon state=false sets noncanon
3048 ** @return [void]
3049 **
3050 ** @release 1.0.0
3051 ** @@
3052 ******************************************************************************/
3053 
ajSysCanon(AjBool state)3054 void ajSysCanon(AjBool state)
3055 {
3056 #ifndef WIN32
3057 #ifndef __VMS
3058     static struct termios tty;
3059 
3060 
3061     tcgetattr(1, &tty);
3062     tty.c_cc[VMIN]  = '\1';
3063     tty.c_cc[VTIME] = '\0';
3064     tcsetattr(1,TCSANOW,&tty);
3065 
3066     if(state)
3067 	tty.c_lflag |= ICANON;
3068     else
3069 	tty.c_lflag &= ~(ICANON);
3070 
3071     tcsetattr(1, TCSANOW, &tty);
3072 #endif
3073 #endif
3074     return;
3075 }
3076 
3077 
3078 
3079 
3080 /* @func ajSysFdFromSocket  ***************************************************
3081 **
3082 ** Return a file descriptor from a UNIX of Windows socket
3083 **
3084 ** @param [r] sock [const AjOSysSocket] AJAX socket structure
3085 ** @param [r] mode [const char*] Opening mode ("r" or "a")
3086 ** @return [FILE*] File descriptor
3087 **
3088 ** @release 6.3.0
3089 ** @@
3090 ******************************************************************************/
3091 
ajSysFdFromSocket(const AjOSysSocket sock,const char * mode)3092 FILE* ajSysFdFromSocket(const AjOSysSocket sock, const char *mode)
3093 {
3094     FILE *ret;
3095 #ifdef WIN32
3096     int fd;
3097     int flags = 0;
3098     char c;
3099 
3100 #endif
3101 
3102     if(!mode)
3103         return NULL;
3104 
3105 #ifndef WIN32
3106     ret = ajSysFuncFdopen(sock.sock,mode);
3107 #else
3108     c = *mode;
3109 
3110     switch(c)
3111     {
3112         case 'r':
3113             flags = _O_RDONLY;
3114             break;
3115         case 'a':
3116             flags = _O_APPEND;
3117             break;
3118         default:
3119             ajErr("ajSysFdFromSocket: Illegal mode [%c]",c);
3120             break;
3121     }
3122 
3123     fd  = _open_osfhandle(sock.sock, _O_RDONLY);
3124     ret = ajSysFuncFdopen(fd,mode);
3125 #endif
3126 
3127     return ret;
3128 }
3129 
3130 
3131 
3132 
3133 /* @func ajSysSocketclose  ****************************************************
3134 **
3135 ** Closes a UNIX or WIN32 socket
3136 **
3137 ** @param [u] sock [AjOSysSocket] AJAX socket structure
3138 ** @return [void]
3139 **
3140 ** @release 6.3.0
3141 ** @@
3142 ******************************************************************************/
3143 
ajSysSocketclose(AjOSysSocket sock)3144 void ajSysSocketclose(AjOSysSocket sock)
3145 {
3146 #ifndef WIN32
3147     close(sock.sock);
3148 #else
3149     closesocket(sock.sock);
3150 #endif
3151 
3152     return;
3153 }
3154 
3155 
3156 
3157 
3158 /* @func ajSysTimeoutSet ******************************************************
3159 **
3160 ** Sets an alarm abort timeout for UNIX and Windows
3161 **
3162 ** @param [u] ts [AjPSysTimeout] AJAX timeout structure
3163 ** @return [int] 0 = success -1 = error
3164 **
3165 ** @release 6.3.0
3166 ** @@
3167 ******************************************************************************/
3168 
ajSysTimeoutSet(AjPSysTimeout ts)3169 int ajSysTimeoutSet(AjPSysTimeout ts)
3170 {
3171     int ret = 0;
3172 
3173 #ifndef WIN32
3174     sigemptyset( &ts->sa.sa_mask );
3175     ts->sa.sa_flags = 0;
3176     ts->sa.sa_handler = sysTimeoutAbort;
3177     ret = sigaction( SIGALRM, &ts->sa, NULL );
3178 
3179     alarm(ts->seconds);
3180 #else
3181     PTIMERAPCROUTINE ptim = NULL;
3182 
3183     ts->wtime.QuadPart = -10000000LL;
3184     ts->wtime.QuadPart *= ts->seconds;
3185 
3186     ts->thandle = CreateWaitableTimer(NULL, TRUE, NULL);
3187     if(!ts->thandle)
3188         return -1;
3189 
3190     ptim = (PTIMERAPCROUTINE) sysTimeoutAbort;
3191 
3192     if (!SetWaitableTimer(ts->thandle, &ts->wtime, 0, ptim, NULL, 0))
3193         ret = -1;
3194 
3195 #endif
3196 
3197     return ret;
3198 }
3199 
3200 
3201 
3202 
3203 /* @func ajSysTimeoutUnset ****************************************************
3204 **
3205 ** Unsets an alarm abort timeout for UNIX and Windows
3206 **
3207 ** @param [u] ts [AjPSysTimeout] AJAX timeout structure
3208 ** @return [int] 0 = success -1 = error
3209 **
3210 ** @release 6.3.0
3211 ** @@
3212 ******************************************************************************/
3213 
ajSysTimeoutUnset(AjPSysTimeout ts)3214 int ajSysTimeoutUnset(AjPSysTimeout ts)
3215 {
3216     int ret = 0;
3217 
3218 #ifndef WIN32
3219     ret = sigemptyset(&ts->sa.sa_mask);
3220 
3221     alarm(0);
3222 #else
3223     if(!CancelWaitableTimer(ts->thandle))
3224         return -1;
3225 
3226     if(!CloseHandle(ts->thandle))
3227       ret = -1;
3228 #endif
3229 
3230     return ret;
3231 }
3232 
3233 
3234 
3235 
3236 #ifndef WIN32
3237 /* @funcstatic sysTimeoutAbort ************************************************
3238 **
3239 ** Fatal error if a socket read hangs
3240 **
3241 ** @param [r] sig [int] Signal code - always SIGALRM but required by the
3242 **                      signal call
3243 ** @return [void]
3244 **
3245 ** @release 6.3.0
3246 ** @@
3247 ******************************************************************************/
sysTimeoutAbort(int sig)3248 static void sysTimeoutAbort(int sig)
3249 {
3250     (void) sig;
3251 
3252     ajDie("Alarm timeout");
3253 
3254     return;
3255 }
3256 #else
sysTimeoutAbort(LPVOID arg,DWORD low,DWORD high)3257 static void CALLBACK sysTimeoutAbort(LPVOID arg, DWORD low, DWORD high)
3258 {
3259     (void) arg;
3260     (void) low;
3261     (void) high;
3262 
3263     ajDie("Timer timeout");
3264 
3265     return;
3266 }
3267 #endif
3268 
3269 
3270 
3271 
3272 /* @section piped commands ****************************************************
3273 **
3274 ** system command lines piped to a file
3275 **
3276 ** @fdata [none]
3277 ** @fcategory misc
3278 **
3279 ** @nam3rule  Create         Create a new input
3280 ** @nam4rule  Inpipe         Create a new input
3281 **
3282 ** @suffix C C character string arguments
3283 ** @suffix S String object arguments
3284 **
3285 ** @argrule C cmdlinetxt [const char*] Command line
3286 ** @argrule S command [const AjPStr] Command line
3287 ** @valrule   *Inpipe  [AjPFile]
3288 **
3289 ******************************************************************************/
3290 
3291 
3292 
3293 
3294 /* @func ajSysCreateInpipeC ***************************************************
3295 **
3296 ** Return a new file object from which to read the output from a command.
3297 **
3298 ** @param [r] cmdlinetxt [const char*] Command string.
3299 **                    The string may end with a trailing pipe character.
3300 ** @return [AjPFile] New file object.
3301 **
3302 ** @release 6.3.0
3303 ** @@
3304 ******************************************************************************/
3305 
ajSysCreateInpipeC(const char * cmdlinetxt)3306 AjPFile ajSysCreateInpipeC(const char* cmdlinetxt)
3307 {
3308     AjPFile thys;
3309     AjPStr cmdstr = NULL;
3310 
3311 #ifndef WIN32
3312     ajint pipefds[2];		     /* file descriptors for a pipe */
3313     char** arglist        = NULL;
3314     char* pgm;
3315 #else
3316     HANDLE cstdinr  = NULL;
3317     HANDLE cstdinw  = NULL;
3318     HANDLE cstdoutr = NULL;
3319     HANDLE cstdoutw = NULL;
3320     HANDLE svstdout = NULL;
3321     HANDLE cstdoutrdup = NULL;
3322 
3323     SECURITY_ATTRIBUTES sa;
3324 
3325     PROCESS_INFORMATION pinf;
3326     STARTUPINFO sinf;
3327 
3328     BOOL ret =  FALSE;
3329 
3330     int fd;
3331 #endif
3332 
3333     cmdstr = ajStrNew();
3334 
3335     AJNEW0(thys);
3336     ajStrAssignC(&cmdstr, cmdlinetxt);
3337 
3338     ajDebug("ajSysCreateInpipeC: '%s'\n", cmdlinetxt);
3339 
3340     /* pipe character at end */
3341     if(ajStrGetCharLast(cmdstr) == '|')
3342 	ajStrCutEnd(&cmdstr, 1);
3343 
3344 
3345 #ifndef WIN32
3346 
3347     if(pipe(pipefds) < 0)
3348 	ajFatal("ajSysCreateInpipeC: pipe create failed");
3349 
3350     /* negative return indicates failure */
3351     thys->Pid = fork();
3352 
3353     if(thys->Pid < 0)
3354 	ajFatal("ajSysCreateInpipeC: fork create failed");
3355 
3356     /* pid is zero in the child, but is the child PID in the parent */
3357 
3358     if(!thys->Pid)
3359     {
3360 	/* this is the child process */
3361 	close(pipefds[0]);
3362 
3363 	dup2(pipefds[1], 1);
3364 	close(pipefds[1]);
3365 	ajSysArglistBuildS(cmdstr, &pgm, &arglist);
3366 	ajDebug("ajSysCreateInpipeC: execvp ('%S', NULL)\n", cmdstr);
3367 	execvp(pgm, arglist);
3368 	ajErr("ajSysCreateInpipeC: execvp ('%S', NULL) failed: '%s'\n",
3369 		cmdstr, strerror(errno));
3370 	ajExitAbort();
3371     }
3372 
3373     ajDebug("ajSysCreateInpipeC: pid %d, pipe '%d', '%d'\n",
3374 	    thys->Pid, pipefds[0], pipefds[1]);
3375 
3376     /* fp is what we read from the pipe */
3377     thys->fp = ajSysFuncFdopen(pipefds[0], "r");
3378     close(pipefds[1]);
3379 
3380 #else
3381 
3382     sa.nLength = sizeof(SECURITY_ATTRIBUTES);
3383     sa.bInheritHandle =  TRUE;
3384     sa.lpSecurityDescriptor = NULL;
3385 
3386     svstdout = GetStdHandle(STD_OUTPUT_HANDLE);
3387 
3388     if(!CreatePipe(&cstdoutr, &cstdoutw, &sa,  0))
3389         ajFatal("ajSysCreateInpipeC: pipe create failed");
3390 
3391     if(!SetHandleInformation(cstdoutr, HANDLE_FLAG_INHERIT, 0))
3392         ajFatal("ajSysCreateInpipeC: Can't set no-inherit on child stdout "
3393 		"read handle");
3394 
3395 
3396     if(!SetStdHandle(STD_OUTPUT_HANDLE, cstdoutw))
3397         ajFatal("ajSysCreateInpipeC: redirecting of STDOUT failed");
3398 
3399     ret = DuplicateHandle(GetCurrentProcess(),
3400 			  cstdoutr,
3401 			  GetCurrentProcess(),
3402 			  &cstdoutrdup , 0,
3403 			  FALSE,
3404 			  DUPLICATE_SAME_ACCESS);
3405     if(!ret)
3406       ajFatal("ajSysCreateInpipeC: Could not duplicate stdout read handle");
3407 
3408     CloseHandle(cstdoutr);
3409 
3410     /* Create Process here */
3411 
3412     ZeroMemory(&pinf, sizeof(PROCESS_INFORMATION));
3413     ZeroMemory(&sinf, sizeof(STARTUPINFO));
3414     sinf.cb = sizeof(STARTUPINFO);
3415 
3416     ret = CreateProcess(NULL, (char *)ajStrGetPtr(cmdstr), NULL, NULL, TRUE, 0,
3417 			NULL, NULL, &sinf, &pinf);
3418 
3419     if(!ret)
3420         ajFatal("ajSysCreateInpipeC: CreateProcess failed: %S", cmdstr);
3421 
3422     thys->Process = pinf.hProcess;
3423     thys->Thread  = pinf.hThread;
3424 
3425     if(!SetStdHandle(STD_OUTPUT_HANDLE, svstdout))
3426        ajFatal("restoring  stdout failed\n");
3427 
3428     CloseHandle(cstdoutw);
3429 
3430     fd = _open_osfhandle((intptr_t) cstdoutrdup, _O_RDONLY);
3431     thys->fp = ajSysFuncFdopen(fd, "r");
3432 #endif
3433 
3434     ajStrDel(&cmdstr);
3435 
3436     if(!thys->fp)
3437     {
3438 	thys->Handle = 0;
3439 	ajFileClose(&thys);
3440 
3441 	return NULL;
3442     }
3443 
3444     return thys;
3445 }
3446 
3447 
3448 
3449 
3450 /* @func ajSysCreateInpipeS ***************************************************
3451 **
3452 ** Return a new file object from which to read the output from a command.
3453 **
3454 ** @param [r] command [const AjPStr] Command string.
3455 **                    The string may end with a trailing pipe character.
3456 ** @return [AjPFile] New file object.
3457 **
3458 ** @release 6.3.0
3459 ** @@
3460 ******************************************************************************/
3461 
ajSysCreateInpipeS(const AjPStr command)3462 AjPFile ajSysCreateInpipeS(const AjPStr command)
3463 {
3464     return ajSysCreateInpipeC(MAJSTRGETPTR(command));
3465 }
3466 
3467 
3468 
3469 
3470 /* @section exit **************************************************************
3471 **
3472 ** Functions called on exit from the program by ajExit to do
3473 ** any necessary cleanup and to report internal statistics to the debug file
3474 **
3475 ** @fdata      [none]
3476 ** @fnote     general exit functions, no arguments
3477 **
3478 ** @nam3rule Exit Cleanup and report on exit
3479 **
3480 ** @valrule * [void]
3481 **
3482 ** @fcategory misc
3483 */
3484 
3485 
3486 
3487 
3488 /* @func ajSysExit ************************************************************
3489 **
3490 ** Cleans up system internals memory
3491 **
3492 ** @return [void]
3493 **
3494 ** @release 4.0.0
3495 ** @@
3496 ******************************************************************************/
3497 
ajSysExit(void)3498 void ajSysExit(void)
3499 {
3500     ajStrDel(&sysFname);
3501     ajStrDel(&sysTname);
3502     ajStrDel(&sysTokSou);
3503     ajStrDel(&sysTokRets);
3504     ajStrDel(&sysUserPath);
3505 
3506     return;
3507 }
3508 
3509 
3510 
3511 
3512 #ifdef AJ_COMPILE_DEPRECATED_BOOK
3513 #endif
3514 
3515 
3516 
3517 
3518 #ifdef AJ_COMPILE_DEPRECATED
3519 /* @obsolete ajSysArglistBuild
3520 ** @rename ajSysArglistBuildS
3521 */
3522 
ajSysArglistBuild(const AjPStr cmdline,char ** Pname,char *** PParglist)3523 __deprecated AjBool ajSysArglistBuild(const AjPStr cmdline,
3524                                       char** Pname, char*** PParglist)
3525 {
3526     return ajSysArglistBuildS(cmdline, Pname, PParglist);
3527 }
3528 
3529 
3530 
3531 
3532 /* @obsolete ajSysArglist
3533 ** @rename ajSysArglistBuildS
3534 */
3535 
ajSysArglist(const AjPStr cmdline,char ** Pname,char *** PParglist)3536 __deprecated AjBool ajSysArglist(const AjPStr cmdline,
3537 				 char** Pname, char*** PParglist)
3538 {
3539     return ajSysArglistBuildS(cmdline, Pname, PParglist);
3540 }
3541 
3542 
3543 
3544 
3545 /* @obsolete ajSysArgListFree
3546 ** @rename ajSysArglistFree
3547 */
3548 
ajSysArgListFree(char *** PParglist)3549 __deprecated void ajSysArgListFree(char*** PParglist)
3550 {
3551     ajSysArglistFree(PParglist);
3552     return;
3553 }
3554 
3555 
3556 
3557 
3558 /* @obsolete ajSysItoC
3559 ** @rename ajSysCastItoC
3560 */
3561 
ajSysItoC(ajint v)3562 __deprecated char ajSysItoC(ajint v)
3563 {
3564     return ajSysCastItoc(v);
3565 }
3566 
3567 
3568 
3569 
3570 /* @obsolete ajSysItoUC
3571 ** @rename ajSysCastItouc
3572 */
3573 
ajSysItoUC(ajint v)3574 __deprecated unsigned char ajSysItoUC(ajint v)
3575 {
3576     return ajSysCastItouc(v);
3577 }
3578 
3579 
3580 
3581 
3582 /* @obsolete ajSysFileUnlink
3583 ** @rename ajSysFileUnlinkS
3584 */
3585 
ajSysFileUnlink(const AjPStr s)3586 __deprecated AjBool ajSysFileUnlink(const AjPStr s)
3587 {
3588     return ajSysFileUnlinkS(s);
3589 }
3590 
3591 
3592 
3593 
3594 /* @obsolete ajSysUnlink
3595 ** @rename ajSysFileUnlinkS
3596 */
3597 
ajSysUnlink(const AjPStr s)3598 __deprecated AjBool ajSysUnlink(const AjPStr s)
3599 {
3600     return ajSysFileUnlinkS(s);
3601 }
3602 
3603 
3604 
3605 
3606 /* @obsolete ajSysWhich
3607 ** @rename ajSysFileWhich
3608 */
3609 
ajSysWhich(AjPStr * s)3610 __deprecated AjBool ajSysWhich(AjPStr *s)
3611 {
3612     return ajSysFileWhich(s);
3613 }
3614 
3615 
3616 
3617 
3618 /* @obsolete ajSysWhichEnv
3619 ** @rename ajSysFileWhichEnv
3620 */
3621 
ajSysWhichEnv(AjPStr * Pfilename,char * const env[])3622 __deprecated AjBool ajSysWhichEnv(AjPStr *Pfilename, char * const env[])
3623 {
3624     return ajSysFileWhichEnv(Pfilename, env);
3625 }
3626 
3627 
3628 
3629 
3630 /* @obsolete ajSysFdopen
3631 ** @rename ajSysFuncFdopen
3632 */
3633 
ajSysFdopen(ajint filedes,const char * mode)3634 __deprecated FILE* ajSysFdopen(ajint filedes, const char *mode)
3635 {
3636     return ajSysFuncFdopen(filedes, mode);
3637 }
3638 
3639 
3640 
3641 
3642 /* @obsolete ajSysFgets
3643 ** @rename ajSysFuncFgets
3644 */
3645 
ajSysFgets(char * buf,int size,FILE * fp)3646 __deprecated char* ajSysFgets(char *buf, int size, FILE *fp)
3647 {
3648     return ajSysFuncFgets(buf, size, fp);
3649 }
3650 
3651 
3652 
3653 
3654 /* @obsolete ajSysFopen
3655 ** @rename ajSysFuncFopen
3656 */
3657 
ajSysFopen(const char * name,const char * flags)3658 __deprecated FILE* ajSysFopen(const char *name, const char *flags)
3659 {
3660     return ajSysFuncFopen(name, flags);
3661 }
3662 
3663 
3664 
3665 
3666 /* @obsolete ajSysStrdup
3667 ** @rename ajSysFuncStrdup
3668 */
ajSysStrdup(const char * s)3669 __deprecated char* ajSysStrdup(const char *s)
3670 {
3671     return ajSysFuncStrdup(s);
3672 }
3673 
3674 
3675 
3676 
3677 /* @obsolete ajSysStrtok
3678 ** @rename ajSysFuncStrtok
3679 */
3680 
ajSysStrtok(const char * s,const char * t)3681 __deprecated char* ajSysStrtok(const char *s, const char *t)
3682 {
3683     return ajSysFuncStrtok(s, t);
3684 }
3685 
3686 
3687 
3688 
3689 /* @obsolete ajSysStrtokR
3690 ** @rename ajSysFuncStrtokR
3691 */
3692 
3693 
ajSysStrtokR(const char * s,const char * t,const char ** ptrptr,AjPStr * buf)3694 __deprecated char* ajSysStrtokR(const char *s, const char *t,
3695 				const char **ptrptr,
3696 				AjPStr *buf)
3697 {
3698     return ajSysFuncStrtokR(s, t, ptrptr, buf);
3699 }
3700 
3701 
3702 
3703 
3704 /* @obsolete ajSystemEnv
3705 ** @rename ajSysExecEnvS
3706 */
3707 
ajSystemEnv(const AjPStr cl,char * const env[])3708 __deprecated void ajSystemEnv(const AjPStr cl, char * const env[])
3709 {
3710     ajSysExecEnvS(cl, env);
3711     return;
3712 }
3713 
3714 
3715 
3716 
3717 /* @obsolete ajSysSystemEnv
3718 ** @rename ajSysExecEnvS
3719 */
3720 
ajSysSystemEnv(const AjPStr cmdline,char * const env[])3721 __deprecated void ajSysSystemEnv(const AjPStr cmdline, char * const env[])
3722 {
3723     ajSysExecEnvS(cmdline, env);
3724 
3725     return;
3726 }
3727 
3728 
3729 
3730 
3731 /* @obsolete ajSystemOut
3732 ** @rename ajSysExecOutnameS
3733 */
3734 
ajSystemOut(const AjPStr cl,const AjPStr outfname)3735 __deprecated void ajSystemOut(const AjPStr cl, const AjPStr outfname)
3736 {
3737     ajSysExecOutnameS(cl, outfname);
3738     return;
3739 }
3740 
3741 
3742 
3743 
3744 /* @obsolete ajSysSystemOut
3745 ** @rename ajSysExecOutnameS
3746 */
3747 
ajSysSystemOut(const AjPStr cmdline,const AjPStr outfname)3748 __deprecated void ajSysSystemOut(const AjPStr cmdline, const AjPStr outfname)
3749 {
3750     ajSysExecOutnameS(cmdline, outfname);
3751     return;
3752 }
3753 
3754 
3755 
3756 
3757 /* @obsolete ajSystem
3758 ** @rename ajSysSystem
3759 */
3760 
ajSystem(const AjPStr cl)3761 __deprecated void ajSystem(const AjPStr cl)
3762 {
3763     ajSysExecS(cl);
3764     return;
3765 }
3766 
3767 
3768 
3769 
3770 /* @obsolete ajSysSystem
3771 ** @rename ajSysExecS
3772 */
3773 
ajSysSystem(const AjPStr cmdline)3774 __deprecated void ajSysSystem(const AjPStr cmdline)
3775 {
3776     ajSysExecS(cmdline);
3777     return;
3778 }
3779 
3780 
3781 
3782 
3783 /* @obsolete ajSysExecProgArgEnvNowaitC
3784 ** @rename ajSysExecProgArgEnvNowaitC
3785 */
ajSysExecProgArgEnvNowaitC(const char * prog,char * const arg[],char * const env[])3786 __deprecated ajint  ajSysExecProgArgEnvNowaitC(const char *prog,
3787                                                char * const arg[],
3788                                                char * const env[])
3789 {
3790     return ajSysExecprogNowaitC(prog, arg, env);
3791 }
3792 
3793 
3794 
3795 
3796 /* @obsolete ajSysExecProgArgEnvNowaitS
3797 ** @rename ajSysExecProgArgEnvNowaitS
3798 */
ajSysExecProgArgEnvNowaitS(const AjPStr progstr,char * const arg[],char * const env[])3799 __deprecated ajint  ajSysExecProgArgEnvNowaitS(const AjPStr progstr,
3800                                                char * const arg[],
3801                                                char * const env[])
3802 {
3803     return ajSysExecprogNowaitC(MAJSTRGETPTR(progstr), arg, env);
3804 }
3805 
3806 
3807 
3808 
3809 /* @obsolete ajSysBasename
3810 ** @rename ajFilenameTrimPath
3811 */
3812 
ajSysBasename(AjPStr * s)3813 __deprecated void ajSysBasename(AjPStr *s)
3814 {
3815     ajFilenameTrimPath(s);
3816 
3817     return;
3818 }
3819 
3820 
3821 
3822 
3823 /* @obsolete ajSysIsDirectory
3824 ** @remove use ajFileDir instead
3825 */
3826 
ajSysIsDirectory(const char * s)3827 __deprecated AjBool ajSysIsDirectory(const char *s)
3828 {
3829     AjBool ret;
3830     AjPStr tmpstr = NULL;
3831     tmpstr = ajStrNewC(s);
3832 
3833     ret = ajDirnameFixExists(&tmpstr);
3834     ajStrDel(&tmpstr);
3835 
3836     return ret;
3837 }
3838 
3839 
3840 
3841 
3842 /* @obsolete ajSysIsRegular
3843 ** @remove use ajFileNameValid instead
3844 */
3845 
ajSysIsRegular(const char * s)3846 __deprecated AjBool ajSysIsRegular(const char *s)
3847 {
3848     AjBool ret;
3849     AjPStr tmpstr;
3850 
3851     tmpstr = ajStrNewC(s);
3852 
3853     ret = ajFilenameExistsRead(tmpstr);
3854     ajStrDel(&tmpstr);
3855 
3856     return ret;
3857 }
3858 #endif
3859