utility.c revision ea7bce9563dfc51a604fe8f65606959e3d08e577
1/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3%                                                                             %
4%                                                                             %
5%                                                                             %
6%             U   U  TTTTT  IIIII  L      IIIII  TTTTT  Y   Y                 %
7%             U   U    T      I    L        I      T     Y Y                  %
8%             U   U    T      I    L        I      T      Y                   %
9%             U   U    T      I    L        I      T      Y                   %
10%              UUU     T    IIIII  LLLLL  IIIII    T      Y                   %
11%                                                                             %
12%                                                                             %
13%                       MagickCore Utility Methods                            %
14%                                                                             %
15%                             Software Design                                 %
16%                               John Cristy                                   %
17%                              January 1993                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization      %
21%  dedicated to making software imaging solutions freely available.           %
22%                                                                             %
23%  You may not use this file except in compliance with the License.  You may  %
24%  obtain a copy of the License at                                            %
25%                                                                             %
26%    http://www.imagemagick.org/script/license.php                            %
27%                                                                             %
28%  Unless required by applicable law or agreed to in writing, software        %
29%  distributed under the License is distributed on an "AS IS" BASIS,          %
30%  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31%  See the License for the specific language governing permissions and        %
32%  limitations under the License.                                             %
33%                                                                             %
34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35%
36%
37*/
38
39/*
40  Include declarations.
41*/
42#include "MagickCore/studio.h"
43#include "MagickCore/property.h"
44#include "MagickCore/blob.h"
45#include "MagickCore/color.h"
46#include "MagickCore/exception.h"
47#include "MagickCore/exception-private.h"
48#include "MagickCore/geometry.h"
49#include "MagickCore/list.h"
50#include "MagickCore/log.h"
51#include "MagickCore/magick-private.h"
52#include "MagickCore/memory_.h"
53#include "MagickCore/nt-base-private.h"
54#include "MagickCore/option.h"
55#include "MagickCore/policy.h"
56#include "MagickCore/resource_.h"
57#include "MagickCore/semaphore.h"
58#include "MagickCore/signature-private.h"
59#include "MagickCore/statistic.h"
60#include "MagickCore/string_.h"
61#include "MagickCore/string-private.h"
62#include "MagickCore/token.h"
63#include "MagickCore/token-private.h"
64#include "MagickCore/utility.h"
65#include "MagickCore/utility-private.h"
66#if defined(MAGICKCORE_HAVE_PROCESS_H)
67#include <process.h>
68#endif
69#if defined(MAGICKCORE_HAVE_MACH_O_DYLD_H)
70#include <mach-o/dyld.h>
71#endif
72
73/*
74  Static declarations.
75*/
76static const char
77  Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
78
79/*
80  Forward declaration.
81*/
82static int
83  IsPathDirectory(const char *);
84
85/*
86%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
87%                                                                             %
88%                                                                             %
89%                                                                             %
90%   A c q u i r e U n i q u e F i l e n a m e                                 %
91%                                                                             %
92%                                                                             %
93%                                                                             %
94%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95%
96%  AcquireUniqueFilename() replaces the contents of path by a unique path name.
97%
98%  The format of the AcquireUniqueFilename method is:
99%
100%      MagickBooleanType AcquireUniqueFilename(char *path)
101%
102%  A description of each parameter follows.
103%
104%   o  path:  Specifies a pointer to an array of characters.  The unique path
105%      name is returned in this array.
106%
107*/
108MagickExport MagickBooleanType AcquireUniqueFilename(char *path)
109{
110  int
111    file;
112
113  file=AcquireUniqueFileResource(path);
114  if (file == -1)
115    return(MagickFalse);
116  file=close(file)-1;
117  return(MagickTrue);
118}
119
120/*
121%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
122%                                                                             %
123%                                                                             %
124%                                                                             %
125%   A c q u i r e U n i q u e S ym b o l i c L i n k                          %
126%                                                                             %
127%                                                                             %
128%                                                                             %
129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
130%
131%  AcquireUniqueSymbolicLink() creates a unique symbolic link to the specified
132%  source path and returns MagickTrue on success otherwise MagickFalse.  If the
133%  symlink() method fails or is not available, a unique file name is generated
134%  and the source file copied to it.  When you are finished with the file, use
135%  RelinquishUniqueFilename() to destroy it.
136%
137%  The format of the AcquireUniqueSymbolicLink method is:
138%
139%      MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
140%        char destination)
141%
142%  A description of each parameter follows.
143%
144%   o  source:  the source path.
145%
146%   o  destination:  the destination path.
147%
148*/
149
150static inline size_t MagickMin(const size_t x,const size_t y)
151{
152  if (x < y)
153    return(x);
154  return(y);
155}
156
157MagickExport MagickBooleanType AcquireUniqueSymbolicLink(const char *source,
158  char *destination)
159{
160  int
161    destination_file,
162    source_file;
163
164  size_t
165    length,
166    quantum;
167
168  ssize_t
169    count;
170
171  struct stat
172    attributes;
173
174  unsigned char
175    *buffer;
176
177  assert(source != (const char *) NULL);
178  assert(destination != (char *) NULL);
179#if defined(MAGICKCORE_HAVE_SYMLINK)
180  (void) AcquireUniqueFilename(destination);
181  (void) RelinquishUniqueFileResource(destination);
182  if (*source == *DirectorySeparator)
183    {
184      if (symlink(source,destination) == 0)
185        return(MagickTrue);
186    }
187  else
188    {
189      char
190        path[MaxTextExtent];
191
192      *path='\0';
193      if (getcwd(path,MaxTextExtent) == (char *) NULL)
194        return(MagickFalse);
195      (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
196      (void) ConcatenateMagickString(path,source,MaxTextExtent);
197      if (symlink(path,destination) == 0)
198        return(MagickTrue);
199    }
200#endif
201  destination_file=AcquireUniqueFileResource(destination);
202  if (destination_file == -1)
203    return(MagickFalse);
204  source_file=open_utf8(source,O_RDONLY | O_BINARY,0);
205  if (source_file == -1)
206    {
207      (void) close(destination_file);
208      (void) RelinquishUniqueFileResource(destination);
209      return(MagickFalse);
210    }
211  quantum=(size_t) MagickMaxBufferExtent;
212  if ((fstat(source_file,&attributes) == 0) && (attributes.st_size != 0))
213    quantum=MagickMin((size_t) attributes.st_size,MagickMaxBufferExtent);
214  buffer=(unsigned char *) AcquireQuantumMemory(quantum,sizeof(*buffer));
215  if (buffer == (unsigned char *) NULL)
216    {
217      (void) close(source_file);
218      (void) close(destination_file);
219      (void) RelinquishUniqueFileResource(destination);
220      return(MagickFalse);
221    }
222  for (length=0; ; )
223  {
224    count=(ssize_t) read(source_file,buffer,quantum);
225    if (count <= 0)
226      break;
227    length=(size_t) count;
228    count=(ssize_t) write(destination_file,buffer,length);
229    if ((size_t) count != length)
230      {
231        (void) close(destination_file);
232        (void) close(source_file);
233        buffer=(unsigned char *) RelinquishMagickMemory(buffer);
234        (void) RelinquishUniqueFileResource(destination);
235        return(MagickFalse);
236      }
237  }
238  (void) close(destination_file);
239  (void) close(source_file);
240  buffer=(unsigned char *) RelinquishMagickMemory(buffer);
241  return(MagickTrue);
242}
243
244/*
245%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246%                                                                             %
247%                                                                             %
248%                                                                             %
249%  A p p e n d I m a g e F o r m a t                                          %
250%                                                                             %
251%                                                                             %
252%                                                                             %
253%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254%
255%  AppendImageFormat() appends the image format type to the filename.  If an
256%  extension to the file already exists, it is first removed.
257%
258%  The format of the AppendImageFormat method is:
259%
260%      void AppendImageFormat(const char *format,char *filename)
261%
262%  A description of each parameter follows.
263%
264%   o  format:  Specifies a pointer to an array of characters.  This the
265%      format of the image.
266%
267%   o  filename:  Specifies a pointer to an array of characters.  The unique
268%      file name is returned in this array.
269%
270*/
271MagickExport void AppendImageFormat(const char *format,char *filename)
272{
273  char
274    extension[MaxTextExtent],
275    root[MaxTextExtent];
276
277  assert(format != (char *) NULL);
278  assert(filename != (char *) NULL);
279  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
280  if ((*format == '\0') || (*filename == '\0'))
281    return;
282  if (LocaleCompare(filename,"-") == 0)
283    {
284      char
285        message[MaxTextExtent];
286
287      (void) FormatLocaleString(message,MaxTextExtent,"%s:%s",format,filename);
288      (void) CopyMagickString(filename,message,MaxTextExtent);
289      return;
290    }
291  GetPathComponent(filename,ExtensionPath,extension);
292  if ((LocaleCompare(extension,"Z") == 0) ||
293      (LocaleCompare(extension,"bz2") == 0) ||
294      (LocaleCompare(extension,"gz") == 0) ||
295      (LocaleCompare(extension,"wmz") == 0) ||
296      (LocaleCompare(extension,"svgz") == 0))
297    {
298      GetPathComponent(filename,RootPath,root);
299      (void) CopyMagickString(filename,root,MaxTextExtent);
300      GetPathComponent(filename,RootPath,root);
301      (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s.%s",root,format,
302        extension);
303      return;
304    }
305  GetPathComponent(filename,RootPath,root);
306  (void) FormatLocaleString(filename,MaxTextExtent,"%s.%s",root,format);
307}
308
309/*
310%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
311%                                                                             %
312%                                                                             %
313%                                                                             %
314%   B a s e 6 4 D e c o d e                                                   %
315%                                                                             %
316%                                                                             %
317%                                                                             %
318%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
319%
320%  Base64Decode() decodes Base64-encoded text and returns its binary
321%  equivalent.  NULL is returned if the text is not valid Base64 data, or a
322%  memory allocation failure occurs.
323%
324%  The format of the Base64Decode method is:
325%
326%      unsigned char *Base64Decode(const char *source,length_t *length)
327%
328%  A description of each parameter follows:
329%
330%    o source:  A pointer to a Base64-encoded string.
331%
332%    o length: the number of bytes decoded.
333%
334*/
335MagickExport unsigned char *Base64Decode(const char *source,size_t *length)
336{
337  int
338    state;
339
340  register const char
341    *p,
342    *q;
343
344  register size_t
345    i;
346
347  unsigned char
348    *decode;
349
350  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
351  assert(source != (char *) NULL);
352  assert(length != (size_t *) NULL);
353  *length=0;
354  decode=(unsigned char *) AcquireQuantumMemory(strlen(source)/4+4,
355    3*sizeof(*decode));
356  if (decode == (unsigned char *) NULL)
357    return((unsigned char *) NULL);
358  i=0;
359  state=0;
360  for (p=source; *p != '\0'; p++)
361  {
362    if (isspace((int) ((unsigned char) *p)) != 0)
363      continue;
364    if (*p == '=')
365      break;
366    q=strchr(Base64,*p);
367    if (q == (char *) NULL)
368      {
369        decode=(unsigned char *) RelinquishMagickMemory(decode);
370        return((unsigned char *) NULL);  /* non-Base64 character */
371      }
372    switch (state)
373    {
374      case 0:
375      {
376        decode[i]=(q-Base64) << 2;
377        state++;
378        break;
379      }
380      case 1:
381      {
382        decode[i++]|=(q-Base64) >> 4;
383        decode[i]=((q-Base64) & 0x0f) << 4;
384        state++;
385        break;
386      }
387      case 2:
388      {
389        decode[i++]|=(q-Base64) >> 2;
390        decode[i]=((q-Base64) & 0x03) << 6;
391        state++;
392        break;
393      }
394      case 3:
395      {
396        decode[i++]|=(q-Base64);
397        state=0;
398        break;
399      }
400    }
401  }
402  /*
403    Verify Base-64 string has proper terminal characters.
404  */
405  if (*p != '=')
406    {
407      if (state != 0)
408        {
409          decode=(unsigned char *) RelinquishMagickMemory(decode);
410          return((unsigned char *) NULL);
411        }
412    }
413  else
414    {
415      p++;
416      switch (state)
417      {
418        case 0:
419        case 1:
420        {
421          /*
422            Unrecognized '=' character.
423          */
424          decode=(unsigned char *) RelinquishMagickMemory(decode);
425          return((unsigned char *) NULL);
426        }
427        case 2:
428        {
429          for ( ; *p != '\0'; p++)
430            if (isspace((int) ((unsigned char) *p)) == 0)
431              break;
432          if (*p != '=')
433            {
434              decode=(unsigned char *) RelinquishMagickMemory(decode);
435              return((unsigned char *) NULL);
436            }
437          p++;
438        }
439        case 3:
440        {
441          for ( ; *p != '\0'; p++)
442            if (isspace((int) ((unsigned char) *p)) == 0)
443              {
444                decode=(unsigned char *) RelinquishMagickMemory(decode);
445                return((unsigned char *) NULL);
446              }
447          if ((int) decode[i] != 0)
448            {
449              decode=(unsigned char *) RelinquishMagickMemory(decode);
450              return((unsigned char *) NULL);
451            }
452        }
453      }
454    }
455  *length=i;
456  return(decode);
457}
458
459/*
460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
461%                                                                             %
462%                                                                             %
463%                                                                             %
464%   B a s e 6 4 E n c o d e                                                   %
465%                                                                             %
466%                                                                             %
467%                                                                             %
468%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
469%
470%  Base64Encode() encodes arbitrary binary data to Base64 encoded format as
471%  described by the "Base64 Content-Transfer-Encoding" section of RFC 2045 and
472%  returns the result as a null-terminated ASCII string.  NULL is returned if
473%  a memory allocation failure occurs.
474%
475%  The format of the Base64Encode method is:
476%
477%      char *Base64Encode(const unsigned char *blob,const size_t blob_length,
478%        size_t *encode_length)
479%
480%  A description of each parameter follows:
481%
482%    o blob:  A pointer to binary data to encode.
483%
484%    o blob_length: the number of bytes to encode.
485%
486%    o encode_length:  The number of bytes encoded.
487%
488*/
489MagickExport char *Base64Encode(const unsigned char *blob,
490  const size_t blob_length,size_t *encode_length)
491{
492  char
493    *encode;
494
495  register const unsigned char
496    *p;
497
498  register size_t
499    i;
500
501  size_t
502    remainder;
503
504  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
505  assert(blob != (const unsigned char *) NULL);
506  assert(blob_length != 0);
507  assert(encode_length != (size_t *) NULL);
508  *encode_length=0;
509  encode=(char *) AcquireQuantumMemory(blob_length/3+4,4*sizeof(*encode));
510  if (encode == (char *) NULL)
511    return((char *) NULL);
512  i=0;
513  for (p=blob; p < (blob+blob_length-2); p+=3)
514  {
515    encode[i++]=Base64[(int) (*p >> 2)];
516    encode[i++]=Base64[(int) (((*p & 0x03) << 4)+(*(p+1) >> 4))];
517    encode[i++]=Base64[(int) (((*(p+1) & 0x0f) << 2)+(*(p+2) >> 6))];
518    encode[i++]=Base64[(int) (*(p+2) & 0x3f)];
519  }
520  remainder=blob_length % 3;
521  if (remainder != 0)
522    {
523      ssize_t
524        j;
525
526      unsigned char
527        code[3];
528
529      code[0]='\0';
530      code[1]='\0';
531      code[2]='\0';
532      for (j=0; j < (ssize_t) remainder; j++)
533        code[j]=(*p++);
534      encode[i++]=Base64[(int) (code[0] >> 2)];
535      encode[i++]=Base64[(int) (((code[0] & 0x03) << 4)+(code[1] >> 4))];
536      if (remainder == 1)
537        encode[i++]='=';
538      else
539        encode[i++]=Base64[(int) (((code[1] & 0x0f) << 2)+(code[2] >> 6))];
540      encode[i++]='=';
541    }
542  *encode_length=i;
543  encode[i++]='\0';
544  return(encode);
545}
546
547/*
548%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
549%                                                                             %
550%                                                                             %
551%                                                                             %
552%   C h o p P a t h C o m p o n e n t s                                       %
553%                                                                             %
554%                                                                             %
555%                                                                             %
556%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
557%
558%  ChopPathComponents() removes the number of specified file components from a
559%  path.
560%
561%  The format of the ChopPathComponents method is:
562%
563%      ChopPathComponents(char *path,size_t components)
564%
565%  A description of each parameter follows:
566%
567%    o path:  The path.
568%
569%    o components:  The number of components to chop.
570%
571*/
572MagickPrivate void ChopPathComponents(char *path,const size_t components)
573{
574  register ssize_t
575    i;
576
577  for (i=0; i < (ssize_t) components; i++)
578    GetPathComponent(path,HeadPath,path);
579}
580
581/*
582%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
583%                                                                             %
584%                                                                             %
585%                                                                             %
586%   E x p a n d F i l e n a m e                                               %
587%                                                                             %
588%                                                                             %
589%                                                                             %
590%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
591%
592%  ExpandFilename() expands '~' in a path.
593%
594%  The format of the ExpandFilename function is:
595%
596%      ExpandFilename(char *path)
597%
598%  A description of each parameter follows:
599%
600%    o path: Specifies a pointer to a character array that contains the
601%      path.
602%
603*/
604MagickPrivate void ExpandFilename(char *path)
605{
606  char
607    expand_path[MaxTextExtent];
608
609  if (path == (char *) NULL)
610    return;
611  if (*path != '~')
612    return;
613  (void) CopyMagickString(expand_path,path,MaxTextExtent);
614  if ((*(path+1) == *DirectorySeparator) || (*(path+1) == '\0'))
615    {
616      char
617        *home;
618
619      /*
620        Substitute ~ with $HOME.
621      */
622      (void) CopyMagickString(expand_path,".",MaxTextExtent);
623      (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
624      home=GetEnvironmentValue("HOME");
625      if (home == (char *) NULL)
626        home=GetEnvironmentValue("USERPROFILE");
627      if (home != (char *) NULL)
628        {
629          (void) CopyMagickString(expand_path,home,MaxTextExtent);
630          (void) ConcatenateMagickString(expand_path,path+1,MaxTextExtent);
631          home=DestroyString(home);
632        }
633    }
634  else
635    {
636#if defined(MAGICKCORE_POSIX_SUPPORT) && !defined(__OS2__)
637      char
638        username[MaxTextExtent];
639
640      register char
641        *p;
642
643      struct passwd
644        *entry;
645
646      /*
647        Substitute ~ with home directory from password file.
648      */
649      (void) CopyMagickString(username,path+1,MaxTextExtent);
650      p=strchr(username,'/');
651      if (p != (char *) NULL)
652        *p='\0';
653      entry=getpwnam(username);
654      if (entry == (struct passwd *) NULL)
655        return;
656      (void) CopyMagickString(expand_path,entry->pw_dir,MaxTextExtent);
657      if (p != (char *) NULL)
658        {
659          (void) ConcatenateMagickString(expand_path,"/",MaxTextExtent);
660          (void) ConcatenateMagickString(expand_path,p+1,MaxTextExtent);
661        }
662#endif
663    }
664  (void) CopyMagickString(path,expand_path,MaxTextExtent);
665}
666
667/*
668%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
669%                                                                             %
670%                                                                             %
671%                                                                             %
672%   E x p a n d F i l e n a m e s                                             %
673%                                                                             %
674%                                                                             %
675%                                                                             %
676%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
677%
678%  ExpandFilenames() checks each argument of the command line vector and
679%  expands it if they have a wildcard character.  For example, *.jpg might
680%  expand to:  bird.jpg rose.jpg tiki.jpg.
681%
682%  The format of the ExpandFilenames function is:
683%
684%      status=ExpandFilenames(int *number_arguments,char ***arguments)
685%
686%  A description of each parameter follows:
687%
688%    o number_arguments: Specifies a pointer to an integer describing the
689%      number of elements in the argument vector.
690%
691%    o arguments: Specifies a pointer to a text array containing the command
692%      line arguments.
693%
694*/
695MagickExport MagickBooleanType ExpandFilenames(int *number_arguments,
696  char ***arguments)
697{
698  char
699    *directory,
700    home_directory[MaxTextExtent],
701    **vector;
702
703  register ssize_t
704    i,
705    j;
706
707  size_t
708    number_files;
709
710  ssize_t
711    count,
712    parameters;
713
714  /*
715    Allocate argument vector.
716  */
717  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
718  assert(number_arguments != (int *) NULL);
719  assert(arguments != (char ***) NULL);
720  vector=(char **) AcquireQuantumMemory((size_t) (*number_arguments+1),
721    sizeof(*vector));
722  if (vector == (char **) NULL)
723    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
724  /*
725    Expand any wildcard filenames.
726  */
727  *home_directory='\0';
728  count=0;
729  for (i=0; i < (ssize_t) *number_arguments; i++)
730  {
731    char
732      **filelist,
733      filename[MaxTextExtent],
734      magick[MaxTextExtent],
735      *option,
736      path[MaxTextExtent],
737      subimage[MaxTextExtent];
738
739    MagickBooleanType
740      destroy;
741
742    option=(*arguments)[i];
743    *magick='\0';
744    *path='\0';
745    *filename='\0';
746    *subimage='\0';
747    vector[count++]=ConstantString(option);
748    destroy=MagickTrue;
749    parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
750    if (parameters > 0)
751      {
752        /*
753          Do not expand command option parameters.
754        */
755        for (j=0; j < parameters; j++)
756        {
757          i++;
758          if (i == (ssize_t) *number_arguments)
759            break;
760          option=(*arguments)[i];
761          vector[count++]=ConstantString(option);
762        }
763        continue;
764      }
765    if ((*option == '"') || (*option == '\''))
766      continue;
767    GetPathComponent(option,TailPath,filename);
768    GetPathComponent(option,MagickPath,magick);
769    if ((LocaleCompare(magick,"CAPTION") == 0) ||
770        (LocaleCompare(magick,"LABEL") == 0) ||
771        (LocaleCompare(magick,"VID") == 0))
772      continue;
773    if ((IsGlob(filename) == MagickFalse) && (*filename != '@'))
774      continue;
775    if (*filename != '@')
776      {
777        /*
778          Generate file list from wildcard filename (e.g. *.jpg).
779        */
780        GetPathComponent(option,HeadPath,path);
781        GetPathComponent(option,SubimagePath,subimage);
782        ExpandFilename(path);
783        if (*home_directory == '\0')
784          directory=getcwd(home_directory,MaxTextExtent-1);
785        (void) directory;
786        filelist=ListFiles(*path == '\0' ? home_directory : path,filename,
787          &number_files);
788      }
789    else
790      {
791        char
792          *files;
793
794        ExceptionInfo
795          *exception;
796
797        int
798          length;
799
800        /*
801          Generate file list from file list (e.g. @filelist.txt).
802        */
803        exception=AcquireExceptionInfo();
804        files=FileToString(filename+1,~0,exception);
805        exception=DestroyExceptionInfo(exception);
806        if (files == (char *) NULL)
807          continue;
808        filelist=StringToArgv(files,&length);
809        if (filelist == (char **) NULL)
810          continue;
811        files=DestroyString(files);
812        filelist[0]=DestroyString(filelist[0]);
813        for (j=0; j < (ssize_t) (length-1); j++)
814          filelist[j]=filelist[j+1];
815        number_files=(size_t) length-1;
816      }
817    if (filelist == (char **) NULL)
818      continue;
819    for (j=0; j < (ssize_t) number_files; j++)
820      if (IsPathDirectory(filelist[j]) <= 0)
821        break;
822    if (j == (ssize_t) number_files)
823      {
824        for (j=0; j < (ssize_t) number_files; j++)
825          filelist[j]=DestroyString(filelist[j]);
826        filelist=(char **) RelinquishMagickMemory(filelist);
827        continue;
828      }
829    /*
830      Transfer file list to argument vector.
831    */
832    vector=(char **) ResizeQuantumMemory(vector,(size_t) *number_arguments+
833      count+number_files+1,sizeof(*vector));
834    if (vector == (char **) NULL)
835      return(MagickFalse);
836    for (j=0; j < (ssize_t) number_files; j++)
837    {
838      option=filelist[j];
839      parameters=ParseCommandOption(MagickCommandOptions,MagickFalse,option);
840      if (parameters > 0)
841        {
842          ssize_t
843            k;
844
845          /*
846            Do not expand command option parameters.
847          */
848          vector[count++]=ConstantString(option);
849          for (k=0; k < parameters; k++)
850          {
851            j++;
852            if (j == (ssize_t) number_files)
853              break;
854            option=filelist[j];
855            vector[count++]=ConstantString(option);
856          }
857          continue;
858        }
859      (void) CopyMagickString(filename,path,MaxTextExtent);
860      if (*path != '\0')
861        (void) ConcatenateMagickString(filename,DirectorySeparator,
862          MaxTextExtent);
863      (void) ConcatenateMagickString(filename,filelist[j],MaxTextExtent);
864      filelist[j]=DestroyString(filelist[j]);
865      if (strlen(filename) >= (MaxTextExtent-1))
866        ThrowFatalException(OptionFatalError,"FilenameTruncated");
867      if (IsPathDirectory(filename) <= 0)
868        {
869          char
870            path[MaxTextExtent];
871
872          *path='\0';
873          if (*magick != '\0')
874            {
875              (void) ConcatenateMagickString(path,magick,MaxTextExtent);
876              (void) ConcatenateMagickString(path,":",MaxTextExtent);
877            }
878          (void) ConcatenateMagickString(path,filename,MaxTextExtent);
879          if (*subimage != '\0')
880            {
881              (void) ConcatenateMagickString(path,"[",MaxTextExtent);
882              (void) ConcatenateMagickString(path,subimage,MaxTextExtent);
883              (void) ConcatenateMagickString(path,"]",MaxTextExtent);
884            }
885          if (strlen(path) >= (MaxTextExtent-1))
886            ThrowFatalException(OptionFatalError,"FilenameTruncated");
887          if (destroy != MagickFalse)
888            {
889              count--;
890              vector[count]=DestroyString(vector[count]);
891              destroy=MagickFalse;
892            }
893          vector[count++]=ConstantString(path);
894        }
895    }
896    filelist=(char **) RelinquishMagickMemory(filelist);
897  }
898  vector[count]=(char *) NULL;
899  if (IsEventLogging() != MagickFalse)
900    {
901      char
902        *command_line;
903
904      command_line=AcquireString(vector[0]);
905      for (i=1; i < count; i++)
906      {
907        (void) ConcatenateString(&command_line," {");
908        (void) ConcatenateString(&command_line,vector[i]);
909        (void) ConcatenateString(&command_line,"}");
910      }
911      (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
912        "Command line: %s",command_line);
913      command_line=DestroyString(command_line);
914    }
915  *number_arguments=(int) count;
916  *arguments=vector;
917  return(MagickTrue);
918}
919
920/*
921%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
922%                                                                             %
923%                                                                             %
924%                                                                             %
925%   G e t E x e c u t i o n P a t h                                           %
926%                                                                             %
927%                                                                             %
928%                                                                             %
929%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
930%
931%  GetExecutionPath() returns the pathname of the executable that started
932%  the process.  On success MagickTrue is returned, otherwise MagickFalse.
933%
934%  The format of the GetExecutionPath method is:
935%
936%      MagickBooleanType GetExecutionPath(char *path,const size_t extent)
937%
938%  A description of each parameter follows:
939%
940%    o path: the pathname of the executable that started the process.
941%
942%    o extent: the maximum extent of the path.
943%
944*/
945MagickPrivate MagickBooleanType GetExecutionPath(char *path,const size_t extent)
946{
947  char
948    *directory;
949
950  *path='\0';
951  directory=getcwd(path,(unsigned long) extent);
952  (void) directory;
953#if defined(MAGICKCORE_HAVE_GETPID) && defined(MAGICKCORE_HAVE_READLINK) && defined(PATH_MAX)
954  {
955    char
956      link_path[MaxTextExtent],
957      execution_path[PATH_MAX+1];
958
959    ssize_t
960      count;
961
962    (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/exe",
963      (double) getpid());
964    count=readlink(link_path,execution_path,PATH_MAX);
965    if (count == -1)
966      {
967        (void) FormatLocaleString(link_path,MaxTextExtent,"/proc/%.20g/file",
968          (double) getpid());
969        count=readlink(link_path,execution_path,PATH_MAX);
970      }
971    if ((count > 0) && (count <= (ssize_t) PATH_MAX))
972      {
973        execution_path[count]='\0';
974        (void) CopyMagickString(path,execution_path,extent);
975      }
976  }
977#endif
978#if defined(MAGICKCORE_HAVE__NSGETEXECUTABLEPATH)
979  {
980    char
981      executable_path[PATH_MAX << 1],
982      execution_path[PATH_MAX+1];
983
984    uint32_t
985      length;
986
987    length=sizeof(executable_path);
988    if ((_NSGetExecutablePath(executable_path,&length) == 0) &&
989        (realpath(executable_path,execution_path) != (char *) NULL))
990      (void) CopyMagickString(path,execution_path,extent);
991  }
992#endif
993#if defined(MAGICKCORE_HAVE_GETEXECNAME)
994  {
995    const char
996      *execution_path;
997
998    execution_path=(const char *) getexecname();
999    if (execution_path != (const char *) NULL)
1000      {
1001        if (*execution_path != *DirectorySeparator)
1002          (void) ConcatenateMagickString(path,DirectorySeparator,extent);
1003        (void) ConcatenateMagickString(path,execution_path,extent);
1004      }
1005  }
1006#endif
1007#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1008  NTGetExecutionPath(path,extent);
1009#endif
1010#if defined(__GNU__)
1011  {
1012    char
1013      *program_name,
1014      *execution_path;
1015
1016    ssize_t
1017      count;
1018
1019    count=0;
1020    execution_path=(char *) NULL;
1021    program_name=program_invocation_name;
1022    if (*program_invocation_name != '/')
1023      {
1024        size_t
1025          extent;
1026
1027        extent=strlen(directory)+strlen(program_name)+2;
1028        program_name=AcquireQuantumMemory(extent,sizeof(*program_name));
1029        if (program_name == (char *) NULL)
1030          program_name=program_invocation_name;
1031        else
1032          count=FormatLocaleString(program_name,extent,"%s/%s",directory,
1033            program_invocation_name);
1034      }
1035    if (count != -1)
1036      {
1037        execution_path=realpath(program_name,NULL);
1038        if (execution_path != (char *) NULL)
1039          (void) CopyMagickString(path,execution_path,extent);
1040      }
1041    if (program_name != program_invocation_name)
1042      program_name=(char *) RelinquishMagickMemory(program_name);
1043    execution_path=(char *) RelinquishMagickMemory(execution_path);
1044  }
1045#endif
1046  return(IsPathAccessible(path));
1047}
1048
1049/*
1050%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1051%                                                                             %
1052%                                                                             %
1053%                                                                             %
1054%   G e t M a g i c k P a g e S i z e                                         %
1055%                                                                             %
1056%                                                                             %
1057%                                                                             %
1058%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1059%
1060%  GetMagickPageSize() returns the memory page size.
1061%
1062%  The format of the GetMagickPageSize method is:
1063%
1064%      ssize_t GetMagickPageSize()
1065%
1066*/
1067MagickPrivate ssize_t GetMagickPageSize(void)
1068{
1069  static ssize_t
1070    page_size = -1;
1071
1072  if (page_size > 0)
1073    return(page_size);
1074#if defined(MAGICKCORE_HAVE_SYSCONF) && defined(_SC_PAGE_SIZE)
1075  page_size=(ssize_t) sysconf(_SC_PAGE_SIZE);
1076#else
1077#if defined(MAGICKCORE_HAVE_GETPAGESIZE)
1078  page_size=(ssize_t) getpagesize();
1079#endif
1080#endif
1081  if (page_size <= 0)
1082    page_size=16384;
1083  return(page_size);
1084}
1085
1086/*
1087%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1088%                                                                             %
1089%                                                                             %
1090%                                                                             %
1091%   G e t P a t h A t t r i b u t e s                                         %
1092%                                                                             %
1093%                                                                             %
1094%                                                                             %
1095%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1096%
1097%  GetPathAttributes() returns attributes (e.g. size of file) about a path.
1098%
1099%  The path of the GetPathAttributes method is:
1100%
1101%      MagickBooleanType GetPathAttributes(const char *path,void *attributes)
1102%
1103%  A description of each parameter follows.
1104%
1105%   o  path: the file path.
1106%
1107%   o  attributes: the path attributes are returned here.
1108%
1109*/
1110MagickExport MagickBooleanType GetPathAttributes(const char *path,
1111  void *attributes)
1112{
1113  MagickBooleanType
1114    status;
1115
1116  if (path == (const char *) NULL)
1117    {
1118      errno=EINVAL;
1119      return(MagickFalse);
1120    }
1121  status=stat_utf8(path,(struct stat *) attributes) == 0 ? MagickTrue :
1122    MagickFalse;
1123  return(status);
1124}
1125
1126/*
1127%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1128%                                                                             %
1129%                                                                             %
1130%                                                                             %
1131%   G e t P a t h C o m p o n e n t                                           %
1132%                                                                             %
1133%                                                                             %
1134%                                                                             %
1135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1136%
1137%  GetPathComponent() returns the parent directory name, filename, basename, or
1138%  extension of a file path.
1139%
1140%  The format of the GetPathComponent function is:
1141%
1142%      GetPathComponent(const char *path,PathType type,char *component)
1143%
1144%  A description of each parameter follows:
1145%
1146%    o path: Specifies a pointer to a character array that contains the
1147%      file path.
1148%
1149%    o type: Specififies which file path component to return.
1150%
1151%    o component: the selected file path component is returned here.
1152%
1153*/
1154MagickExport void GetPathComponent(const char *path,PathType type,
1155  char *component)
1156{
1157  char
1158    magick[MaxTextExtent],
1159    *q,
1160    subimage[MaxTextExtent];
1161
1162  register char
1163    *p;
1164
1165  assert(path != (const char *) NULL);
1166  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",path);
1167  assert(component != (char *) NULL);
1168  if (*path == '\0')
1169    {
1170      *component='\0';
1171      return;
1172    }
1173  (void) CopyMagickString(component,path,MaxTextExtent);
1174  *magick='\0';
1175#if defined(__OS2__)
1176  if (path[1] != ":")
1177#endif
1178  for (p=component; *p != '\0'; p++)
1179  {
1180    if ((*p == '%') && (*(p+1) == '['))
1181      {
1182        /*
1183          Skip over %[...].
1184        */
1185        for (p++; (*p != ']') && (*p != '\0'); p++) ;
1186        if (*p == '\0')
1187          break;
1188      }
1189    if ((*p == ':') && (IsPathDirectory(path) < 0) &&
1190        (IsPathAccessible(path) == MagickFalse))
1191      {
1192        /*
1193          Look for image format specification (e.g. ps3:image).
1194        */
1195        (void) CopyMagickString(magick,component,(size_t) (p-component+1));
1196        if (IsMagickConflict(magick) != MagickFalse)
1197          *magick='\0';
1198        else
1199          for (q=component; *q != '\0'; q++)
1200            *q=(*++p);
1201        break;
1202      }
1203  }
1204  *subimage='\0';
1205  p=component;
1206  if (*p != '\0')
1207    p=component+strlen(component)-1;
1208  if ((*p == ']') && (strchr(component,'[') != (char *) NULL) &&
1209      (IsPathAccessible(path) == MagickFalse))
1210    {
1211      /*
1212        Look for scene specification (e.g. img0001.pcd[4]).
1213      */
1214      for (q=p-1; q > component; q--)
1215        if (*q == '[')
1216          break;
1217      if (*q == '[')
1218        {
1219          (void) CopyMagickString(subimage,q+1,MaxTextExtent);
1220          subimage[p-q-1]='\0';
1221          if ((IsSceneGeometry(subimage,MagickFalse) == MagickFalse) &&
1222              (IsGeometry(subimage) == MagickFalse))
1223            *subimage='\0';
1224          else
1225            *q='\0';
1226        }
1227    }
1228  p=component;
1229  if (*p != '\0')
1230    for (p=component+strlen(component)-1; p > component; p--)
1231      if (IsBasenameSeparator(*p) != MagickFalse)
1232        break;
1233  switch (type)
1234  {
1235    case MagickPath:
1236    {
1237      (void) CopyMagickString(component,magick,MaxTextExtent);
1238      break;
1239    }
1240    case RootPath:
1241    {
1242      for (p=component+(strlen(component)-1); p > component; p--)
1243      {
1244        if (IsBasenameSeparator(*p) != MagickFalse)
1245          break;
1246        if (*p == '.')
1247          break;
1248      }
1249      if (*p == '.')
1250        *p='\0';
1251      break;
1252    }
1253    case HeadPath:
1254    {
1255      *p='\0';
1256      break;
1257    }
1258    case TailPath:
1259    {
1260      if (IsBasenameSeparator(*p) != MagickFalse)
1261        (void) CopyMagickMemory((unsigned char *) component,
1262          (const unsigned char *) (p+1),strlen(p+1)+1);
1263      break;
1264    }
1265    case BasePath:
1266    {
1267      if (IsBasenameSeparator(*p) != MagickFalse)
1268        (void) CopyMagickString(component,p+1,MaxTextExtent);
1269      for (p=component+(strlen(component)-1); p > component; p--)
1270        if (*p == '.')
1271          {
1272            *p='\0';
1273            break;
1274          }
1275      break;
1276    }
1277    case ExtensionPath:
1278    {
1279      if (IsBasenameSeparator(*p) != MagickFalse)
1280        (void) CopyMagickString(component,p+1,MaxTextExtent);
1281      p=component;
1282      if (*p != '\0')
1283        for (p=component+strlen(component)-1; p > component; p--)
1284          if (*p == '.')
1285            break;
1286      *component='\0';
1287      if (*p == '.')
1288        (void) CopyMagickString(component,p+1,MaxTextExtent);
1289      break;
1290    }
1291    case SubimagePath:
1292    {
1293      (void) CopyMagickString(component,subimage,MaxTextExtent);
1294      break;
1295    }
1296    case CanonicalPath:
1297    case UndefinedPath:
1298      break;
1299  }
1300}
1301
1302/*
1303%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1304%                                                                             %
1305%                                                                             %
1306%                                                                             %
1307%  G e t P a t h C o m p o n e n t s                                          %
1308%                                                                             %
1309%                                                                             %
1310%                                                                             %
1311%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1312%
1313%  GetPathComponents() returns a list of path components.
1314%
1315%  The format of the GetPathComponents method is:
1316%
1317%      char **GetPathComponents(const char *path,
1318%        size_t *number_componenets)
1319%
1320%  A description of each parameter follows:
1321%
1322%    o path:  Specifies the string to segment into a list.
1323%
1324%    o number_components:  return the number of components in the list
1325%
1326*/
1327MagickPrivate char **GetPathComponents(const char *path,
1328  size_t *number_components)
1329{
1330  char
1331    **components;
1332
1333  register const char
1334    *p,
1335    *q;
1336
1337  register ssize_t
1338    i;
1339
1340  if (path == (char *) NULL)
1341    return((char **) NULL);
1342  *number_components=1;
1343  for (p=path; *p != '\0'; p++)
1344    if (IsBasenameSeparator(*p))
1345      (*number_components)++;
1346  components=(char **) AcquireQuantumMemory((size_t) *number_components+1UL,
1347    sizeof(*components));
1348  if (components == (char **) NULL)
1349    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1350  p=path;
1351  for (i=0; i < (ssize_t) *number_components; i++)
1352  {
1353    for (q=p; *q != '\0'; q++)
1354      if (IsBasenameSeparator(*q))
1355        break;
1356    components[i]=(char *) AcquireQuantumMemory((size_t) (q-p)+MaxTextExtent,
1357      sizeof(**components));
1358    if (components[i] == (char *) NULL)
1359      ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1360    (void) CopyMagickString(components[i],p,(size_t) (q-p+1));
1361    p=q+1;
1362  }
1363  components[i]=(char *) NULL;
1364  return(components);
1365}
1366
1367/*
1368%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1369%                                                                             %
1370%                                                                             %
1371%                                                                             %
1372%  I s P a t h A c c e s s i b l e                                            %
1373%                                                                             %
1374%                                                                             %
1375%                                                                             %
1376%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1377%
1378%  IsPathAccessible() returns MagickTrue if the file as defined by the path is
1379%  accessible.
1380%
1381%  The format of the IsPathAccessible method is:
1382%
1383%      MagickBooleanType IsPathAccessible(const char *filename)
1384%
1385%  A description of each parameter follows.
1386%
1387%    o path:  Specifies a path to a file.
1388%
1389*/
1390MagickExport MagickBooleanType IsPathAccessible(const char *path)
1391{
1392  MagickBooleanType
1393    status;
1394
1395  struct stat
1396    attributes;
1397
1398  if ((path == (const char *) NULL) || (*path == '\0'))
1399    return(MagickFalse);
1400  status=GetPathAttributes(path,&attributes);
1401  if (status == MagickFalse)
1402    return(status);
1403  if (S_ISREG(attributes.st_mode) == 0)
1404    return(MagickFalse);
1405  if (access_utf8(path,F_OK) != 0)
1406    return(MagickFalse);
1407  return(MagickTrue);
1408}
1409
1410/*
1411%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1412%                                                                             %
1413%                                                                             %
1414%                                                                             %
1415+  I s P a t h D i r e c t o r y                                              %
1416%                                                                             %
1417%                                                                             %
1418%                                                                             %
1419%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1420%
1421%  IsPathDirectory() returns -1 if the directory does not exist,  1 is returned
1422%  if the path represents a directory otherwise 0.
1423%
1424%  The format of the IsPathDirectory method is:
1425%
1426%      int IsPathDirectory(const char *path)
1427%
1428%  A description of each parameter follows.
1429%
1430%   o  path:  The directory path.
1431%
1432*/
1433static int IsPathDirectory(const char *path)
1434{
1435  MagickBooleanType
1436    status;
1437
1438  struct stat
1439    attributes;
1440
1441  if ((path == (const char *) NULL) || (*path == '\0'))
1442    return(MagickFalse);
1443  status=GetPathAttributes(path,&attributes);
1444  if (status == MagickFalse)
1445    return(-1);
1446  if (S_ISDIR(attributes.st_mode) == 0)
1447    return(0);
1448  return(1);
1449}
1450
1451/*
1452%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1453%                                                                             %
1454%                                                                             %
1455%                                                                             %
1456%   I s M a g i c k T r u e                                                   %
1457%                                                                             %
1458%                                                                             %
1459%                                                                             %
1460%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1461%
1462%  IsMagickTrue() returns MagickTrue if the value is "true", "on", "yes" or
1463%  "1".
1464%
1465%  The format of the IsMagickTrue method is:
1466%
1467%      MagickBooleanType IsMagickTrue(const char *value)
1468%
1469%  A description of each parameter follows:
1470%
1471%    o option: either MagickTrue or MagickFalse depending on the value
1472%      parameter.
1473%
1474%    o value: Specifies a pointer to a character array.
1475%
1476*/
1477MagickExport MagickBooleanType IsMagickTrue(const char *value)
1478{
1479  if (value == (const char *) NULL)
1480    return(MagickFalse);
1481  if (LocaleCompare(value,"true") == 0)
1482    return(MagickTrue);
1483  if (LocaleCompare(value,"on") == 0)
1484    return(MagickTrue);
1485  if (LocaleCompare(value,"yes") == 0)
1486    return(MagickTrue);
1487  if (LocaleCompare(value,"1") == 0)
1488    return(MagickTrue);
1489  return(MagickFalse);
1490}
1491
1492/*
1493%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1494%                                                                             %
1495%                                                                             %
1496%                                                                             %
1497%   L i s t F i l e s                                                         %
1498%                                                                             %
1499%                                                                             %
1500%                                                                             %
1501%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1502%
1503%  ListFiles() reads the directory specified and returns a list of filenames
1504%  contained in the directory sorted in ascending alphabetic order.
1505%
1506%  The format of the ListFiles function is:
1507%
1508%      char **ListFiles(const char *directory,const char *pattern,
1509%        ssize_t *number_entries)
1510%
1511%  A description of each parameter follows:
1512%
1513%    o filelist: Method ListFiles returns a list of filenames contained
1514%      in the directory.  If the directory specified cannot be read or it is
1515%      a file a NULL list is returned.
1516%
1517%    o directory: Specifies a pointer to a text string containing a directory
1518%      name.
1519%
1520%    o pattern: Specifies a pointer to a text string containing a pattern.
1521%
1522%    o number_entries:  This integer returns the number of filenames in the
1523%      list.
1524%
1525*/
1526
1527#if defined(__cplusplus) || defined(c_plusplus)
1528extern "C" {
1529#endif
1530
1531static int FileCompare(const void *x,const void *y)
1532{
1533  register const char
1534    **p,
1535    **q;
1536
1537  p=(const char **) x;
1538  q=(const char **) y;
1539  return(LocaleCompare(*p,*q));
1540}
1541
1542#if defined(__cplusplus) || defined(c_plusplus)
1543}
1544#endif
1545
1546static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
1547  struct dirent **result)
1548{
1549#if defined(MAGICKCORE_HAVE_READDIR_R)
1550  return(readdir_r(directory,entry,result));
1551#else
1552  (void) entry;
1553  errno=0;
1554  *result=readdir(directory);
1555  return(errno);
1556#endif
1557}
1558
1559MagickPrivate char **ListFiles(const char *directory,const char *pattern,
1560  size_t *number_entries)
1561{
1562  char
1563    **filelist;
1564
1565  DIR
1566    *current_directory;
1567
1568  struct dirent
1569    *buffer,
1570    *entry;
1571
1572  size_t
1573    max_entries;
1574
1575  /*
1576    Open directory.
1577  */
1578  assert(directory != (const char *) NULL);
1579  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",directory);
1580  assert(pattern != (const char *) NULL);
1581  assert(number_entries != (size_t *) NULL);
1582  *number_entries=0;
1583  current_directory=opendir(directory);
1584  if (current_directory == (DIR *) NULL)
1585    return((char **) NULL);
1586  /*
1587    Allocate filelist.
1588  */
1589  max_entries=2048;
1590  filelist=(char **) AcquireQuantumMemory((size_t) max_entries,
1591    sizeof(*filelist));
1592  if (filelist == (char **) NULL)
1593    {
1594      (void) closedir(current_directory);
1595      return((char **) NULL);
1596    }
1597  /*
1598    Save the current and change to the new directory.
1599  */
1600  buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
1601    FILENAME_MAX+1);
1602  if (buffer == (struct dirent *) NULL)
1603    ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1604  while ((MagickReadDirectory(current_directory,buffer,&entry) == 0) &&
1605         (entry != (struct dirent *) NULL))
1606  {
1607    if (*entry->d_name == '.')
1608      continue;
1609    if ((IsPathDirectory(entry->d_name) > 0) ||
1610#if defined(MAGICKCORE_WINDOWS_SUPPORT)
1611        (GlobExpression(entry->d_name,pattern,MagickTrue) != MagickFalse))
1612#else
1613        (GlobExpression(entry->d_name,pattern,MagickFalse) != MagickFalse))
1614#endif
1615      {
1616        if (*number_entries >= max_entries)
1617          {
1618            /*
1619              Extend the file list.
1620            */
1621            max_entries<<=1;
1622            filelist=(char **) ResizeQuantumMemory(filelist,(size_t)
1623              max_entries,sizeof(*filelist));
1624            if (filelist == (char **) NULL)
1625              break;
1626          }
1627#if defined(vms)
1628        {
1629          register char
1630            *p;
1631
1632          p=strchr(entry->d_name,';');
1633          if (p)
1634            *p='\0';
1635          if (*number_entries > 0)
1636            if (LocaleCompare(entry->d_name,filelist[*number_entries-1]) == 0)
1637              continue;
1638        }
1639#endif
1640        filelist[*number_entries]=(char *) AcquireString(entry->d_name);
1641        (*number_entries)++;
1642      }
1643  }
1644  buffer=(struct dirent *) RelinquishMagickMemory(buffer);
1645  (void) closedir(current_directory);
1646  if (filelist == (char **) NULL)
1647    return((char **) NULL);
1648  /*
1649    Sort filelist in ascending order.
1650  */
1651  qsort((void *) filelist,(size_t) *number_entries,sizeof(*filelist),
1652    FileCompare);
1653  return(filelist);
1654}
1655
1656/*
1657%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658%                                                                             %
1659%                                                                             %
1660%                                                                             %
1661%   M a g i c k D e l a y                                                     %
1662%                                                                             %
1663%                                                                             %
1664%                                                                             %
1665%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666%
1667%  MagickDelay() suspends program execution for the number of milliseconds
1668%  specified.
1669%
1670%  The format of the Delay method is:
1671%
1672%      void MagickDelay(const MagickSizeType milliseconds)
1673%
1674%  A description of each parameter follows:
1675%
1676%    o milliseconds: Specifies the number of milliseconds to delay before
1677%      returning.
1678%
1679*/
1680MagickPrivate void MagickDelay(const MagickSizeType milliseconds)
1681{
1682  if (milliseconds == 0)
1683    return;
1684#if defined(MAGICKCORE_HAVE_NANOSLEEP)
1685  {
1686    struct timespec
1687      timer;
1688
1689    timer.tv_sec=(time_t) (milliseconds/1000);
1690    timer.tv_nsec=(milliseconds % 1000)*1000*1000;
1691    (void) nanosleep(&timer,(struct timespec *) NULL);
1692  }
1693#elif defined(MAGICKCORE_HAVE_USLEEP)
1694  usleep(1000*milliseconds);
1695#elif defined(MAGICKCORE_HAVE_SELECT)
1696  {
1697    struct timeval
1698      timer;
1699
1700    timer.tv_sec=(long) milliseconds/1000;
1701    timer.tv_usec=(long) (milliseconds % 1000)*1000;
1702    (void) select(0,(XFD_SET *) NULL,(XFD_SET *) NULL,(XFD_SET *) NULL,&timer);
1703  }
1704#elif defined(MAGICKCORE_HAVE_POLL)
1705  (void) poll((struct pollfd *) NULL,0,(int) milliseconds);
1706#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1707  Sleep((long) milliseconds);
1708#elif defined(vms)
1709  {
1710    float
1711      timer;
1712
1713    timer=milliseconds/1000.0;
1714    lib$wait(&timer);
1715  }
1716#elif defined(__BEOS__)
1717  snooze(1000*milliseconds);
1718#else
1719# error "Time delay method not defined."
1720#endif
1721}
1722
1723/*
1724%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1725%                                                                             %
1726%                                                                             %
1727%                                                                             %
1728%  M u l t i l i n e C e n s u s                                              %
1729%                                                                             %
1730%                                                                             %
1731%                                                                             %
1732%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1733%
1734%  MultilineCensus() returns the number of lines within a label.  A line is
1735%  represented by a \n character.
1736%
1737%  The format of the MultilineCenus method is:
1738%
1739%      size_t MultilineCensus(const char *label)
1740%
1741%  A description of each parameter follows.
1742%
1743%   o  label:  This character string is the label.
1744%
1745*/
1746MagickExport size_t MultilineCensus(const char *label)
1747{
1748  size_t
1749    number_lines;
1750
1751  /*
1752    Determine the number of lines within this label.
1753  */
1754  if (label == (char *) NULL)
1755    return(0);
1756  for (number_lines=1; *label != '\0'; label++)
1757    if (*label == '\n')
1758      number_lines++;
1759  return(number_lines);
1760}
1761
1762/*
1763%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1764%                                                                             %
1765%                                                                             %
1766%                                                                             %
1767%   S y s t e m C o m m a n d                                                 %
1768%                                                                             %
1769%                                                                             %
1770%                                                                             %
1771%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1772%
1773%  SystemCommand() executes the specified command and waits until it
1774%  terminates.  The returned value is the exit status of the command.
1775%
1776%  The format of the SystemCommand method is:
1777%
1778%      int SystemCommand(const MagickBooleanType asynchronous,
1779%        const MagickBooleanType verbose,const char *command,
1780%        ExceptionInfo *exception)
1781%
1782%  A description of each parameter follows:
1783%
1784%    o asynchronous: a value other than 0 executes the parent program
1785%      concurrently with the new child process.
1786%
1787%    o verbose: a value other than 0 prints the executed command before it is
1788%      invoked.
1789%
1790%    o command: this string is the command to execute.
1791%
1792%    o exception: return any errors here.
1793%
1794*/
1795MagickExport int SystemCommand(const MagickBooleanType asynchronous,
1796  const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
1797{
1798  char
1799    **arguments,
1800    *shell_command;
1801
1802  int
1803    number_arguments,
1804    status;
1805
1806  PolicyDomain
1807    domain;
1808
1809  PolicyRights
1810    rights;
1811
1812  register ssize_t
1813    i;
1814
1815  status=(-1);
1816  arguments=StringToArgv(command,&number_arguments);
1817  if (arguments == (char **) NULL)
1818    return(status);
1819  rights=ExecutePolicyRights;
1820  domain=DelegatePolicyDomain;
1821  if (IsRightsAuthorized(domain,rights,arguments[1]) == MagickFalse)
1822    {
1823      errno=EPERM;
1824      (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
1825        "NotAuthorized","`%s'",arguments[1]);
1826      for (i=0; i < (ssize_t) number_arguments; i++)
1827        arguments[i]=DestroyString(arguments[i]);
1828      arguments=(char **) RelinquishMagickMemory(arguments);
1829      return(-1);
1830    }
1831  if (verbose != MagickFalse)
1832    {
1833      (void) FormatLocaleFile(stderr,"%s\n",command);
1834      (void) fflush(stderr);
1835    }
1836  shell_command=(char *) command;
1837  if (asynchronous != MagickFalse)
1838    {
1839      shell_command=AcquireString(command);
1840      (void) ConcatenateMagickString(shell_command,"&",MaxTextExtent);
1841    }
1842#if defined(MAGICKCORE_POSIX_SUPPORT)
1843#if !defined(MAGICKCORE_HAVE_EXECVP)
1844  status=system(shell_command);
1845#else
1846  if ((asynchronous != MagickFalse) || (strspn(shell_command,"&;<>|") == 0))
1847    status=system(shell_command);
1848  else
1849    {
1850      pid_t
1851        child_pid;
1852
1853      /*
1854        Call application directly rather than from a shell.
1855      */
1856      child_pid=fork();
1857      if (child_pid == (pid_t) -1)
1858        status=system(command);
1859      else
1860        if (child_pid == 0)
1861          {
1862            status=execvp(arguments[1],arguments+1);
1863            _exit(1);
1864          }
1865        else
1866          {
1867            int
1868              child_status;
1869
1870            pid_t
1871              pid;
1872
1873            child_status=0;
1874            pid=waitpid(child_pid,&child_status,0);
1875            if (pid == -1)
1876              status=(-1);
1877            else
1878              {
1879                if (WIFEXITED(child_status) != 0)
1880                  status=WEXITSTATUS(child_status);
1881                else
1882                  if (WIFSIGNALED(child_status))
1883                    status=(-1);
1884              }
1885          }
1886    }
1887#endif
1888#elif defined(MAGICKCORE_WINDOWS_SUPPORT)
1889  status=NTSystemCommand(shell_command);
1890#elif defined(macintosh)
1891  status=MACSystemCommand(shell_command);
1892#elif defined(vms)
1893  status=system(shell_command);
1894#else
1895#  error No suitable system() method.
1896#endif
1897  if (status < 0)
1898    (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
1899      "`%s' (%d)",command,status);
1900  if (shell_command != command)
1901    shell_command=DestroyString(shell_command);
1902  for (i=0; i < (ssize_t) number_arguments; i++)
1903    arguments[i]=DestroyString(arguments[i]);
1904  arguments=(char **) RelinquishMagickMemory(arguments);
1905  return(status);
1906}
1907