Radix cross Linux Package Tools

Package Tools – is a set of utilities to create, install, and update RcL packages

8 Commits   0 Branches   2 Tags
     5         kx 
     5         kx /**********************************************************************
     5         kx 
     5         kx   Copyright 2019 Andrey V.Kosteltsev
     5         kx 
     5         kx   Licensed under the Radix.pro License, Version 1.0 (the "License");
     5         kx   you may not use this file  except  in compliance with the License.
     5         kx   You may obtain a copy of the License at
     5         kx 
     5         kx      https://radix.pro/licenses/LICENSE-1.0-en_US.txt
     5         kx 
     5         kx   Unless required by applicable law or agreed to in writing, software
     5         kx   distributed under the License is distributed on an "AS IS" BASIS,
     5         kx   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
     5         kx   implied.
     5         kx 
     5         kx  **********************************************************************/
     5         kx 
     5         kx #include <config.h>
     5         kx 
     5         kx #include <stdlib.h>
     5         kx #include <stdio.h>
     5         kx #include <sys/types.h>
     5         kx #include <stdint.h>
     5         kx #include <dirent.h>
     5         kx #include <sys/stat.h> /* chmod(2)    */
     5         kx #include <fcntl.h>
     5         kx #include <linux/limits.h>
     5         kx #include <alloca.h>   /* alloca(3)   */
     5         kx #include <string.h>   /* strdup(3)   */
     5         kx #include <strings.h>  /* index(3)    */
     5         kx #include <libgen.h>   /* basename(3) */
     5         kx #include <ctype.h>    /* tolower(3)  */
     5         kx #include <errno.h>
     5         kx #include <time.h>
     5         kx #include <sys/time.h>
     5         kx #include <pwd.h>
     5         kx #include <grp.h>
     5         kx #include <stdarg.h>
     5         kx #include <unistd.h>
     5         kx 
     5         kx #include <sys/resource.h>
     5         kx 
     5         kx #include <signal.h>
     5         kx #if !defined SIGCHLD && defined SIGCLD
     5         kx # define SIGCHLD SIGCLD
     5         kx #endif
     5         kx 
     5         kx #define _GNU_SOURCE
     5         kx #include <getopt.h>
     5         kx 
     5         kx 
     5         kx #include <msglog.h>
     5         kx #include <wrapper.h>
     5         kx #include <system.h>
     5         kx 
     5         kx #define PROGRAM_NAME "pkginfo"
     5         kx 
     5         kx #include <defs.h>
     5         kx 
     5         kx 
     5         kx char *program     = PROGRAM_NAME;
     5         kx char *destination = NULL, *operation = NULL, *pkglog_fname = NULL;
     5         kx int   exit_status = EXIT_SUCCESS; /* errors counter */
     5         kx char *selfdir     = NULL;
     5         kx 
     5         kx char           *pkgname = NULL,
     5         kx                 *pkgver = NULL,
     5         kx                   *arch = NULL,
     5         kx             *distroname = NULL,
     5         kx              *distrover = NULL,
     5         kx                  *group = NULL,
     5         kx                    *url = NULL,
     5         kx                *license = NULL,
     5         kx      *uncompressed_size = NULL,
     5         kx            *total_files = NULL;
     5         kx 
     5         kx FILE *pkglog = NULL;
     5         kx FILE *output = NULL;
     5         kx 
     5         kx 
     5         kx #define FREE_PKGINFO_VARIABLES() \
     5         kx   if( pkgname )           { free( pkgname );           } pkgname = NULL;            \
     5         kx   if( pkgver )            { free( pkgver );            } pkgver = NULL;             \
     5         kx   if( arch )              { free( arch );              } arch = NULL;               \
     5         kx   if( distroname )        { free( distroname );        } distroname = NULL;         \
     5         kx   if( distrover )         { free( distrover );         } distrover = NULL;          \
     5         kx   if( group )             { free( group );             } group = NULL;              \
     5         kx   if( url )               { free( url );               } url = NULL;                \
     5         kx   if( license )           { free( license );           } license = NULL;            \
     5         kx   if( uncompressed_size ) { free( uncompressed_size ); } uncompressed_size = NULL;  \
     5         kx   if( total_files )       { free( total_files );       } total_files = NULL
     5         kx 
     5         kx void free_resources()
     5         kx {
     5         kx   if( selfdir )      { free( selfdir );      selfdir     = NULL;  }
     5         kx   if( destination )  { free( destination );  destination = NULL;  }
     5         kx   if( operation )    { free( operation );    operation = NULL;    }
     5         kx   if( pkglog_fname ) { free( pkglog_fname ); pkglog_fname = NULL; }
     5         kx 
     5         kx   FREE_PKGINFO_VARIABLES();
     5         kx }
     5         kx 
     5         kx void usage()
     5         kx {
     5         kx   free_resources();
     5         kx 
     5         kx   fprintf( stdout, "\n" );
     5         kx   fprintf( stdout, "Usage: %s [options] <pkglog|package>\n", program );
     5         kx   fprintf( stdout, "\n" );
     5         kx   fprintf( stdout, "Read information from <pkglog> or <package> file and create\n" );
     5         kx   fprintf( stdout, "requested package's service files in the destination directory.\n" );
     5         kx   fprintf( stdout, "\n" );
     5         kx   fprintf( stdout, "Options:\n" );
     5         kx   fprintf( stdout, "  -h,--help                     Display this information.\n" );
     5         kx   fprintf( stdout, "  -v,--version                  Display the version of %s utility.\n", program );
     5         kx   fprintf( stdout, "  -d,--destination=<DIR>        Target directory to save output files.\n" );
     5         kx   fprintf( stdout, "  -o,--operations=<OP1,..,OPn>  Comma separated list of:\n" );
     5         kx   fprintf( stdout, "\n" );
     5         kx   fprintf( stdout, "Operations:\n" );
     5         kx   fprintf( stdout, "  ----------------+----------------\n" );
     5         kx   fprintf( stdout, "   operation name | output file\n"     );
     5         kx   fprintf( stdout, "  ----------------+----------------\n" );
     5         kx   fprintf( stdout, "   pkginfo        | .PKGINFO\n"        );
     5         kx   fprintf( stdout, "   references     | .REFERENCES\n"     );
     5         kx   fprintf( stdout, "   requires       | .REQUIRES\n"       );
     5         kx   fprintf( stdout, "   description    | .DESCRIPTION\n"    );
     5         kx   fprintf( stdout, "   restore-links  | .RESTORELINKS\n"   );
     5         kx   fprintf( stdout, "   install-script | .INSTALL\n"        );
     5         kx   fprintf( stdout, "   filelist       | .FILELIST\n"       );
     5         kx   fprintf( stdout, "  ----------------+----------------\n" );
     5         kx   fprintf( stdout, "\n" );
     5         kx   fprintf( stdout, "Parameter:\n" );
     5         kx   fprintf( stdout, "  <pkglog|package>              PKGLOG file or package tarball.\n"  );
     5         kx   fprintf( stdout, "\n" );
     5         kx 
     5         kx   exit( EXIT_FAILURE );
     5         kx }
     5         kx 
     5         kx void to_lowercase( char *s )
     5         kx {
     5         kx   char *p = s;
     5         kx   while( p && *p ) { int c = *p; *p = tolower( c ); ++p; }
     5         kx }
     5         kx 
     5         kx void to_uppercase( char *s )
     5         kx {
     5         kx   char *p = s;
     5         kx   while( p && *p ) { int c = *p; *p = toupper( c ); ++p; }
     5         kx }
     5         kx 
     5         kx void version()
     5         kx {
     5         kx   char *upper = NULL;
     5         kx 
     5         kx   upper = (char *)alloca( strlen( program ) + 1 );
     5         kx 
     5         kx   strcpy( (char *)upper, (const char *)program );
     5         kx   to_uppercase( upper );
     5         kx 
     5         kx   fprintf( stdout, "%s (%s) %s\n", program, upper, PROGRAM_VERSION );
     5         kx 
     5         kx   fprintf( stdout, "Copyright (C) 2019 Andrey V.Kosteltsev.\n" );
     5         kx   fprintf( stdout, "This is free software.   There is NO warranty; not even\n" );
     5         kx   fprintf( stdout, "for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" );
     5         kx   fprintf( stdout, "\n" );
     5         kx 
     5         kx   free_resources();
     5         kx   exit( EXIT_SUCCESS );
     5         kx }
     5         kx 
     5         kx 
     5         kx static void remove_trailing_slash( char *dir )
     5         kx {
     5         kx   char *s;
     5         kx 
     5         kx   if( !dir || dir[0] == '\0' ) return;
     5         kx 
     5         kx   s = dir + strlen( dir ) - 1;
     5         kx   while( *s == '/' )
     5         kx   {
     5         kx     *s = '\0'; --s;
     5         kx   }
     5         kx }
     5         kx 
     5         kx void fatal_error_actions( void )
     5         kx {
     5         kx   logmsg( errlog, MSG_NOTICE, "Free resources on FATAL error..." );
     5         kx   free_resources();
     5         kx }
     5         kx 
     5         kx void sigint( int signum )
     5         kx {
     5         kx   (void)signum;
     5         kx   free_resources();
     5         kx }
     5         kx 
     5         kx static void set_signal_handlers()
     5         kx {
     5         kx   struct sigaction  sa;
     5         kx   sigset_t          set;
     5         kx 
     5         kx   memset( &sa, 0, sizeof( sa ) );
     5         kx   sa.sa_handler = sigint;          /* TERM, INT */
     5         kx   sa.sa_flags = SA_RESTART;
     5         kx   sigemptyset( &set );
     5         kx   sigaddset( &set, SIGTERM );
     5         kx   sigaddset( &set, SIGINT );
     5         kx   sa.sa_mask = set;
     5         kx   sigaction( SIGTERM, &sa, NULL );
     5         kx   sigaction( SIGINT, &sa,  NULL );
     5         kx 
     5         kx   memset( &sa, 0, sizeof( sa ) );  /* ignore SIGPIPE */
     5         kx   sa.sa_handler = SIG_IGN;
     5         kx   sa.sa_flags = 0;
     5         kx   sigaction( SIGPIPE, &sa, NULL );
     5         kx 
     5         kx   /* System V fork+wait does not work if SIGCHLD is ignored */
     5         kx   signal( SIGCHLD, SIG_DFL );
     5         kx }
     5         kx 
     5         kx enum _pkglog_type
     5         kx {
     5         kx   PKGLOG_TEXT = 0,
     5         kx   PKGLOG_GZ,
     5         kx   PKGLOG_BZ2,
     5         kx   PKGLOG_XZ,
     5         kx   PKGLOG_TAR,
     5         kx 
     5         kx   PKGLOG_UNKNOWN
     5         kx };
     5         kx 
     5         kx static enum _pkglog_type pkglog_type = PKGLOG_UNKNOWN;
     5         kx static char uncompress[2] = { 0, 0 };
     5         kx 
     5         kx 
     5         kx static enum _pkglog_type check_pkglog_file( const char *fname )
     5         kx {
     5         kx   struct stat st;
     5         kx   size_t pkglog_size = 0;
     5         kx   unsigned char buf[8];
     5         kx   int rc, fd;
     5         kx 
     5         kx   /* SIGNATURES: https://www.garykessler.net/library/file_sigs.html */
     5         kx 
     5         kx   uncompress[0] = '\0';
     5         kx 
     5         kx   if( stat( fname, &st ) == -1 )
     5         kx   {
     5         kx     FATAL_ERROR( "Cannot access %s file: %s", basename( (char *)fname ), strerror( errno ) );
     5         kx   }
     5         kx 
     5         kx   pkglog_size = st.st_size;
     5         kx 
     5         kx   if( (fd = open( fname, O_RDONLY )) == -1 )
     5         kx   {
     5         kx     FATAL_ERROR( "Cannot open %s file: %s", basename( (char *)fname ), strerror( errno ) );
     5         kx   }
     5         kx 
     5         kx   rc = (int)read( fd, (void *)&buf[0], 7 );
     5         kx   if( rc != 7 )
     5         kx   {
     5         kx     FATAL_ERROR( "Unknown type of input file %s", basename( (char *)fname ) );
     5         kx   }
     5         kx   buf[7] = '\0';
     5         kx 
     5         kx   /* TEXT */
     5         kx   if( !strncmp( (const char *)&buf[0], "PACKAGE", 7 ) )
     5         kx   {
     5         kx     close( fd ); return PKGLOG_TEXT;
     5         kx   }
     5         kx 
     5         kx   /* GZ */
     5         kx   if( buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x08 )
     5         kx   {
     5         kx     uncompress[0] = 'x';
     5         kx     close( fd ); return PKGLOG_GZ;
     5         kx   }
     5         kx 
     5         kx   /* BZ2 */
     5         kx   if( buf[0] == 0x42 && buf[1] == 0x5A && buf[2] == 0x68 )
     5         kx   {
     5         kx     uncompress[0] = 'j';
     5         kx     close( fd ); return PKGLOG_BZ2;
     5         kx   }
     5         kx 
     5         kx   /* XZ */
     5         kx   if( buf[0] == 0xFD && buf[1] == 0x37 && buf[2] == 0x7A &&
     5         kx       buf[3] == 0x58 && buf[4] == 0x5A && buf[5] == 0x00   )
     5         kx   {
     5         kx     uncompress[0] = 'J';
     5         kx     close( fd ); return PKGLOG_XZ;
     5         kx   }
     5         kx 
     5         kx   if( pkglog_size > 262 )
     5         kx   {
     5         kx     if( lseek( fd, 257, SEEK_SET ) == -1 )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot check signature of %s file: %s", basename( (char *)fname ), strerror( errno ) );
     5         kx     }
     5         kx     rc = (int)read( fd, &buf[0], 5 );
     5         kx     if( rc != 5 )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot read signature of %s file", basename( (char *)fname ) );
     5         kx     }
     5         kx     /* TAR */
     5         kx     if( buf[0] == 0x75 && buf[1] == 0x73 && buf[2] == 0x74 && buf[3] == 0x61 && buf[4] == 0x72 )
     5         kx     {
     5         kx       close( fd ); return PKGLOG_TAR;
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   close( fd ); return PKGLOG_UNKNOWN;
     5         kx }
     5         kx 
     5         kx 
     5         kx void get_args( int argc, char *argv[] )
     5         kx {
     5         kx   const char* short_options = "hvd:o:";
     5         kx 
     5         kx   const struct option long_options[] =
     5         kx   {
     5         kx     { "help",        no_argument,       NULL, 'h' },
     5         kx     { "version",     no_argument,       NULL, 'v' },
     5         kx     { "destination", required_argument, NULL, 'd' },
     5         kx     { "operations",  required_argument, NULL, 'o' },
     5         kx     { NULL,          0,                 NULL,  0  }
     5         kx   };
     5         kx 
     5         kx   int ret;
     5         kx   int option_index = 0;
     5         kx 
     5         kx   while( (ret = getopt_long( argc, argv, short_options, long_options, &option_index )) != -1 )
     5         kx   {
     5         kx     switch( ret )
     5         kx     {
     5         kx       case 'h':
     5         kx       {
     5         kx         usage();
     5         kx         break;
     5         kx       }
     5         kx       case 'v':
     5         kx       {
     5         kx         version();
     5         kx         break;
     5         kx       }
     5         kx 
     5         kx       case 'd':
     5         kx       {
     5         kx         if( optarg != NULL )
     5         kx         {
     5         kx           destination = xstrdup( (const char *)optarg );
     5         kx           remove_trailing_slash( destination );
     5         kx         }
     5         kx         else
     5         kx           /* option is present but without value */
     5         kx           usage();
     5         kx         break;
     5         kx       }
     5         kx       case 'o':
     5         kx       {
     5         kx         operation = xstrdup( (const char *)optarg );
     5         kx         to_lowercase( operation );
     5         kx         break;
     5         kx       }
     5         kx 
     5         kx       case '?': default:
     5         kx       {
     5         kx         usage();
     5         kx         break;
     5         kx       }
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination == NULL )
     5         kx   {
     5         kx     char cwd[PATH_MAX];
     5         kx     if( getcwd( cwd, sizeof(cwd) ) != NULL )
     5         kx       destination = xstrdup( (const char *)cwd );
     5         kx     else
     5         kx       destination = xstrdup( "." );
     5         kx   }
     5         kx 
     5         kx   if( operation == NULL ) usage();
     5         kx 
     5         kx   /* last command line argument is the LOGFILE */
     5         kx   if( optind < argc )
     5         kx   {
     5         kx     pkglog_fname = xstrdup( (const char *)argv[optind++] );
     5         kx     if( pkglog_fname == NULL )
     5         kx     {
     5         kx       usage();
     5         kx     }
     5         kx     pkglog_type = check_pkglog_file( (const char *)pkglog_fname );
     5         kx     if( pkglog_type == PKGLOG_UNKNOWN )
     5         kx     {
     5         kx       ERROR( "%s: Unknown input file format", basename( pkglog_fname ) );
     5         kx       usage();
     5         kx     }
     5         kx   }
     5         kx   else
     5         kx   {
     5         kx     usage();
     5         kx   }
     5         kx }
     5         kx 
     5         kx 
     5         kx /*
     5         kx   Especialy for pkginfo lines.
     5         kx   Remove leading spaces and take non-space characters only:
     5         kx  */
     5         kx static char *skip_spaces( char *s )
     5         kx {
     5         kx   char *q, *p = (char *)0;
     5         kx 
     5         kx   if( !s || *s == '\0' ) return p;
     5         kx 
     5         kx   p = s;
     5         kx 
     5         kx   while( (*p == ' ' || *p == '\t') && *p != '\0' ) { ++p; } q = p;
     5         kx   while(  *q != ' ' && *q != '\t'  && *q != '\0' ) { ++q; } *q = '\0';
     5         kx 
     5         kx   if( *p == '\0' ) return (char *)0;
     5         kx 
     5         kx   return( xstrdup( (const char *)p ) );
     5         kx }
     5         kx 
     5         kx /*
     5         kx   remove spaces at end of line:
     5         kx  */
     5         kx static void skip_eol_spaces( char *s )
     5         kx {
     5         kx   char *p = (char *)0;
     5         kx 
     5         kx   if( !s || *s == '\0' ) return;
     5         kx 
     5         kx   p = s + strlen( s ) - 1;
     5         kx   while( isspace( *p ) ) { *p-- = '\0'; }
     5         kx }
     5         kx 
     5         kx 
     5         kx int printf_variable( FILE *output, char *log_fname, char *name, char *value, char *pattern, int error )
     5         kx {
     5         kx   int   exit_status = 0; /* local errors counter */
     5         kx   char  buf[24];
     5         kx   char *p;
     5         kx 
     5         kx   bzero( (void *)buf, 24 );
     5         kx 
     5         kx   if( pattern )
     5         kx     (void)sprintf( (char *)&buf[0], "%s", pattern );
     5         kx 
     5         kx   p = (char *)&buf[0];
     5         kx   p[strlen(buf) - 1] = '\0'; /* skip colon at end of pattern */
     5         kx 
     5         kx   if( value )
     5         kx   {
     5         kx     fprintf( output, "%s=%s\n", name, value );
     5         kx   }
     5         kx   else
     5         kx   {
     5         kx     if( error )
     5         kx     {
     5         kx       ERROR( "There is no %s declaration in the %s file", p, log_fname );
     5         kx     }
     5         kx     else
     5         kx     {
     5         kx       if( ! DO_NOT_WARN_ABOUT_OPT_PKGINFO_ITEMS )
     5         kx         WARNING( "There is no %s declaration in the %s file", p, log_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   return( exit_status );
     5         kx }
     5         kx 
     5         kx 
     5         kx static void get_short_description( char *buf, const char *line )
     5         kx {
     5         kx   char *s, *p, *q;
     5         kx 
     5         kx   if( buf ) { buf[0] = '\0'; s = buf; }
     5         kx   if( !line || line[0] == '\0' ) return;
     5         kx 
     5         kx   p = index( line, '(' );
     5         kx   q = index( line, ')' );
     5         kx   if( p && q && q > p )
     5         kx   {
     5         kx     *s = '"'; ++s; /* start " */
     5         kx     ++p;
     5         kx     while( *p && p < q )
     5         kx     {
     5         kx       *s = *p;
     5         kx       ++p; ++s;
     5         kx     }
     5         kx     *s++ = '"';    /* stop "  */
     5         kx     *s   = '\0';
     5         kx   }
     5         kx }
     5         kx 
     5         kx int write_pkginfo()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 10 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.PKGINFO" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx     char *desc = NULL;
     5         kx 
     5         kx     char           *pkgname_pattern = "PACKAGE NAME:",
     5         kx                     *pkgver_pattern = "PACKAGE VERSION:",
     5         kx                       *arch_pattern = "ARCH:",
     5         kx                 *distroname_pattern = "DISTRO:",
     5         kx                  *distrover_pattern = "DISTRO VERSION:",
     5         kx                      *group_pattern = "GROUP:",
     5         kx                        *url_pattern = "URL:",
     5         kx                    *license_pattern = "LICENSE:",
     5         kx          *uncompressed_size_pattern = "UNCOMPRESSED SIZE:",
     5         kx                *total_files_pattern = "TOTAL FILES:";
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx     {
     5         kx       char *match = NULL;
     5         kx 
     5         kx       ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx       skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx       if( (match = strstr( ln, pkgname_pattern )) && match == ln ) /* at start of line only */
     5         kx       {
     5         kx         pkgname = skip_spaces( ln + strlen( pkgname_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, pkgver_pattern )) && match == ln )
     5         kx       {
     5         kx         pkgver = skip_spaces( ln + strlen( pkgver_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, arch_pattern )) && match == ln )
     5         kx       {
     5         kx         arch = skip_spaces( ln + strlen( arch_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, distroname_pattern )) && match == ln )
     5         kx       {
     5         kx         distroname = skip_spaces( ln + strlen( distroname_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, distrover_pattern )) && match == ln )
     5         kx       {
     5         kx         distrover = skip_spaces( ln + strlen( distrover_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, group_pattern )) && match == ln )
     5         kx       {
     5         kx         group = skip_spaces( ln + strlen( group_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, url_pattern )) && match == ln )
     5         kx       {
     5         kx         url = skip_spaces( ln + strlen( url_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, license_pattern )) && match == ln )
     5         kx       {
     5         kx         license = skip_spaces( ln + strlen( license_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, uncompressed_size_pattern )) && match == ln )
     5         kx       {
     5         kx         uncompressed_size = skip_spaces( ln + strlen( uncompressed_size_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, total_files_pattern )) && match == ln )
     5         kx       {
     5         kx         total_files = skip_spaces( ln + strlen( total_files_pattern ) );
     5         kx       }
     5         kx       if( (match = strstr( ln, "PACKAGE DESCRIPTION:" )) && match == ln )
     5         kx       {
     5         kx         char *buf = NULL;
     5         kx 
     5         kx         buf = (char *)malloc( (size_t)PATH_MAX );
     5         kx         if( !buf )
     5         kx         {
     5         kx           FATAL_ERROR( "Cannot allocate memory" );
     5         kx         }
     5         kx 
     5         kx         /* Get short_description from PACKAGE DESCRIPTION */
     5         kx         ln = fgets( line, PATH_MAX, pkglog );
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol */
     5         kx 
     5         kx         bzero( (void *)buf, PATH_MAX );
     5         kx         get_short_description( buf, (const char *)line );
     5         kx         if( buf[0] != '\0' )
     5         kx         {
     5         kx           desc = xstrdup( (const char *)buf );
     5         kx         }
     5         kx         free( buf );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     ret += printf_variable( output, pkglog_fname, "pkgname",           pkgname,           pkgname_pattern,           1 );
     5         kx     ret += printf_variable( output, pkglog_fname, "pkgver",            pkgver,            pkgver_pattern,            1 );
     5         kx     ret += printf_variable( output, pkglog_fname, "arch",              arch,              arch_pattern,              1 );
     5         kx     ret += printf_variable( output, pkglog_fname, "distroname",        distroname,        distroname_pattern,        1 );
     5         kx     ret += printf_variable( output, pkglog_fname, "distrover",         distrover,         distrover_pattern,         1 );
     5         kx     ret += printf_variable( output, pkglog_fname, "group",             group,             group_pattern,             0 );
     5         kx     if( desc != NULL )
     5         kx     {
     5         kx       ret += printf_variable( output, pkglog_fname, "short_description", desc, "SHORT DESCRIPTION:", 0 );
     5         kx       free( desc ); desc = NULL;
     5         kx     }
     5         kx     ret += printf_variable( output, pkglog_fname, "url",               url,               url_pattern,               0 );
     5         kx     ret += printf_variable( output, pkglog_fname, "license",           license,           license_pattern,           0 );
     5         kx     ret += printf_variable( output, pkglog_fname, "uncompressed_size", uncompressed_size, uncompressed_size_pattern, 0 );
     5         kx     ret += printf_variable( output, pkglog_fname, "total_files",       total_files,       total_files_pattern,       0 );
     5         kx 
     5         kx     FREE_PKGINFO_VARIABLES();
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx /*
     5         kx   NOTE:
     5         kx     1. first line has number 1.
     5         kx     2. sections are ordered according to following list:
     5         kx  */
     5         kx int reference_counter   = 0;
     5         kx int requires            = 0;
     5         kx int package_description = 0;
     5         kx int restore_links       = 0;
     5         kx int install_script      = 0;
     5         kx int file_list           = 0;
     5         kx 
     5         kx int refcount = 0;
     5         kx 
     5         kx 
     5         kx int get_pkglog_sections()
     5         kx {
     5         kx   int ret = -1, found = 0;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( pkglog != NULL )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx     {
     5         kx       char *match = NULL;
     5         kx 
     5         kx       if( (match = strstr( ln, "REFERENCE COUNTER:" )) && match == ln ) /* at start of line only */
     5         kx       {
     5         kx         reference_counter = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx       if( (match = strstr( ln, "REQUIRES:" )) && match == ln )
     5         kx       {
     5         kx         requires = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx       if( (match = strstr( ln, "PACKAGE DESCRIPTION:" )) && match == ln )
     5         kx       {
     5         kx         package_description = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx       if( (match = strstr( ln, "RESTORE LINKS:" )) && match == ln )
     5         kx       {
     5         kx         restore_links = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx       if( (match = strstr( ln, "INSTALL SCRIPT:" )) && match == ln )
     5         kx       {
     5         kx         install_script = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx       if( (match = strstr( ln, "FILE LIST:" )) && match == ln )
     5         kx       {
     5         kx         file_list = ret + 1;
     5         kx         ++found;
     5         kx       }
     5         kx 
     5         kx       ++ret;
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     ret = found;
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int get_pkglog_line( char *pattern )
     5         kx {
     5         kx   int ret = -1, found = 0;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( pkglog != NULL )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx     while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx     {
     5         kx       char *match = NULL;
     5         kx 
     5         kx       if( (match = strstr( ln, pattern )) && match == ln ) /* at start of line only */
     5         kx       {
     5         kx         ++ret;
     5         kx         ++found;
     5         kx         break;
     5         kx       }
     5         kx       ++ret;
     5         kx     }
     5         kx     if( !found ) ret = 0;
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx   }
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int get_ref_cnt()
     5         kx {
     5         kx   int ret = -1, found = 0;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( pkglog != NULL )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx     {
     5         kx       char *match = NULL;
     5         kx 
     5         kx       ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx       skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx       if( (match = strstr( ln, "REFERENCE COUNTER:" )) && match == ln ) /* at start of line only */
     5         kx       {
     5         kx         char *cnt = skip_spaces( ln + strlen( "REFERENCE COUNTER:" ) );
     5         kx         ret = atoi( cnt );
     5         kx         free( cnt );
     5         kx         ++found;
     5         kx         break;
     5         kx       }
     5         kx     }
     5         kx     if( !found ) ret = -1;
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx   }
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_references()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 13 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.REFERENCES" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( reference_counter && reference_counter < requires )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( (n > reference_counter) && (n < requires) )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_requires()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 11 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.REQUIRES" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( requires && requires < package_description )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( (n > requires) && (n < package_description) )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_package_description()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 14 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.DESCRIPTION" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( package_description && package_description < restore_links )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( (n > package_description) && (n < restore_links) )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_restore_links()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 15 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.RESTORELINKS" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( restore_links && restore_links < install_script )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( (n > restore_links) && (n < install_script) )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_install_script()
     5         kx {
     5         kx   int ret = -1;
     5         kx   char *output_fname = NULL;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 10 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.INSTALL" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( install_script && install_script < file_list )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( (n > install_script) && (n < file_list) )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   chmod( (const char *)output_fname, (mode_t)0755 );
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx int write_filelist()
     5         kx {
     5         kx   int ret = -1;
     5         kx 
     5         kx   if( pkglog_fname != NULL )
     5         kx   {
     5         kx     pkglog = fopen( (const char *)pkglog_fname, "r" );
     5         kx     if( !pkglog )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot open %s file", pkglog_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( destination != NULL )
     5         kx   {
     5         kx     char *output_fname = NULL;
     5         kx 
     5         kx     output_fname = (char *)alloca( strlen( destination ) + 11 );
     5         kx     strcpy( output_fname, destination );
     5         kx     strcat( output_fname, "/.FILELIST" );
     5         kx     output = fopen( (const char *)output_fname, "w" );
     5         kx     if( !output )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot create %s file", output_fname );
     5         kx     }
     5         kx   }
     5         kx 
     5         kx   if( (pkglog != NULL) && (output != NULL) )
     5         kx   {
     5         kx     char *ln   = NULL;
     5         kx     char *line = NULL;
     5         kx 
     5         kx     line = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !line )
     5         kx     {
     5         kx       FATAL_ERROR( "Cannot allocate memory" );
     5         kx     }
     5         kx 
     5         kx     ++ret;
     5         kx 
     5         kx     if( file_list )
     5         kx     {
     5         kx       int n = 1, lines = 0;
     5         kx 
     5         kx       ++ret;
     5         kx 
     5         kx       while( (ln = fgets( line, PATH_MAX, pkglog )) )
     5         kx       {
     5         kx         ln[strlen(ln) - 1] = '\0'; /* replace new-line symbol      */
     5         kx         skip_eol_spaces( ln );     /* remove spaces at end-of-line */
     5         kx 
     5         kx         if( n > file_list )
     5         kx         {
     5         kx           fprintf( output, "%s\n", ln );
     5         kx           ++lines;
     5         kx         }
     5         kx         ++n;
     5         kx       }
     5         kx 
     5         kx       ret = lines; /* number of lines in the LIST */
     5         kx     }
     5         kx 
     5         kx     free( line );
     5         kx 
     5         kx     fclose( pkglog ); pkglog = NULL;
     5         kx     fclose( output ); output = NULL;
     5         kx   }
     5         kx 
     5         kx   return( ret );
     5         kx }
     5         kx 
     5         kx 
     5         kx /*********************************************
     5         kx   Get directory where this program is placed:
     5         kx  */
     5         kx char *get_selfdir( void )
     5         kx {
     5         kx   char    *buf = NULL;
     5         kx   ssize_t  len;
     5         kx 
     5         kx   buf = (char *)malloc( PATH_MAX );
     5         kx   if( !buf )
     5         kx   {
     5         kx     FATAL_ERROR( "Cannot allocate memory" );
     5         kx   }
     5         kx 
     5         kx   bzero( (void *)buf, PATH_MAX );
     5         kx   len = readlink( "/proc/self/exe", buf, (size_t)PATH_MAX );
     5         kx   if( len > 0 && len < PATH_MAX )
     5         kx   {
     5         kx     char *p = xstrdup( (const char *)dirname( buf ) );
     5         kx     free( buf );
     5         kx     return p;
     5         kx   }
     5         kx   FATAL_ERROR( "Cannot determine self directory. Please mount /proc filesystem" );
     5         kx }
     5         kx 
     5         kx void set_stack_size( void )
     5         kx {
     5         kx   const rlim_t   stack_size = 16 * 1024 * 1024; /* min stack size = 16 MB */
     5         kx   struct rlimit  rl;
     5         kx   int ret;
     5         kx 
     5         kx   ret = getrlimit( RLIMIT_STACK, &rl );
     5         kx   if( ret == 0 )
     5         kx   {
     5         kx     if( rl.rlim_cur < stack_size )
     5         kx     {
     5         kx       rl.rlim_cur = stack_size;
     5         kx       ret = setrlimit( RLIMIT_STACK, &rl );
     5         kx       if( ret != 0 )
     5         kx       {
     5         kx         fprintf(stderr, "setrlimit returned result = %d\n", ret);
     5         kx         FATAL_ERROR( "Cannot set stack size" );
     5         kx       }
     5         kx     }
     5         kx   }
     5         kx }
     5         kx 
     5         kx 
     5         kx int main( int argc, char *argv[] )
     5         kx {
     5         kx   int    sections = 0;
     5         kx   gid_t  gid;
     5         kx 
     5         kx   set_signal_handlers();
     5         kx 
     5         kx   gid = getgid();
     5         kx   setgroups( 1, &gid );
     5         kx 
     5         kx   fatal_error_hook = fatal_error_actions;
     5         kx 
     5         kx   selfdir = get_selfdir();
     5         kx 
     5         kx   errlog = stderr;
     5         kx 
     5         kx   program = basename( argv[0] );
     5         kx   get_args( argc, argv );
     5         kx 
     5         kx   /* set_stack_size(); */
     5         kx 
     5         kx   if( pkglog_type == PKGLOG_TEXT )
     5         kx   {
     5         kx     sections = get_pkglog_sections();
     5         kx     if( sections < 3 )
     5         kx     {
     5         kx       FATAL_ERROR( "%s: Wrong PKGLOG file format", basename( pkglog_fname) );
     5         kx     }
     5         kx 
     5         kx     refcount = get_ref_cnt();
     5         kx 
     5         kx     if( strstr( operation, "pkginfo" ) ) exit_status += write_pkginfo();
     5         kx 
     5         kx     if( strstr( operation, "references" ) )
     5         kx     {
     5         kx       if( !reference_counter )
     5         kx       {
     5         kx         WARNING( "The REFERENCE COUNTER is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx       else
     5         kx       {
     5         kx         if( write_references() != refcount )
     5         kx         {
     5         kx           WARNING( "The REFERENCE COUNTER invalid in %s file", basename( pkglog_fname ) );
     5         kx         }
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "requires" ) )
     5         kx     {
     5         kx       if( write_requires() <= 0 )
     5         kx       {
     5         kx         if( ! DO_NOT_WARN_ABOUT_EMPTY_REQUIRES )
     5         kx           WARNING( "The REQUIRES is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "description" ) )
     5         kx     {
     5         kx       if( write_package_description() <= 0 )
     5         kx       {
     5         kx         WARNING( "The PACKAGE DESCRIPTION is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "restore-links" ) )
     5         kx     {
     5         kx       if( write_restore_links() <= 0 )
     5         kx       {
     5         kx         if( ! DO_NOT_WARN_ABOUT_EMPTY_RESTORE_LINKS )
     5         kx           WARNING( "The RESTORE LINKS is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "install-script" ) )
     5         kx     {
     5         kx       if( write_install_script() <= 0 )
     5         kx       {
     5         kx         ERROR( "The INSTALL SCRIPT is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "filelist" ) )
     5         kx     {
     5         kx       if( write_filelist() <= 0 )
     5         kx       {
     5         kx         ERROR( "The FILE LIST is not present in %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx   }
     5         kx   else /* TARBALL: */
     5         kx   {
     5         kx     pid_t p = (pid_t) -1;
     5         kx     int   rc;
     5         kx 
     5         kx     int   len = 0;
     5         kx     char *cmd = NULL, *errmsg = NULL, *wmsg = NULL;
     5         kx 
     5         kx     cmd = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !cmd )    { FATAL_ERROR( "Cannot allocate memory" ); }
     5         kx 
     5         kx     errmsg = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !errmsg ) { FATAL_ERROR( "Cannot allocate memory" ); }
     5         kx 
     5         kx     wmsg = (char *)malloc( (size_t)PATH_MAX );
     5         kx     if( !wmsg )   { FATAL_ERROR( "Cannot allocate memory" ); }
     5         kx 
     5         kx 
     5         kx     if( strstr( operation, "pkginfo" ) ) /* strongly required */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)errmsg, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &errmsg[0], "Cannot get .PKGINFO from %s file", basename( pkglog_fname ) );
     5         kx 
     5         kx       len = snprintf( &cmd[0], PATH_MAX, "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".PKGINFO" );
     5         kx       if( len == 0 || len == PATH_MAX - 1 )
     5         kx       {
     5         kx         FATAL_ERROR( errmsg );
     5         kx       }
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 )
     5         kx       {
     5         kx         /*****************************************
     5         kx           if( rc > 0 ) { return TAR exit status }
     5         kx           else         { return EXIT_FAILURE    }
     5         kx          */
     5         kx         if( rc > 0 ) exit_status = rc - 1; /* ERROR() will add one */
     5         kx         ERROR( errmsg );
     5         kx         if( fatal_error_hook) fatal_error_hook();
     5         kx         exit( exit_status );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     /* .REFERENCES is not present in package tarball */
     5         kx 
     5         kx     if( strstr( operation, "requires" ) ) /* optional; may be warning */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)errmsg, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &errmsg[0], "Cannot get .REQUIRES from %s file", basename( pkglog_fname ) );
     5         kx 
     5         kx       (void)sprintf( &cmd[0], "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".REQUIRES" );
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 && DO_NOT_WARN_ABOUT_EMPTY_REQUIRES == 0 )
     5         kx       {
     5         kx         WARNING( errmsg );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "description" ) ) /* optional; always warning */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &cmd[0], "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".DESCRIPTION" );
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 )
     5         kx       {
     5         kx         WARNING( "Cannot get package .DESCRIPTION from %s file", basename( pkglog_fname ) );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "restore-links" ) ) /* optional; may be warning */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)errmsg, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &errmsg[0], "Cannot get .RESTORELINKS script from %s file", basename( pkglog_fname ) );
     5         kx 
     5         kx       (void)sprintf( &cmd[0], "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".RESTORELINKS" );
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 && DO_NOT_WARN_ABOUT_EMPTY_RESTORE_LINKS == 0 )
     5         kx       {
     5         kx         WARNING( errmsg );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "install-script" ) ) /* strongly required */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)errmsg, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &errmsg[0], "Cannot get .INSTALL script from %s file", basename( pkglog_fname ) );
     5         kx 
     5         kx       len = snprintf( &cmd[0], PATH_MAX, "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".INSTALL" );
     5         kx       if( len == 0 || len == PATH_MAX - 1 )
     5         kx       {
     5         kx         FATAL_ERROR( errmsg );
     5         kx       }
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 )
     5         kx       {
     5         kx         /*****************************************
     5         kx           if( rc > 0 ) { return TAR exit status }
     5         kx           else         { return EXIT_FAILURE    }
     5         kx          */
     5         kx         if( rc > 0 ) exit_status = rc - 1; /* ERROR() will add one */
     5         kx         ERROR( errmsg );
     5         kx         if( fatal_error_hook) fatal_error_hook();
     5         kx         exit( exit_status );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( strstr( operation, "filelist" ) ) /* strongly required */
     5         kx     {
     5         kx       bzero( (void *)cmd, PATH_MAX );
     5         kx       bzero( (void *)errmsg, PATH_MAX );
     5         kx       bzero( (void *)wmsg, PATH_MAX );
     5         kx 
     5         kx       (void)sprintf( &errmsg[0], "Cannot get .FILELIST from %s file", basename( pkglog_fname ) );
     5         kx 
     5         kx       len = snprintf( &cmd[0], PATH_MAX, "tar -C %s -x%sf %s %s > /dev/null 2>&1", destination, uncompress, pkglog_fname, ".FILELIST" );
     5         kx       if( len == 0 || len == PATH_MAX - 1 )
     5         kx       {
     5         kx         FATAL_ERROR( errmsg );
     5         kx       }
     5         kx       p = sys_exec_command( cmd );
     5         kx       rc = sys_wait_command( p, (char *)&wmsg[0], PATH_MAX );
     5         kx       if( rc != 0 )
     5         kx       {
     5         kx         /*****************************************
     5         kx           if( rc > 0 ) { return TAR exit status }
     5         kx           else         { return EXIT_FAILURE    }
     5         kx          */
     5         kx         if( rc > 0 ) exit_status = rc - 1; /* ERROR() will add one */
     5         kx         ERROR( errmsg );
     5         kx         if( fatal_error_hook) fatal_error_hook();
     5         kx         exit( exit_status );
     5         kx       }
     5         kx     }
     5         kx 
     5         kx     if( cmd )    free( cmd );
     5         kx     if( errmsg ) free( errmsg );
     5         kx     if( wmsg )   free( wmsg );
     5         kx   }
     5         kx 
     5         kx 
     5         kx   free_resources();
     5         kx 
     5         kx   exit( exit_status );
     5         kx }