1 /* @source ajutil *************************************************************
2 **
3 **AJAX utility functions
4 **
5 ** @author Copyright (C) 1998 Ian Longden
6 ** @author Copyright (C) 1998 Peter Rice
7 ** @version $Revision: 1.67 $
8 ** @modified $Date: 2012/09/03 14:52:38 $ by $Author: rice $
9 ** @@
10 **
11 ** This library is free software; you can redistribute it and/or
12 ** modify it under the terms of the GNU Lesser General Public
13 ** License as published by the Free Software Foundation; either
14 ** version 2.1 of the License, or (at your option) any later version.
15 **
16 ** This library is distributed in the hope that it will be useful,
17 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
18 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19 ** Lesser General Public License for more details.
20 **
21 ** You should have received a copy of the GNU Lesser General Public
22 ** License along with this library; if not, write to the Free Software
23 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
24 ** MA  02110-1301,  USA.
25 **
26 ******************************************************************************/
27 
28 #include "ajlib.h"
29 
30 #include "ajutil.h"
31 
32 /* include anything with an Exit function */
33 
34 #include "ajindex.h"
35 #include "ajsql.h"
36 #include "ajmatrices.h"
37 #include "ajtree.h"
38 #include "ajdmx.h"
39 #include "ajdomain.h"
40 #include "ajquery.h"
41 #include "ajtext.h"
42 #include "ajfeat.h"
43 #include "ajseq.h"
44 #include "ajobo.h"
45 #include "ajassem.h"
46 #include "ajrefseq.h"
47 #include "ajtax.h"
48 #include "ajurl.h"
49 #include "ajvar.h"
50 #include "ajxml.h"
51 #include "ajresource.h"
52 #include "ajphylo.h"
53 #include "ajnexus.h"
54 #include "ajalign.h"
55 #include "ajreport.h"
56 #include "ajnam.h"
57 #include "ajsys.h"
58 #include "ajcall.h"
59 #include "ajbase.h"
60 #include "ajcod.h"
61 #include "ajtranslate.h"
62 #include "ajdan.h"
63 #include "ajtime.h"
64 #include "ajreg.h"
65 #include "ajarr.h"
66 #include "ajfiledata.h"
67 #include "ajfile.h"
68 #include "ajlist.h"
69 #include "ajtable.h"
70 #include "ajstr.h"
71 #include "ajmem.h"
72 
73 #include <stdarg.h>
74 #ifdef WIN32
75 #include "win32.h"
76 #include <winsock2.h>
77 #include <lmcons.h> /* for UNLEN */
78 #else /* !WIN32 */
79 #include <pwd.h>
80 #include <unistd.h>
81 #endif /* WIN32 */
82 
83 
84 
85 static AjBool utilBigendian;
86 static ajint utilBigendCalled = 0;
87 
88 static AjBool utilIsBase64(char c);
89 static char   utilBase64Encode(unsigned char u);
90 static unsigned char utilBase64Decode(char c);
91 
92 
93 
94 
95 /* @filesection ajutil ********************************************************
96 **
97 ** @nam1rule aj Function belongs to the AJAX library.
98 **
99 ******************************************************************************/
100 
101 
102 
103 
104 /* @datasection [none] Exit functions *****************************************
105 **
106 ** @nam2rule Exit Functions for exiting cleanly
107 **
108 ******************************************************************************/
109 
110 
111 
112 
113 /* @section exit  *************************************************************
114 **
115 ** Functions for exiting cleanly.
116 **
117 ** @fdata [none]
118 **
119 ** @nam3rule  Abort  Exits without flushing any files.
120 ** @nam3rule  Bad    Calls 'exit' with an unsuccessful code (EXIT_FAILURE
121 **                   defined in stdlib.h).
122 **
123 ** @valrule   *  [void] All functions do not return
124 **
125 ** @fcategory misc
126 **
127 ******************************************************************************/
128 
129 
130 
131 
132 /* @func ajExit ***************************************************************
133 **
134 ** Calls 'exit' with a successful code (zero), but first calls ajReset to
135 ** call memory clean up and debug reporting functions.
136 **
137 ** No cleanup or reporting routines are called. Simply crashes.
138 **
139 ** @return [void]
140 **
141 ** @release 1.0.0
142 ** @@
143 ******************************************************************************/
144 
ajExit(void)145 __noreturn void ajExit(void)
146 {
147     ajReset();
148     exit(EXIT_SUCCESS);
149 }
150 
151 
152 
153 
154 /* @func ajExitAbort **********************************************************
155 **
156 ** Exits without flushing any files. Needed for exit from, for example,
157 ** a failed system call (ajFileNewInPipe, and so on) where the parent
158 ** process has open output files, and the child process needs to exit
159 ** without affecting them. Failure to exit this way can mean the output
160 ** buffer is flushed twice.
161 **
162 ** Calls '_exit' with an unsuccessful code (EXIT_FAILURE defined in stdlib.h).
163 **
164 ** No cleanup or reporting routines are called. Simply crashes.
165 **
166 ** @return [void]
167 **
168 ** @release 3.0.0
169 ** @@
170 ******************************************************************************/
171 
ajExitAbort(void)172 __noreturn void  ajExitAbort(void)
173 {
174     _exit(EXIT_FAILURE);
175 }
176 
177 
178 
179 
180 /* @func ajExitBad ************************************************************
181 **
182 ** Calls 'exit' with an unsuccessful code (EXIT_FAILURE defined in stdlib.h).
183 **
184 ** No cleanup or reporting routines are called. Simply crashes.
185 **
186 ** @return [void]
187 **
188 ** @release 1.0.0
189 ** @@
190 ******************************************************************************/
191 
ajExitBad(void)192 __noreturn void  ajExitBad(void)
193 {
194     exit(EXIT_FAILURE);
195 }
196 
197 
198 
199 
200 /* @datasection [none] Memory cleanup functions *******************************
201 **
202 ** @nam2rule  Reset  Resets internal memory and returns.
203 **
204 ******************************************************************************/
205 
206 
207 
208 
209 /* @section reset *************************************************************
210 **
211 ** Functions for memory cleanup
212 **
213 ** @fdata [none]
214 **
215 **
216 ** @valrule   *  [void] No return value
217 **
218 ** @fcategory misc
219 **
220 ******************************************************************************/
221 
222 
223 
224 
225 /* @func ajReset **************************************************************
226 **
227 ** Cleans up all internal memory by calling cleanup routines which
228 ** can report on resource usage etc.
229 **
230 ** Intended to be called at the end of processing by exit functions.
231 **
232 ** @return [void]
233 **
234 ** @release 5.0.0
235 ** @@
236 ******************************************************************************/
237 
ajReset(void)238 void ajReset(void)
239 {
240 #ifdef WIN32
241     WSACleanup();
242 #endif /* WIN32 */
243     ajDebug("\nFinal Summary\n=============\n\n");
244     ajBtreeExit();
245     ajSqlExit();
246     ajMatrixExit();
247     ajTreeExit();
248     ajPdbExit();
249     ajDmxExit();
250     ajDomainExit();
251     ajQueryExit();
252     ajTextExit();
253     ajFeatExit();
254     ajSeqExit();
255     ajOboExit();
256     ajAssemExit();
257     ajRefseqExit();
258     ajTaxExit();
259     ajUrlExit();
260     ajVarExit();
261     ajXmlExit();
262     ajResourceExit();
263     ajPhyloExit();
264     ajNexusExit();
265     ajAlignExit();
266     ajReportExit();
267     ajNamExit();
268     ajSysExit();
269     ajCallExit();
270     ajBaseExit();
271     ajCodExit();
272     ajTrnExit();
273     ajMeltExit();
274     ajTimeExit();
275     ajRegExit();
276     ajArrExit();
277     ajDatafileExit();
278     ajFileExit();
279     ajListExit();
280     ajMessExit();
281     ajTableExit();
282     ajStrExit();
283     ajMemExit();
284     ajMessExitDebug();     /* clears data for ajDebug - do this last!!!  */
285 
286     return;
287 }
288 
289 
290 
291 
292 /* @datasection [none] Byte manipulation functions ****************************
293 **
294 ** @nam2rule  Byte          Manipulate a byte of data.
295 **
296 ******************************************************************************/
297 
298 
299 
300 
301 /* @section byte manipulation functions  **************************************
302 **
303 ** Functions for manipulating bytes.
304 **
305 ** @fdata [none]
306 **
307 ** @nam3rule  Rev       Reverse the byte order.
308 ** @nam4rule  RevLen2      Reverse the byte order in a 2 byte integer.
309 ** @nam4rule  RevLen4      Reverse the byte order in a 4 byte integer.
310 ** @nam4rule  RevLen8      Reverse the byte order in a 8 byte integer.
311 ** @nam4rule  RevLen2u      Reverse the byte order in a 2 byte unsigned integer.
312 ** @nam4rule  RevLen4u      Reverse the byte order in a 4 byte unsigned integer.
313 ** @nam4rule  RevLen8u      Reverse the byte order in a 8 byte unsigned integer.
314 ** @nam4rule  RevInt    Reverse the byte order in an integer.
315 ** @nam4rule  RevShort  Reverse the byte order in a short integer.
316 ** @nam4rule  RevLong   Reverse the byte order in a long.
317 ** @nam4rule  RevUint    Reverse the byte order in an unsigned integer.
318 ** @nam4rule  RevUlong   Reverse the byte order in an unsigned long.
319 **
320 ** @argrule   RevLen2  sval [ajshort*] Short to be reversed
321 ** @argrule   RevLen4  ival [ajint*] Integer to be reversed
322 ** @argrule   RevLen8  lval [ajlong*] Long integer to be reversed
323 ** @argrule   RevLen2u  sval [ajushort*] Unsigned short to be reversed
324 ** @argrule   RevLen4u  ival [ajuint*] Unsigned integer to be reversed
325 ** @argrule   RevLen8u  lval [ajulong*] Unsigned long integer to be reversed
326 ** @argrule   RevShort sval [ajshort*] Short to be reversed
327 ** @argrule   RevInt   ival [ajint*] Integer to be reversed
328 ** @argrule   RevLong  lval [ajlong*] Long integer to be reversed
329 ** @argrule   RevUint  ival [ajuint*] Unsigned integer to be reversed
330 ** @argrule   RevUlong lval [ajulong*] Unsigned long integer to be reversed
331 **
332 ** @valrule   *  [void]
333 **
334 ** @fcategory misc
335 **
336 ******************************************************************************/
337 
338 
339 
340 
341 /* @func ajByteRevInt *********************************************************
342 **
343 ** Reverses the byte order in an integer.
344 **
345 ** @param [u] ival [ajint*] Integer in wrong byte order.
346 **                        Returned in correct order.
347 ** @return [void]
348 **
349 ** @release 5.0.0
350 ** @@
351 ******************************************************************************/
352 
ajByteRevInt(ajint * ival)353 void ajByteRevInt(ajint* ival)
354 {
355     union lbytes
356     {
357         char chars[8];
358         ajint i;
359     } data, revdata;
360 
361     char* cs;
362     char* cd;
363     ajuint i;
364 
365     data.i = *ival;
366     cs     = data.chars;
367     cd     = &revdata.chars[sizeof(ajint)-1];
368 
369     for(i=0; i < sizeof(ajint); i++)
370     {
371         *cd = *cs++;
372         --cd;
373     }
374 
375     *ival = revdata.i;
376 
377     return;
378 }
379 
380 
381 
382 
383 /* @func ajByteRevLen2 ********************************************************
384 **
385 ** Reverses the byte order in a 2 byte integer.
386 **
387 ** Intended for cases where the number of bytes is known, for
388 ** example when reading a binary file.
389 **
390 ** @param [u] sval [ajshort*] Short integer in wrong byte order.
391 **                          Returned in correct order.
392 ** @return [void]
393 **
394 ** @release 5.0.0
395 ** @@
396 ******************************************************************************/
397 
ajByteRevLen2(ajshort * sval)398 void ajByteRevLen2(ajshort* sval)
399 {
400     union lbytes
401     {
402         char chars[2];
403         ajshort s;
404     } data, revdata;
405 
406     char* cs;
407     char* cd;
408     ajint i;
409 
410     data.s = *sval;
411     cs     = data.chars;
412     cd     = &revdata.chars[1];
413 
414     for(i=0; i < 2; i++)
415     {
416         *cd = *cs++;
417         --cd;
418     }
419 
420     *sval = revdata.s;
421 
422     return;
423 }
424 
425 
426 
427 
428 /* @func ajByteRevLen2u *******************************************************
429 **
430 ** Reverses the byte order in a 2 byte integer.
431 **
432 ** Intended for cases where the number of bytes is known, for
433 ** example when reading a binary file.
434 **
435 ** @param [u] sval [ajushort*] Short integer in wrong byte order.
436 **                          Returned in correct order.
437 ** @return [void]
438 **
439 ** @release 6.2.0
440 ** @@
441 ******************************************************************************/
442 
ajByteRevLen2u(ajushort * sval)443 void ajByteRevLen2u(ajushort* sval)
444 {
445     union lbytes
446     {
447         char chars[2];
448         ajushort s;
449     } data, revdata;
450 
451     char* cs;
452     char* cd;
453     ajint i;
454 
455     data.s = *sval;
456     cs     = data.chars;
457     cd     = &revdata.chars[1];
458 
459     for(i=0; i < 2; i++)
460     {
461         *cd = *cs++;
462         --cd;
463     }
464 
465     *sval = revdata.s;
466 
467     return;
468 }
469 
470 
471 
472 
473 /* @func ajByteRevLen4 ********************************************************
474 **
475 ** Reverses the byte order in a 4 byte integer.
476 **
477 ** Intended for cases where the number of bytes is known, for
478 ** example when reading a binary file.
479 **
480 ** @param [u] ival [ajint*] Integer in wrong byte order.
481 **                        Returned in correct order.
482 ** @return [void]
483 **
484 ** @release 5.0.0
485 ** @@
486 ******************************************************************************/
487 
ajByteRevLen4(ajint * ival)488 void ajByteRevLen4(ajint* ival)
489 {
490     union lbytes
491     {
492         char chars[4];
493         ajint i;
494     } data, revdata;
495 
496     char* cs;
497     char* cd;
498     ajint i;
499 
500     data.i = *ival;
501     cs     = data.chars;
502     cd     = &revdata.chars[3];
503 
504     for(i=0; i < 4; i++)
505     {
506         *cd = *cs++;
507         --cd;
508     }
509 
510     *ival = revdata.i;
511 
512     return;
513 }
514 
515 
516 
517 
518 /* @func ajByteRevLen4u *******************************************************
519 **
520 ** Reverses the byte order in a 4 byte integer.
521 **
522 ** Intended for cases where the number of bytes is known, for
523 ** example when reading a binary file.
524 **
525 ** @param [u] ival [ajuint*] Integer in wrong byte order.
526 **                        Returned in correct order.
527 ** @return [void]
528 **
529 ** @release 6.2.0
530 ** @@
531 ******************************************************************************/
532 
ajByteRevLen4u(ajuint * ival)533 void ajByteRevLen4u(ajuint* ival)
534 {
535     union lbytes
536     {
537         char chars[4];
538         ajuint i;
539     } data, revdata;
540 
541     char* cs;
542     char* cd;
543     ajint i;
544 
545     data.i = *ival;
546     cs     = data.chars;
547     cd     = &revdata.chars[3];
548 
549     for(i=0; i < 4; i++)
550     {
551         *cd = *cs++;
552         --cd;
553     }
554 
555     *ival = revdata.i;
556 
557     return;
558 }
559 
560 
561 
562 
563 /* @func ajByteRevLen8 ********************************************************
564 **
565 ** Reverses the byte order in an 8 byte long.
566 **
567 ** Intended for cases where the number of bytes is known, for
568 ** example when reading a binary file.
569 **
570 ** @param [u] lval [ajlong*] Integer in wrong byte order.
571 **                           Returned in correct order.
572 ** @return [void]
573 **
574 ** @release 5.0.0
575 ** @@
576 ******************************************************************************/
577 
ajByteRevLen8(ajlong * lval)578 void ajByteRevLen8(ajlong* lval)
579 {
580     union lbytes
581     {
582         char chars[8];
583         ajlong l;
584     } data, revdata;
585 
586     char* cs;
587     char* cd;
588     ajint i;
589 
590     data.l = *lval;
591     cs     = data.chars;
592     cd     = &revdata.chars[7];
593 
594     for(i=0; i < 8; i++)
595     {
596         *cd = *cs++;
597         --cd;
598     }
599 
600     *lval = revdata.l;
601 
602     return;
603 }
604 
605 
606 
607 
608 /* @func ajByteRevLen8u *******************************************************
609 **
610 ** Reverses the byte order in an 8 byte long.
611 **
612 ** Intended for cases where the number of bytes is known, for
613 ** example when reading a binary file.
614 **
615 ** @param [u] lval [ajulong*] Integer in wrong byte order.
616 **                           Returned in correct order.
617 ** @return [void]
618 **
619 ** @release 6.2.0
620 ** @@
621 ******************************************************************************/
622 
ajByteRevLen8u(ajulong * lval)623 void ajByteRevLen8u(ajulong* lval)
624 {
625     union lbytes
626     {
627         char chars[8];
628         ajulong l;
629     } data, revdata;
630 
631     char* cs;
632     char* cd;
633     ajint i;
634 
635     data.l = *lval;
636     cs     = data.chars;
637     cd     = &revdata.chars[7];
638 
639     for(i=0; i < 8; i++)
640     {
641         *cd = *cs++;
642         --cd;
643     }
644 
645     *lval = revdata.l;
646 
647     return;
648 }
649 
650 
651 
652 
653 /* @func ajByteRevLong ********************************************************
654 **
655 ** Reverses the byte order in a long.
656 **
657 ** @param [u] lval [ajlong*] Integer in wrong byte order.
658 **                           Returned in correct order.
659 ** @return [void]
660 **
661 ** @release 5.0.0
662 ** @@
663 ******************************************************************************/
664 
ajByteRevLong(ajlong * lval)665 void ajByteRevLong(ajlong* lval)
666 {
667     union lbytes
668     {
669         char chars[8];
670         ajlong l;
671     } data, revdata;
672 
673     char* cs;
674     char* cd;
675     ajuint i;
676 
677     data.l = *lval;
678     cs     = data.chars;
679     cd     = &revdata.chars[sizeof(ajlong)-1];
680 
681     for(i=0; i < sizeof(ajlong); i++)
682     {
683         *cd = *cs++;
684         --cd;
685     }
686 
687     *lval = revdata.l;
688 
689     return;
690 }
691 
692 
693 
694 
695 /* @func ajByteRevShort *******************************************************
696 **
697 ** Reverses the byte order in a short integer.
698 **
699 ** @param [u] sval [ajshort*] Short integer in wrong byte order.
700 **                          Returned in correct order.
701 ** @return [void]
702 **
703 ** @release 5.0.0
704 ** @@
705 ******************************************************************************/
706 
ajByteRevShort(ajshort * sval)707 void ajByteRevShort(ajshort* sval)
708 {
709     union lbytes
710     {
711         char chars[8];
712         short s;
713     } data, revdata;
714 
715     char* cs;
716     char* cd;
717     ajuint i;
718 
719     data.s = *sval;
720     cs     = data.chars;
721     cd     = &revdata.chars[sizeof(ajshort)-1];
722 
723     for(i=0; i < sizeof(ajshort); i++)
724     {
725         *cd = *cs++;
726         --cd;
727     }
728 
729     *sval = revdata.s;
730 
731     return;
732 }
733 
734 
735 
736 
737 /* @func ajByteRevUint ********************************************************
738 **
739 ** Reverses the byte order in an unsigned integer.
740 **
741 ** @param [u] ival [ajuint*] Unsigned integer in wrong byte order.
742 **                        Returned in correct order.
743 ** @return [void]
744 **
745 ** @release 5.0.0
746 ** @@
747 ******************************************************************************/
748 
ajByteRevUint(ajuint * ival)749 void ajByteRevUint(ajuint* ival)
750 {
751     union lbytes
752     {
753         char chars[8];
754         ajuint i;
755     } data, revdata;
756 
757     char* cs;
758     char* cd;
759     ajuint i;
760 
761     data.i = *ival;
762     cs     = data.chars;
763     cd     = &revdata.chars[sizeof(ajuint)-1];
764 
765     for(i=0; i < sizeof(ajuint); i++)
766     {
767         *cd = *cs++;
768         --cd;
769     }
770 
771     *ival = revdata.i;
772 
773     return;
774 }
775 
776 
777 
778 
779 /* @func ajByteRevUlong *******************************************************
780 **
781 ** Reverses the byte order in an unsigned long.
782 **
783 ** @param [u] lval [ajulong*] Integer in wrong byte order.
784 **                           Returned in correct order.
785 ** @return [void]
786 **
787 ** @release 6.4.0
788 ** @@
789 ******************************************************************************/
790 
ajByteRevUlong(ajulong * lval)791 void ajByteRevUlong(ajulong* lval)
792 {
793     union lbytes
794     {
795         char chars[8];
796         ajulong l;
797     } data, revdata;
798 
799     char* cs;
800     char* cd;
801     ajuint i;
802 
803     data.l = *lval;
804     cs     = data.chars;
805     cd     = &revdata.chars[sizeof(ajulong)-1];
806 
807     for(i=0; i < sizeof(ajulong); i++)
808     {
809         *cd = *cs++;
810         --cd;
811     }
812 
813     *lval = revdata.l;
814 
815     return;
816 }
817 
818 
819 
820 
821 /* @datasection [none]  Miscellaneous utility functions ***********************
822 **
823 ** Miscellaneous utility functions.
824 **
825 ** @nam2rule  Util           Miscellaneous utility functions.
826 **
827 ******************************************************************************/
828 
829 
830 
831 
832 /* @section Miscellaneous utility functions ***********************************
833 **
834 ** Miscellaneous utility functions.
835 **
836 ** @fdata [none]
837 **
838 ** @nam3rule  Base64     Base-64 encode/decode functions
839 ** @nam4rule  Decode     Base-64 decode
840 ** @nam4rule  Encode     Base-64 encode
841 ** @nam3rule  Catch      Dummy function to be called in special cases so
842 **                       it can be used when debugging in GDB.
843 ** @nam3rule  Get        Retrieve system information
844 ** @nam4rule  GetBigendian  Tests whether the host system uses big endian
845 **                          byte order.
846 ** @nam4rule  GetUid        Returns the user's userid.
847 **
848 ** @nam3rule  Loginfo    If a log file is in use, writes run details to
849 **                       end of file.
850 ** @suffix C Character string input
851 **
852 ** @argrule   GetUid  Puid [AjPStr*] User's userid
853 ** @argrule   Decode  Pdest [AjPStr*] Decoded string
854 ** @argrule   Decode  src [const char*] Encoded input string
855 ** @argrule   Encode  Pdest [AjPStr*] Decoded string
856 ** @argrule   Encode  size [size_t] Length of input string
857 ** @argrule   Encode  src [const unsigned char*] Input string
858 **
859 ** @valrule   *  [void]
860 ** @valrule   *Decode  [size_t] Length of encoded string
861 ** @valrule   *Encode  [AjBool] True if operation was successful.
862 ** @valrule   *Get  [AjBool] True if operation was successful.
863 **
864 ** @fcategory misc
865 **
866 ******************************************************************************/
867 
868 
869 
870 
871 /* @func ajUtilBase64DecodeC **************************************************
872 **
873 ** Decode a base 64 string
874 **
875 ** @param [w] Pdest [AjPStr*] Decoded string
876 ** @param [r] src [const char*] source base64 string
877 ** @return [size_t] Length of decoded string (zero if decode error)
878 **
879 ** @release 6.4.0
880 ** @@
881 ******************************************************************************/
882 
ajUtilBase64DecodeC(AjPStr * Pdest,const char * src)883 size_t ajUtilBase64DecodeC(AjPStr *Pdest, const char *src)
884 {
885     unsigned char *buf = NULL;
886     size_t srclen;
887     size_t i,j;
888     char c1 = 'A';
889     char c2 = 'A';
890     char c3 = 'A';
891     char c4 = 'A';
892     unsigned char b1 = 0;
893     unsigned char b2 = 0;
894     unsigned char b3 = 0;
895     unsigned char b4 = 0;
896 
897     if(!src)
898         return 0;
899 
900     if(!*src)
901         return 0;
902 
903     if(!Pdest)
904         return 0;
905 
906     if(!*Pdest)
907         *Pdest = ajStrNew();
908 
909     ajStrSetClear(Pdest);
910 
911     srclen = strlen(src);
912 
913     buf = (unsigned char *) ajCharNewRes(srclen);
914 
915     /* Ignore non-base64 chars */
916     for(i = 0, j = 0; src[i]; ++i)
917         if(utilIsBase64(src[i]))
918             buf[j++] = src[i];
919 
920     for(i = 0; i < j; i += 4)
921     {
922         c1 = buf[i];
923 
924         if(i+1 < j)
925             c2 = buf[i+1];
926 
927         if(i+2 < j)
928             c3 = buf[i+2];
929 
930         if(i+3 < j)
931             c4 = buf[i+3];
932 
933 
934       b1 = utilBase64Decode(c1);
935       b2 = utilBase64Decode(c2);
936       b3 = utilBase64Decode(c3);
937       b4 = utilBase64Decode(c4);
938 
939       ajStrAppendK(Pdest, ((b1<<2)|(b2>>4)));
940 
941       if(c3 != '=')
942           ajStrAppendK(Pdest, (((b2&0xf)<<4)|(b3>>2)));
943 
944       if(c4 != '=')
945           ajStrAppendK(Pdest, (((b3&0x3)<<6)|b4));
946     }
947 
948     AJFREE(buf);
949 
950     return ajStrGetLen(*Pdest);
951 
952 }
953 
954 
955 
956 
957 /* @func ajUtilBase64EncodeC **************************************************
958 **
959 ** Decode a base 64 string
960 **
961 ** @param [u] Pdest [AjPStr*] Encoded string
962 ** @param [r] size [size_t] Size of data to encode
963 ** @param [r] src [const unsigned char *] source data
964 ** @return [AjBool] True on success
965 **
966 ** @release 6.4.0
967 ** @@
968 ******************************************************************************/
969 
ajUtilBase64EncodeC(AjPStr * Pdest,size_t size,const unsigned char * src)970 AjBool ajUtilBase64EncodeC(AjPStr *Pdest, size_t size, const unsigned char *src)
971 {
972     size_t i;
973     unsigned char b1 = 0;
974     unsigned char b2 = 0;
975     unsigned char b3 = 0;
976     unsigned char b4 = 0;
977     unsigned char b5 = 0;
978     unsigned char b6 = 0;
979     unsigned char b7 = 0;
980 
981     if(!src)
982         return ajFalse;
983 
984     if(!Pdest)
985         return ajFalse;
986 
987     if(!*Pdest)
988         return ajFalse;
989 
990     if(!size)
991         size = strlen((const char *)src);
992 
993 
994     for(i = 0; i < size; i += 3)
995     {
996         b1 = src[i];
997 
998         if(i+1 < size)
999             b2 = src[i+1];
1000 
1001         if(i+2 < size)
1002             b3 = src[i+2];
1003 
1004         b4 = b1 >> 2;
1005         b5 = ((b1 & 0x3) << 4) | (b2 >> 4);
1006         b6 = ((b2 & 0xf) << 2) | (b3 >> 6);
1007         b7 = b3 & 0x3f;
1008 
1009         ajStrAppendK(Pdest, utilBase64Encode(b4));
1010         ajStrAppendK(Pdest, utilBase64Encode(b5));
1011 
1012         if(i+1 < size)
1013             ajStrAppendK(Pdest, utilBase64Encode(b6));
1014         else
1015             ajStrAppendK(Pdest, '=');
1016 
1017         if(i+2 < size)
1018             ajStrAppendK(Pdest, utilBase64Encode(b7));
1019         else
1020             ajStrAppendK(Pdest, '=');
1021     }
1022 
1023     return ajTrue;
1024 }
1025 
1026 
1027 
1028 
1029 /* @funcstatic utilIsBase64 ***************************************************
1030 **
1031 ** Test for valid base 64 character
1032 **
1033 ** @param [r] c [char] Character
1034 ** @return [AjBool] True if valid base64 character
1035 **
1036 ** @release 6.4.0
1037 ** @@
1038 ******************************************************************************/
1039 
utilIsBase64(char c)1040 static AjBool utilIsBase64(char c)
1041 {
1042 
1043     if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
1044        (c >= '0' && c <= '9') || (c == '+')             ||
1045        (c == '/')             || (c == '='))
1046         return ajTrue;
1047 
1048     return ajFalse;
1049 }
1050 
1051 
1052 
1053 
1054 /* @funcstatic utilBase64Encode ***********************************************
1055 **
1056 ** Encode one byte to base 64
1057 **
1058 ** @param [r] u [unsigned char] Character
1059 ** @return [char] Encoded character
1060 **
1061 ** @release 6.4.0
1062 ** @@
1063 ******************************************************************************/
1064 
utilBase64Encode(unsigned char u)1065 static char utilBase64Encode(unsigned char u)
1066 {
1067 
1068     if(u < 26)
1069         return 'A' + u;
1070 
1071     if(u < 52)
1072         return 'a' + (u-26);
1073 
1074     if(u < 62)
1075         return '0' + (u-52);
1076 
1077     if(u == 62)
1078         return '+';
1079 
1080     return '/';
1081 }
1082 
1083 
1084 
1085 
1086 /* @funcstatic utilBase64Decode ***********************************************
1087 **
1088 ** Decode one byte from base 64
1089 **
1090 ** @param [r] c [char] Character
1091 ** @return [unsigned char] Decoded character
1092 **
1093 ** @release 6.4.0
1094 ** @@
1095 ******************************************************************************/
1096 
utilBase64Decode(char c)1097 static unsigned char utilBase64Decode(char c)
1098 {
1099 
1100     if(c >= 'A' && c <= 'Z')
1101         return(c - 'A');
1102 
1103     if(c >= 'a' && c <= 'z')
1104         return(c - 'a' + 26);
1105 
1106     if(c >= '0' && c <= '9')
1107         return(c - '0' + 52);
1108 
1109     if(c == '+')
1110         return 62;
1111 
1112     return 63;
1113 }
1114 
1115 
1116 
1117 
1118 /* @func ajUtilCatch **********************************************************
1119 **
1120 ** Dummy function to be called in special cases so it can be used when
1121 ** debugging in GDB.
1122 **
1123 ** To use, simply put a call to ajUtilCatch() into your code, and use
1124 ** "break ajUtilCatch" in gdb to get a traceback.
1125 **
1126 ** @return [void]
1127 **
1128 ** @release 2.5.0
1129 ** @@
1130 ******************************************************************************/
1131 
ajUtilCatch(void)1132 void ajUtilCatch(void)
1133 {
1134     static ajint calls = 0;
1135 
1136     calls = calls + 1;
1137 
1138     return;
1139 }
1140 
1141 
1142 
1143 
1144 /* @func ajUtilGetBigendian ***************************************************
1145 **
1146 ** Tests whether the host system uses big endian byte order.
1147 **
1148 ** @return [AjBool] ajTrue if host is big endian.
1149 **
1150 ** @release 5.0.0
1151 ** @@
1152 ******************************************************************************/
1153 
ajUtilGetBigendian(void)1154 AjBool ajUtilGetBigendian(void)
1155 {
1156     static union lbytes
1157     {
1158         char chars[sizeof(ajint)];
1159         ajint i;
1160     } data;
1161 
1162     if(!utilBigendCalled)
1163     {
1164         utilBigendCalled = 1;
1165         data.i           = 0;
1166         data.chars[0]    = '\1';
1167 
1168         if(data.i == 1)
1169             utilBigendian = ajFalse;
1170         else
1171             utilBigendian = ajTrue;
1172     }
1173 
1174     return utilBigendian;
1175 }
1176 
1177 
1178 
1179 
1180 /* @func ajUtilGetUid *********************************************************
1181 **
1182 ** Returns the user's userid
1183 **
1184 ** @param [w] Puid [AjPStr*] String to return result
1185 ** @return [AjBool] ajTrue on success
1186 **
1187 ** @release 5.0.0
1188 ** @@
1189 ******************************************************************************/
1190 
ajUtilGetUid(AjPStr * Puid)1191 AjBool ajUtilGetUid(AjPStr* Puid)
1192 {
1193 #ifndef WIN32
1194     ajint uid;
1195     struct passwd* pwd;
1196 
1197     ajDebug("ajUtilUid\n");
1198 
1199     uid = getuid();
1200 
1201     if(!uid)
1202     {
1203         ajStrAssignClear(Puid);
1204 
1205         return ajFalse;
1206     }
1207 
1208     ajDebug("  uid: %d\n", uid);
1209     pwd = getpwuid(uid);
1210 
1211     if(!pwd)
1212     {
1213         ajStrAssignClear(Puid);
1214 
1215         return ajFalse;
1216     }
1217 
1218     ajDebug("  pwd: '%s'\n", pwd->pw_name);
1219 
1220     ajStrAssignC(Puid, pwd->pw_name);
1221 
1222     return ajTrue;
1223 
1224 #else /* WIN32 */
1225     char nameBuf[UNLEN+1];
1226     DWORD nameLen = UNLEN+1;
1227 
1228     ajDebug("ajUtilUid\n");
1229 
1230     if (GetUserName(nameBuf, &nameLen))
1231     {
1232         ajDebug("  pwd: '%s'\n", nameBuf);
1233         ajStrAssignC(Puid, nameBuf);
1234 
1235         return ajTrue;
1236     }
1237 
1238     ajStrAssignC(Puid, "");
1239 
1240     return ajFalse;
1241 #endif /* !WIN32 */
1242 }
1243 
1244 
1245 
1246 
1247 /* @func ajUtilLoginfo ********************************************************
1248 **
1249 ** If a log file is in use, writes run details to end of file.
1250 **
1251 ** @return [void]
1252 **
1253 ** @release 5.0.0
1254 ** @@
1255 ******************************************************************************/
1256 
ajUtilLoginfo(void)1257 void ajUtilLoginfo(void)
1258 {
1259     AjPFile logf;
1260     AjPStr logfname = NULL;
1261     AjPStr uids    = NULL;
1262     AjPTime today = NULL;
1263     double walltime;
1264     double cputime;
1265 
1266     today = ajTimeNewTodayFmt("log");
1267 
1268     if(ajNamGetValueC("logfile", &logfname))
1269     {
1270         logf = ajFileNewOutappendNameS(logfname);
1271 
1272         if(!logf)
1273             return;
1274 
1275         walltime = ajTimeDiff(ajTimeRefToday(),today);
1276         cputime = ajClockSeconds();
1277 
1278         if(walltime < cputime)
1279             walltime = cputime; /* avoid reporting 0.0 if cpu time appears */
1280 
1281         ajUtilGetUid(&uids),
1282             ajFmtPrintF(logf, "%S\t%S\t%D\t%.1f\t%.1f\n",
1283                         ajUtilGetProgram(),
1284                         uids,
1285                         today,
1286                         cputime, walltime);
1287         ajStrDel(&uids);
1288         ajStrDel(&logfname);
1289         ajFileClose(&logf);
1290     }
1291 
1292 
1293     ajTimeDel(&today);
1294 
1295     return;
1296 }
1297 
1298 
1299 
1300 
1301 /* @section provenance ********************************************************
1302 **
1303 ** Functions providing information about the run-time environment
1304 **
1305 ** @fdata [none]
1306 **
1307 ** @nam3rule Get Return data as a string
1308 ** @nam4rule GetCmdline Return the full commandline equivalent
1309 ** @nam4rule GetInputs Return the full commandline equivalent
1310 ** @nam4rule GetProgram Return the program name
1311 **
1312 ** @valrule * [const AjPStr]
1313 ** @fcategory misc
1314 **
1315 ******************************************************************************/
1316 
1317 
1318 
1319 
1320 /* @func ajUtilGetCmdline *****************************************************
1321 **
1322 ** Returns the original command line as qualifiers and values with newline
1323 ** delimiters
1324 **
1325 ** @return [const AjPStr] Commandline with newlines between qualifiers
1326 ** and parameters
1327 **
1328 ** @release 6.2.0
1329 ******************************************************************************/
1330 
ajUtilGetCmdline(void)1331 const AjPStr ajUtilGetCmdline (void)
1332 {
1333     return acdArgSave;
1334 }
1335 
1336 
1337 
1338 
1339 /* @func ajUtilGetInputs ******************************************************
1340 **
1341 ** Returns the user non-default inputs in commandline form
1342 **
1343 ** @return [const AjPStr] Commandline with newlines between qualifiers
1344 ** and parameters
1345 **
1346 ** @release 6.2.0
1347 ******************************************************************************/
1348 
ajUtilGetInputs(void)1349 const AjPStr ajUtilGetInputs (void)
1350 {
1351     return acdInputSave;
1352 }
1353 
1354 
1355 
1356 
1357 /* @func ajUtilGetProgram *****************************************************
1358 **
1359 ** Returns the application (program) name from the ACD definition.
1360 **
1361 ** @return [const AjPStr] Program name
1362 **
1363 ** @release 6.2.0
1364 ** @@
1365 ******************************************************************************/
1366 
ajUtilGetProgram(void)1367 const AjPStr ajUtilGetProgram(void)
1368 {
1369     return acdProgram;
1370 }
1371 
1372 
1373 
1374 
1375 #ifdef AJ_COMPILE_DEPRECATED_BOOK
1376 #endif /* AJ_COMPILE_DEPRECATED_BOOK */
1377 
1378 
1379 
1380 
1381 
1382 #ifdef AJ_COMPILE_DEPRECATED
1383 /* @obsolete ajUtilRevInt
1384 ** @rename ajByteRevInt
1385 */
1386 
ajUtilRevInt(ajint * ival)1387 __deprecated void ajUtilRevInt(ajint* ival)
1388 {
1389     ajByteRevInt(ival);
1390 
1391     return;
1392 }
1393 
1394 
1395 
1396 
1397 /* @obsolete ajUtilRev2
1398 ** @rename ajByteRev2
1399 */
1400 
ajUtilRev2(ajshort * sval)1401 __deprecated void ajUtilRev2(ajshort* sval)
1402 {
1403     ajByteRevLen2(sval);
1404 
1405     return;
1406 }
1407 
1408 
1409 
1410 
1411 /* @obsolete ajUtilRev4
1412 ** @rename ajByteRevLen4
1413 */
1414 
ajUtilRev4(ajint * ival)1415 __deprecated void ajUtilRev4(ajint* ival)
1416 {
1417     ajByteRevLen4(ival);
1418 
1419     return;
1420 }
1421 
1422 
1423 
1424 
1425 /* @obsolete ajUtilRev8
1426 ** @rename ajByteRevLen8
1427 */
1428 
ajUtilRev8(ajlong * lval)1429 __deprecated void ajUtilRev8(ajlong* lval)
1430 {
1431     ajByteRevLen8(lval);
1432 }
1433 
1434 
1435 
1436 
1437 /* @obsolete ajUtilRevLong
1438 ** @rename ajByteRevLong
1439 */
1440 
ajUtilRevLong(ajlong * lval)1441 __deprecated void ajUtilRevLong(ajlong* lval)
1442 {
1443     ajByteRevLong(lval);
1444 
1445     return;
1446 }
1447 
1448 
1449 
1450 
1451 /* @obsolete ajUtilRevShort
1452 ** @rename ajByteRevShort
1453 */
1454 
ajUtilRevShort(ajshort * sval)1455 __deprecated void ajUtilRevShort(ajshort* sval)
1456 {
1457     ajByteRevShort(sval);
1458 }
1459 
1460 
1461 
1462 
1463 /* @obsolete ajUtilRevUint
1464 ** @rename ajByteRevUint
1465 */
1466 
ajUtilRevUint(ajuint * ival)1467 __deprecated void ajUtilRevUint(ajuint* ival)
1468 {
1469     ajByteRevUint(ival);
1470 }
1471 
1472 
1473 
1474 
1475 /* @obsolete ajUtilBigendian
1476 ** @rename ajUtilGetBigendian
1477 */
ajUtilBigendian(void)1478 __deprecated AjBool ajUtilBigendian(void)
1479 {
1480     return ajUtilGetBigendian();
1481 }
1482 
1483 
1484 
1485 
1486 /* @obsolete ajUtilUid
1487 ** @rename ajUtilGetUid
1488 */
1489 
ajUtilUid(AjPStr * dest)1490 __deprecated AjBool ajUtilUid(AjPStr* dest)
1491 {
1492     return ajUtilGetUid(dest);
1493 }
1494 
1495 
1496 
1497 
1498 /* @obsolete ajLogInfo
1499 ** @rename ajUtilLoginfo
1500 */
1501 
ajLogInfo(void)1502 __deprecated void ajLogInfo(void)
1503 {
1504     ajUtilLoginfo();
1505 
1506     return;
1507 }
1508 
1509 
1510 
1511 
1512 /* @obsolete ajAcdGetCmdline
1513 ** @rename ajUtilGetCmdline
1514 */
ajAcdGetCmdline(void)1515 __deprecated const AjPStr ajAcdGetCmdline (void)
1516 {
1517     return ajUtilGetCmdline();
1518 }
1519 
1520 
1521 
1522 
1523 /* @obsolete ajAcdGetInputs
1524 ** @rename ajUtilGetInputs
1525 */
1526 
ajAcdGetInputs(void)1527 __deprecated const AjPStr ajAcdGetInputs (void)
1528 {
1529     return ajUtilGetInputs();
1530 }
1531 
1532 
1533 
1534 
1535 /* @obsolete ajAcdProgramS
1536 ** @remove Use ajAcdGetProgram
1537 */
1538 
ajAcdProgramS(AjPStr * pgm)1539 __deprecated void  ajAcdProgramS(AjPStr* pgm)
1540 {
1541     ajStrAssignS(pgm, acdProgram);
1542     return;
1543 }
1544 
1545 
1546 
1547 
1548 /* @obsolete ajAcdGetProgram
1549 ** @rename ajUtilGetProgram
1550 */
ajAcdGetProgram(void)1551 __deprecated const AjPStr ajAcdGetProgram(void)
1552 {
1553     return ajUtilGetProgram();
1554 }
1555 
1556 
1557 
1558 
1559 /* @obsolete ajAcdProgram
1560 ** @remove Use ajAcdGetProgram
1561 */
1562 
ajAcdProgram(void)1563 __deprecated const char*  ajAcdProgram(void)
1564 {
1565     return ajStrGetPtr(acdProgram);
1566 }
1567 
1568 #endif /* AJ_COMPILE_DEPRECATED */
1569