cronolog.org
flexible web log rotation
HOME
DOWNLOAD
FEATURES
USAGE
FAQ
BLOG
KNOWN BUGS
SECURITY
PATCHES
USERS
TO DO
HISTORY
LINKS
FEEDBACK
MAILING LIST
ADVERTISING

support cronolog development



Google   HELP


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [CRONOLOG]: Cronolog 1.6.2 for WIndows - Compile Success without Cygwin dependency


  • To: <cronolog-users@xxxxxxxxxxxxxxxx>
  • Subject: RE: [CRONOLOG]: Cronolog 1.6.2 for WIndows - Compile Success without Cygwin dependency
  • From: "Ian Huynh" <ianh@xxxxxxxxxxx>
  • Date: Thu, 16 Sep 2004 14:11:58 -0700
  • Thread-index: AcScC1hNYf4LBzL5Tx6c8xf3L9ebVQAIiYDg
  • Thread-topic: [CRONOLOG]: Cronolog 1.6.2 for WIndows

I think I finally have a compiled binary for Cronolog 1.6.2 for Win2K that does not depend on Cygwin1.dll.  The process was a bit convoluted and so here's the instructions just in case someone wants to do the same.  Hopefully this will be useful to someone else. 

(Note: The standard source from 1.6.2 builds fine with Cygwin but during execution, it requires Cygwin1.dll to be present in the path.)

The attached files are as follows:

1. howToCompileChronolog1.6.2ForWin2K.htm  - instructions on how to build, incl. errors that I have encountered and what I did to get around the error.
2. cronolog-1.6.2.windows.build.zip - a zip copy of my build directory.  You can find the .exe in cronolog-1.6.2\src directory
3. a diff of cronoutils.c in html format 

Of importance is item (3).  I had to modify 1 line in cronoutils.c when compiling.  I think I am right but not sure if this is correct.  It 
seems to compile and runs OK.


To view the attached HTML files, you are going to need either IE or FireFox to view them properly)

AND, as a disclaimer, this stuff hasn't been tested !



>-----Original Message-----
>From: Matthew Grosso [mailto:mgrosso@xxxxxxxxxxxxx]
>Sent: Thursday, September 16, 2004 9:34 AM
>To: Ian Huynh
>Cc: cronolog-users@xxxxxxxxxxxxxxxx
>Subject: Re: [CRONOLOG]: Cronolog 1.6.2 for WIndows
>
>
>
>Ian,
>
>You might want to try MinGW. Its basically cygwin minus the 
>compatibility layer
>dll. Not all of the the posix functions are there, but 
>cronolog is pretty
>small, so there's a good chance it will still compile, and if 
>not ifdefing the
>missing functionality shouldnt be too hard.  http://www.mingw.org
>
>Matt
>
>On Sep 13 0923, Ian Huynh wrote:
>> Andrew
>> Thanks.  It does work with Cygwin out of the box but the 
>.exe has a dependency on cygwin1.dll which
>> is not desirable
>> 
>> I've tried to use GCC option  -mno-cygwin but that created a 
>whole set of other problems with missing header file (e.g. langinfo.h)
>> 
>> Ian.
>> 
>> 
>> >-----Original Message-----
>> >From: Andrew Ford [mailto:A.Ford@xxxxxxxxxxxxxxxx]
>> >Sent: Saturday, September 11, 2004 11:39 PM
>> >To: Ian Huynh; cronolog-users@xxxxxxxxxxxxxxxx
>> >Subject: Re: [CRONOLOG]: Cronolog 1.6.2 for WIndows
>> >
>> >
>> >Ian Huynh wrote:
>> >
>> >>
>> >>Will there be a 1.6.2 build for Win2K?  If not, are there 
>> >>instructions on how to build for Win2K ?
>> >>Thanks.
>> >>
>> >>  
>> >>
>> >I don't do the builds for Windows, and don't actually know 
>how to -- 
>> >although I suspect that cronolog, like many programs designed for 
>> >Unix-like operating systems, would compile straightforwardly under 
>> >Cygwin on Windows.  The existing Windows version was 
>contributed.  If 
>> >someone contributes a Windows build of a newer version I will 
>> >put it up too.
>> >
>> >Andrew
>> >
>> >-- 
>> >Andrew Ford,  Director    Pauntley Prints / Ford & Mason Ltd
>> >A.Ford@xxxxxxxxxxxxxxxx   South Wing Compton House 
>> >pauntley-prints.co.uk     Compton Green, Redmarley  Tel: +44 
>> >1531 829900
>> >ford-mason.co.uk          Gloucester GL19 3JB       Fax: +44 
>> >1531 829901
>> >refcards.com/cronolog.org Great Britain          Mobile: +44 
>> >7785 258278
>> >
>> >
>> 
>> ---------------------------------------------------------------------
>> cronolog-users mailing list
>> --------------------------
>> Send messages to "cronolog-users@xxxxxxxxxxxxxxxx"
>> To unsubscribe send email to "majordomo@xxxxxxxxxxxxxxxx" 
>with the command:
>> "unsubscribe cronolog-users"
>> in the body of the message.
>
>-- 
>#######################################################################
># Matt Grosso mgrosso@xxxxxxxxxxxxx   w(201)963-2024 c(201)780-9592   #
># pgp public key is at http://www.falconweb.com/~mattg/publickey.pgp  #
>#######################################################################
>
Title: How to compile Chronolog 1.6.2 for Win2K

How to compile Chronolog 1.6.2 for Win2K

 

1         Downloading the Software

 

From www.mingw.org

·          Install MinGW   MinGW-3.1.0-1.exe

·          Install MSYS     MSYS-1.0.10.exe

 

From www.cygwin.com

·          Install Cygwin and make sure that you also include the Developer Kit to get all the GCC packages.

 

From www.chronolog.org

·          Get a copy of chronolog 1.6.2 and unzip it to a local drive

 

 

2         Compiling

 

·          Launch MSYS

o         cd to the directory where you unzipped chronolog 1.6.2

o         run ./configure

o         run make

·          You will get this error below

 

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.      -g -O2 -c strptime.c

strptime.c:31:22: langinfo.h: No such file or directory

make[1]: *** [strptime.o] Error 1

make[1]: Leaving directory `/c/cronolog-1.6.2/lib'

make: *** [all-recursive] Error 1

 

·          Save this snippet of code below as strptime.h inside directory lib? (Found this via googling)

 

#ifndef _STRPTIME_H

#define _STRPTIME_H

/*

  amplib strptime

*/

 

#if TIME_WITH_SYS_TIME

# include <sys/time.h>

# include <time.h>

#else

# if HAVE_SYS_TIME_H

#  include <sys/time.h>

# else

#  include <time.h>

# endif

#endif

 

 

//prototypes

char *ourStrptime(const char *s, const char *format, struct tm *tm);

 

#endif //_STRPTIMEH

 

// Emacs control

// Local Variables:

// eval: (c++-mode)

 

·          Recompiling

o         Run make clean

o         Run make

·          Got this error below

 

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.      -g -O2 -c strptime.c

strptime.c:31:22: langinfo.h: No such file or directory

make[1]: *** [strptime.o] Error 1

make[1]: Leaving directory `/c/cronolog-1.6.2/lib'

make: *** [all-recursive] Error 1

 

·          Edit file lib\Makefile.in and change

 

DEFS = @DEFS@ -I. -I$(srcdir)

            to

DEFS = @DEFS@ -I. -I$(srcdir) -I/c/cygnus/usr/include

       

        NOTE: This is assuming that Cygwin was installed at at C:\Cygnus

       

·          Reconfigure and remake

o         Run ./configure

o         Run make clean

o         Run make

·          Got this error below

gcc  -g -O2  -o cronotest  cronotest.o cronoutils.o ../lib/libutil.a

../lib/libutil.a(getopt.o)(.text+0x673): In function `getopt_internal':

c:/cronolog-1.6.2/lib/getopt.c:678: undefined reference to `_impure_ptr'

../lib/libutil.a(getopt.o)(.text+0x746):c:/cronolog-1.6.2/lib/getopt.c:706: undefined reference to `_impure_ptr'

../lib/libutil.a(getopt.o)(.text+0x78c):c:/cronolog-1.6.2/lib/getopt.c:701: undefined reference to `_impure_ptr'

../lib/libutil.a(getopt.o)(.text+0x83c):c:/cronolog-1.6.2/lib/getopt.c:723: undefined reference to `_impure_ptr'

../lib/libutil.a(getopt.o)(.text+0x8c8):c:/cronolog-1.6.2/lib/getopt.c:757: undefined reference to `_impure_ptr'

../lib/libutil.a(getopt.o)(.text+0x90c):c:/cronolog-1.6.2/lib/getopt.c:753: more undefined references to `_impure_ptr' follow

../lib/libutil.a(strptime.o)(.text+0x1f8): In function `strptime_internal':

c:/cronolog-1.6.2/lib/strptime.c:207: undefined reference to `_ctype_'

../lib/libutil.a(strptime.o)(.text+0x208):c:/cronolog-1.6.2/lib/strptime.c:209: undefined reference to `_ctype_'

../lib/libutil.a(strptime.o)(.text+0x219):c:/cronolog-1.6.2/lib/strptime.c:210: undefined reference to `_ctype_'

../lib/libutil.a(strptime.o)(.text+0xdc9):c:/cronolog-1.6.2/lib/strptime.c:401: undefined reference to `_ctype_'

../lib/libutil.a(strptime.o)(.text+0xdde):c:/cronolog-1.6.2/lib/strptime.c:402: undefined reference to `_ctype_'

make[1]: *** [cronotest] Error 1

make[1]: Leaving directory `/c/cronolog-1.6.2/src'

make: *** [all-recursive] Error 1

 

·          Edit file lib\Makefile.in and change

      

DEFS = @DEFS@ -I. -I$(srcdir) -I/c/cygnus/usr/include

 

            to

       

DEFS = @DEFS@ -I. -I$(srcdir) -I/mingw/include -I/c/cygnus/usr/include  

                       

·          Reconfigure and remake

o         Run ./configure

o         Run make clean

o         Run make

·          Got this error below

 

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS_TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1 -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.  -I../lib    -g -O2 -c cronoutils.c

cronoutils.c: In function `create_subdirs':

cronoutils.c:170: `S_IRWXG' undeclared (first use in this function)

cronoutils.c:170: (Each undeclared identifier is reported only once

cronoutils.c:170: for each function it appears in.)

cronoutils.c:170: `S_IROTH' undeclared (first use in this function)

cronoutils.c:170: `S_IXOTH' undeclared (first use in this function)

cronoutils.c:170: too many arguments to function `_mkdir'

cronoutils.c: At top level:

cronoutils.c:183: warning: parameter names (without types) in function declaration

cronoutils.c:183: warning: data definition has no type or storage class

cronoutils.c:185: parse error before '}' token

make[1]: *** [cronoutils.o] Error 1

make[1]: Leaving directory `/c/cronolog-1.6.2/src'

make: *** [all-recursive] Error 1

 

·          Make a small modification in cronoutils.c  around the #ifndef _WIN32 line near the mkdir function

Modified code from 1.6.2

 

    DEBUG(("Testing directory \"%s\"\n", dirname));

    if (stat(dirname, &stat_buf) < 0)

    {

           if (errno != ENOENT)

           {

                  perror(dirname);

                  exit(2);

           }

           else

           {

                  DEBUG(("Directory \"%s\" does not exist -- creating\n", dirname));

#ifndef _WIN32

                  if ((mkdir(dirname, DIR_MODE) < 0) && (errno != EEXIST))

#else

                  if ((mkdir(dirname) < 0) && (errno != EEXIST))

#endif

                  {

                                perror(dirname);

                         exit(2);

                  }

           }

    }

 

 

 

 

Original code from 1.6.2

 

 

    DEBUG(("Testing directory \"%s\"\n", dirname));

    if (stat(dirname, &stat_buf) < 0)

    {

        if (errno != ENOENT)

        {

           perror(dirname);

           exit(2);

        }

        else

        {

           DEBUG(("Directory \"%s\" does not exist -- creating\n", dirname));

           if ((mkdir(dirname, DIR_MODE) < 0) && (errno != EEXIST))

#ifndef _WIN32

           {

#else

                if ((mkdir(dirname) < 0) && (errno != EEXIST))

#endif

               perror(dirname);

               exit(2);

           }

        }

    }

·          Remake

o         Run make clean

o         Run make

 

$ make clean

Making clean in .

make[1]: Entering directory `/c/cronolog-1.6.2'

make[1]: Nothing to be done for `clean-am'.

make[1]: Leaving directory `/c/cronolog-1.6.2'

Making clean in testsuite

make[1]: Entering directory `/c/cronolog-1.6.2/testsuite'

make[1]: Nothing to be done for `clean'.

make[1]: Leaving directory `/c/cronolog-1.6.2/testsuite'

Making clean in doc

make[1]: Entering directory `/c/cronolog-1.6.2/doc'

rm -f cronolog.aux cronolog.cp cronolog.cps cronolog.dvi cronolog.fn \

  cronolog.fns cronolog.ky cronolog.kys cronolog.ps \

  cronolog.log cronolog.pg cronolog.toc cronolog.tp \

  cronolog.tps cronolog.vr cronolog.vrs cronolog.op cronolog.tr \

  cronolog.cv cronolog.cn

make[1]: Leaving directory `/c/cronolog-1.6.2/doc'

Making clean in src

make[1]: Entering directory `/c/cronolog-1.6.2/src'

test -z "cronotest" || rm -f cronotest

test -z "cronolog" || rm -f cronolog

rm -f *.o core *.core

make[1]: Leaving directory `/c/cronolog-1.6.2/src'

Making clean in lib

make[1]: Entering directory `/c/cronolog-1.6.2/lib'

test -z "libutil.a" || rm -f libutil.a

rm -f *.o core *.core

make[1]: Leaving directory `/c/cronolog-1.6.2/lib'

 

$ make

Making all in lib

make[1]: Entering directory `/c/cronolog-1.6.2/lib'

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I. -I/min                                                                          gw/include -I/c/cygnus/usr/include     -g -O2 -c getopt.c

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I. -I/min                                                                          gw/include -I/c/cygnus/usr/include     -g -O2 -c getopt1.c

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I. -I/min                                                                          gw/include -I/c/cygnus/usr/include     -g -O2 -c strptime.c

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I. -I/min                                                                          gw/include -I/c/cygnus/usr/include     -g -O2 -c localtime_r.c

rm -f libutil.a

ar cru libutil.a getopt.o getopt1.o strptime.o localtime_r.o

ranlib libutil.a

make[1]: Leaving directory `/c/cronolog-1.6.2/lib'

Making all in src

make[1]: Entering directory `/c/cronolog-1.6.2/src'

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.  -I../                                                                          lib    -g -O2 -c cronotest.c

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.  -I../                                                                          lib    -g -O2 -c cronoutils.c

gcc  -g -O2  -o cronotest  cronotest.o cronoutils.o ../lib/libutil.a

gcc -DPACKAGE=\"cronolog\" -DVERSION=\"1.6.2\" -DSTDC_HEADERS=1 -DTIME_WITH_SYS                                                                          _TIME=1 -DHAVE_FCNTL_H=1 -DHAVE_LIMITS_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STRFTIME=1                                                                           -DHAVE_VPRINTF=1 -DHAVE_MKDIR=1 -DHAVE_MKTIME=1 -DHAVE_PUTENV=1  -I. -I.  -I../                                                                          lib    -g -O2 -c cronolog.c

gcc  -g -O2  -o cronolog  cronolog.o cronoutils.o ../lib/libutil.a

make[1]: Leaving directory `/c/cronolog-1.6.2/src'

Making all in doc

make[1]: Entering directory `/c/cronolog-1.6.2/doc'

make[1]: Nothing to be done for `all'.

make[1]: Leaving directory `/c/cronolog-1.6.2/doc'

Making all in testsuite

make[1]: Entering directory `/c/cronolog-1.6.2/testsuite'

make[1]: Nothing to be done for `all'.

make[1]: Leaving directory `/c/cronolog-1.6.2/testsuite'

make[1]: Entering directory `/c/cronolog-1.6.2'

make[1]: Nothing to be done for `all-am'.

make[1]: Leaving directory `/c/cronolog-1.6.2'

 

Attachment: cronolog-1.6.2.windows.build.zip
Description: cronolog-1.6.2.windows.build.zip

CRONOUTILS.C Difference
Produced: 9/16/2004 1:53:35 PM
   
Mode:  All Lines  
   
Left file: C:\cronolog-1.6.2\src\cronoutils.c     Right file: C:\cronolog-1.6.2\src\cronoutils.c.v.1.6.2  
/* ==================================================================== = /* ====================================================================
* Copyright (c) 1995-1999 The Apache Group.  All rights reserved.   * Copyright (c) 1995-1999 The Apache Group.  All rights reserved.
*   *
* Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
* are met:   * are met:
*   *
* 1. Redistributions of source code must retain the above copyright   * 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer. <> *    notice, this list of conditions and the following disclaimer.
* = *
* 2. Redistributions in binary form must reproduce the above copyright   * 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in   *    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the   *    the documentation and/or other materials provided with the
*    distribution.   *    distribution.
*   *
* 3. All advertising materials mentioning features or use of this   * 3. All advertising materials mentioning features or use of this
*    software must display the following acknowledgment:   *    software must display the following acknowledgment:
*    "This product includes software developed by the Apache Group   *    "This product includes software developed by the Apache Group
*    for use in the Apache HTTP server project (http://www.apache.org/)."   *    for use in the Apache HTTP server project (http://www.apache.org/)."
*   *
* 4. The names "Apache Server" and "Apache Group" must not be used to   * 4. The names "Apache Server" and "Apache Group" must not be used to
*    endorse or promote products derived from this software without   *    endorse or promote products derived from this software without
*    prior written permission. For written permission, please contact   *    prior written permission. For written permission, please contact
*    apache@xxxxxxxxxxx   *    apache@xxxxxxxxxxx
*   *
* 5. Products derived from this software may not be called "Apache"   * 5. Products derived from this software may not be called "Apache"
*    nor may "Apache" appear in their names without prior written   *    nor may "Apache" appear in their names without prior written
*    permission of the Apache Group.   *    permission of the Apache Group.
*   *
* 6. Redistributions of any form whatsoever must retain the following   * 6. Redistributions of any form whatsoever must retain the following
*    acknowledgment:   *    acknowledgment:
*    "This product includes software developed by the Apache Group   *    "This product includes software developed by the Apache Group
*    for use in the Apache HTTP server project (http://www.apache.org/)."   *    for use in the Apache HTTP server project (http://www.apache.org/)."
*   *
* THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY   * THIS SOFTWARE IS PROVIDED BY THE APACHE GROUP ``AS IS'' AND ANY
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE APACHE GROUP OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.   * OF THE POSSIBILITY OF SUCH DAMAGE.
* ====================================================================   * ====================================================================
*   *
* This software consists of voluntary contributions made by many   * This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Group and was originally based   * individuals on behalf of the Apache Group and was originally based
* on public domain software written at the National Center for   * on public domain software written at the National Center for
* Supercomputing Applications, University of Illinois, Urbana-Champaign.   * Supercomputing Applications, University of Illinois, Urbana-Champaign.
* For more information on the Apache Group and the Apache HTTP server   * For more information on the Apache Group and the Apache HTTP server
* project, please see <http://www.apache.org/>.   * project, please see <http://www.apache.org/>.
*   *
*/   */
/*   /*
* cronoutils -- utilities for the cronolog program   * cronoutils -- utilities for the cronolog program
*   *
* Copyright (c) 1996-1999 by Ford & Mason Ltd   * Copyright (c) 1996-1999 by Ford & Mason Ltd
*   *
* This software was submitted by Ford & Mason Ltd to the Apache   * This software was submitted by Ford & Mason Ltd to the Apache
* Software Foundation in December 1999.  Future revisions and   * Software Foundation in December 1999.  Future revisions and
* derivatives of this source code must acknowledge Ford & Mason Ltd   * derivatives of this source code must acknowledge Ford & Mason Ltd
* as the original contributor of this module.  All other licensing   * as the original contributor of this module.  All other licensing
* and usage conditions are those of the Apache Software Foundation.   * and usage conditions are those of the Apache Software Foundation.
*   *
* Originally written by Andrew Ford <A.Ford@xxxxxxxxxxxxxxxx>   * Originally written by Andrew Ford <A.Ford@xxxxxxxxxxxxxxxx>
*   *
*/   */
     
#include "cronoutils.h"   #include "cronoutils.h"
extern char *tzname[2];   extern char *tzname[2];
     
     
#ifdef _WIN32   #ifdef _WIN32
#include "strptime.h"   #include "strptime.h"
#endif   #endif
/* debug_file is the file to output debug messages to.  No debug   /* debug_file is the file to output debug messages to.  No debug
* messages are output if it is set to NULL. <> * messages are output if it is set to NULL.
*/ = */
FILE    *debug_file = NULL;   FILE    *debug_file = NULL;
     
     
/* America and Europe disagree on whether weeks start on Sunday or   /* America and Europe disagree on whether weeks start on Sunday or
* Monday - weeks_start_on_mondays is set if a %U specifier is encountered.   * Monday - weeks_start_on_mondays is set if a %U specifier is encountered.
*/   */
int weeks_start_on_mondays = 0;   int weeks_start_on_mondays = 0;
     
     
/* periods[] is an array of the names of the periods.   /* periods[] is an array of the names of the periods.
*/   */
char    *periods[] = <> char    *periods[] =
{ = {
    "second",       "second",
    "minute",       "minute",
    "hour",       "hour",
    "day",       "day",
    "week",       "week",
    "month",       "month",
    "year",       "year",
    "aeon"  /* i.e. once only */       "aeon"  /* i.e. once only */
};   };
     
/* period_seconds[] is an array of the number of seconds in a period.   /* period_seconds[] is an array of the number of seconds in a period.
*/   */
int period_seconds[] = <> int period_seconds[] =
{ = {
    1,       1,
    60,       60,
    60 * 60,       60 * 60,
    60 * 60 * 24,       60 * 60 * 24,
    60 * 60 * 24 * 7,       60 * 60 * 24 * 7,
    60 * 60 * 24 * 31,       60 * 60 * 24 * 31,
    60 * 60 * 24 * 36       60 * 60 * 24 * 36
};   };
?   ?
/* Try to create missing directories on the path of filename.   /* Try to create missing directories on the path of filename.
*   *
* Note that on a busy server there may theoretically be many cronolog   * Note that on a busy server there may theoretically be many cronolog
* processes trying simultaneously to create the same subdirectories   * processes trying simultaneously to create the same subdirectories
* so ignore any EEXIST errors on mkdir -- they probably just mean   * so ignore any EEXIST errors on mkdir -- they probably just mean
* that another process got there first.   * that another process got there first.
*   *
* Unless CHECK_ALL_PREFIX_DIRS is defined, we save the directory of   * Unless CHECK_ALL_PREFIX_DIRS is defined, we save the directory of
* the last file tested -- any common prefix should exist.  This   * the last file tested -- any common prefix should exist.  This
* probably only saves a few stat system calls at the start of each   * probably only saves a few stat system calls at the start of each
* log period, but it might as well be done. <> * log period, but it might as well be done.
*/ = */
void   void
create_subdirs(char *filename)   create_subdirs(char *filename)
{   {
#ifndef CHECK_ALL_PREFIX_DIRS   #ifndef CHECK_ALL_PREFIX_DIRS
    static char lastpath[MAX_PATH] = "";       static char lastpath[MAX_PATH] = "";
#endif   #endif
    struct stat stat_buf;       struct stat stat_buf;
    char    dirname[MAX_PATH];       char    dirname[MAX_PATH];
    char    *p;       char    *p;
  <>    
    DEBUG(("Creating missing components of \"%s\"\n", filename)); =     DEBUG(("Creating missing components of \"%s\"\n", filename));
    for (p = filename; (p = strchr(p, '/')); p++)       for (p = filename; (p = strchr(p, '/')); p++)
    {       {
        if (p == filename) <>     if (p == filename)
        {       {
            continue;       /* Don't bother with the root directory */           continue;       /* Don't bother with the root directory */
        }       }
       
        memcpy(dirname, filename, p - filename);       memcpy(dirname, filename, p - filename);
        dirname[p-filename] = '\0';       dirname[p-filename] = '\0';
       
#ifndef CHECK_ALL_PREFIX_DIRS = #ifndef CHECK_ALL_PREFIX_DIRS
        if (strncmp(dirname, lastpath, strlen(dirname)) == 0) <>     if (strncmp(dirname, lastpath, strlen(dirname)) == 0)
        {       {
            DEBUG(("Initial prefix \"%s\" known to exist\n", dirname));           DEBUG(("Initial prefix \"%s\" known to exist\n", dirname));
            continue;           continue;
        }       }
#endif = #endif
     
        DEBUG(("Testing directory \"%s\"\n", dirname)); <>     DEBUG(("Testing directory \"%s\"\n", dirname));
        if (stat(dirname, &stat_buf) < 0)       if (stat(dirname, &stat_buf) < 0)
        {       {
            if (errno != ENOENT)           if (errno != ENOENT)
            {           {
                perror(dirname);           perror(dirname);
                exit(2);           exit(2);
            }           }
            else           else
            {           {
                DEBUG(("Directory \"%s\" does not exist -- creating\n", dirname));           DEBUG(("Directory \"%s\" does not exist -- creating\n", dirname));
            if ((mkdir(dirname, DIR_MODE) < 0) && (errno != EEXIST))
#ifndef _WIN32 = #ifndef _WIN32
                if ((mkdir(dirname, DIR_MODE) < 0) && (errno != EEXIST)) <>         {
#else = #else
                if ((mkdir(dirname) < 0) && (errno != EEXIST))                   if ((mkdir(dirname) < 0) && (errno != EEXIST))
#endif   #endif
                { <>  
                        perror(dirname);               perror(dirname);
                    exit(2);               exit(2);
                }           }
            }           }
        }       }
    } =     }
#ifndef CHECK_ALL_PREFIX_DIRS   #ifndef CHECK_ALL_PREFIX_DIRS
    strcpy(lastpath, dirname);       strcpy(lastpath, dirname);
#endif   #endif
}   }
?   ?
/* Create a hard or symbolic link to a filename according to the type specified.   /* Create a hard or symbolic link to a filename according to the type specified.
*   *
* This function could do with more error checking! <> * This function could do with more error checking!
*/ = */
void   void
create_link(char *pfilename, <> create_link(char *pfilename,
        const char *linkname, mode_t linktype, =         const char *linkname, mode_t linktype,
        const char *prevlinkname)           const char *prevlinkname)
{   {
    struct stat     stat_buf;       struct stat     stat_buf;
  <>    
    if (stat(prevlinkname, &stat_buf) == 0) =     if (stat(prevlinkname, &stat_buf) == 0)
    {       {
    unlink(prevlinkname);       unlink(prevlinkname);
    }       }
    if (stat(linkname, &stat_buf) == 0)       if (stat(linkname, &stat_buf) == 0)
    {       {
    if (prevlinkname) {       if (prevlinkname) {
        rename(linkname, prevlinkname);           rename(linkname, prevlinkname);
    }       }
    else {       else {
        unlink(linkname);           unlink(linkname);
    }       }
    }       }
#ifndef _WIN32   #ifndef _WIN32
    if (linktype == S_IFLNK)       if (linktype == S_IFLNK)
    {       {
    symlink(pfilename, linkname);       symlink(pfilename, linkname);
    }       }
    else       else
    {       {
    link(pfilename, linkname);       link(pfilename, linkname);
    }       }
#else   #else
    fprintf(stderr, "Creating link from %s to %s not supported", pfilename, linkname);       fprintf(stderr, "Creating link from %s to %s not supported", pfilename, linkname);
#endif <> #endif   
} = }
     
/* Examine the log file name specifier for strftime conversion   /* Examine the log file name specifier for strftime conversion
* specifiers and determine the period between log files. <> * specifiers and determine the period between log files.
* Smallest period allowed is per minute. = * Smallest period allowed is per minute.
*/   */
PERIODICITY   PERIODICITY
determine_periodicity(char *spec)   determine_periodicity(char *spec)
{   {
    PERIODICITY periodicity = ONCE_ONLY;       PERIODICITY periodicity = ONCE_ONLY;
    char    ch;       char    ch;
  <>    
    DEBUG(("Determining periodicity of \"%s\"\n", spec)); =     DEBUG(("Determining periodicity of \"%s\"\n", spec));
    while ((ch = *spec++) != 0)       while ((ch = *spec++) != 0)
    {       {
    if (ch == '%')       if (ch == '%')
    {       {
        ch = *spec++;           ch = *spec++;
        if (!ch) break;           if (!ch) break;
  <>        
        switch (ch) =         switch (ch)
        {           {
        case 'y':       /* two digit year */           case 'y':       /* two digit year */
        case 'Y':       /* four digit year */           case 'Y':       /* four digit year */
        if (periodicity > YEARLY)           if (periodicity > YEARLY)
        {           {
            DEBUG(("%%%c -> yearly\n", ch));               DEBUG(("%%%c -> yearly\n", ch));
            periodicity = YEARLY;               periodicity = YEARLY;
        }           }
        break;           break;
     
        case 'b':       /* abbreviated month name */           case 'b':       /* abbreviated month name */
        case 'h':       /* abbreviated month name (non-standard) */           case 'h':       /* abbreviated month name (non-standard) */
        case 'B':       /* full month name */           case 'B':       /* full month name */
        case 'm':       /* month as two digit number (with           case 'm':       /* month as two digit number (with
                   leading zero) */                      leading zero) */
        if (periodicity > MONTHLY)           if (periodicity > MONTHLY)
        {           {
            DEBUG(("%%%c -> monthly\n", ch));               DEBUG(("%%%c -> monthly\n", ch));
            periodicity = MONTHLY;               periodicity = MONTHLY;
        }           }
            break;               break;
  <>        
        case 'U':       /* week number (weeks start on Sunday) */ =         case 'U':       /* week number (weeks start on Sunday) */
        case 'W':       /* week number (weeks start on Monday) */           case 'W':       /* week number (weeks start on Monday) */
            if (periodicity > WEEKLY)               if (periodicity > WEEKLY)
        {           {
            DEBUG(("%%%c -> weeky\n", ch));               DEBUG(("%%%c -> weeky\n", ch));
            periodicity = WEEKLY;               periodicity = WEEKLY;
            weeks_start_on_mondays = (ch == 'W');               weeks_start_on_mondays = (ch == 'W');
        }           }
        break;           break;
  <>        
        case 'a':       /* abbreviated weekday name */ =         case 'a':       /* abbreviated weekday name */
        case 'A':       /* full weekday name */           case 'A':       /* full weekday name */
        case 'd':       /* day of the month (with leading zero) */           case 'd':       /* day of the month (with leading zero) */
        case 'e':       /* day of the month (with leading space -- non-standard) */           case 'e':       /* day of the month (with leading space -- non-standard) */
        case 'j':       /* day of the year (with leading zeroes) */