2023-10-09 23:04:59 -04:00
/* baked-nobloat.c - cake makes you fat. This version just removes features I don't find entirely necessary ($+, require space, shake support, ctype, and options).
* Copyright 2023 Emil Williams
* Licensed under the GNU Public License version 3 only , see LICENSE .
* @ EXEC cc $ @ - o $ * - std = gnu89 - O2 - Wall - Wextra - Wpedantic - pipe $ CFLAGS STOP @
*/
# include <errno.h>
# include <fcntl.h>
# include <locale.h>
# include <stddef.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <sys/mman.h>
# include <sys/stat.h>
# include <unistd.h>
# define START "@EXEC"
# define STOP "STOP@"
# define HELP \
" target-file [arguments ...] \n " \
" Use the format `@EXEC cmd ...' within the target-file, this will execute the \n " \
" rest of line, or if found within the file, until the STOP@ marker. \n "
# define DESC \
" Expansions \n " \
" \t $@ returns target-file (abc.x.txt) \n " \
" \t $* returns target-file without suffix (^-> abc.x) \n "
2023-10-09 23:37:26 -04:00
char * g_filename , * g_short ;
2023-10-09 23:04:59 -04:00
static char *
2023-10-11 07:59:40 -04:00
map ( char * fn , size_t * len )
2023-10-09 23:04:59 -04:00
{
struct stat s ;
int fd ;
char * addr = NULL ;
fd = open ( fn , O_RDONLY ) ;
if ( fd ! = - 1 )
{
if ( ! fstat ( fd , & s )
& & s . st_mode & S_IFREG
& & s . st_size )
{
* len = s . st_size ;
addr = mmap ( NULL , s . st_size , PROT_READ , MAP_SHARED , fd , 0 ) ;
}
close ( fd ) ;
}
return addr ;
}
2023-10-11 07:59:40 -04:00
static char *
find ( char * x , char * buf , size_t max , size_t min )
2023-10-09 23:04:59 -04:00
{
2023-10-11 07:59:40 -04:00
char * start = buf ;
2023-10-09 23:04:59 -04:00
for ( ; * buf ; + + buf )
{
if ( max - ( buf - start ) > min & & ! strncmp ( buf , x , min ) )
{ return buf ; }
}
return NULL ;
}
static char *
2023-10-11 07:59:40 -04:00
find_region ( char * fn , char * start , char * stop )
2023-10-09 23:04:59 -04:00
{
2023-10-09 23:37:26 -04:00
size_t len = 0 ;
char * buf = NULL , * addr ;
2023-10-11 07:59:40 -04:00
char * pb , * pe ;
2023-10-09 23:37:26 -04:00
addr = map ( fn , & len ) ;
if ( addr ! = MAP_FAILED )
2023-10-09 23:04:59 -04:00
{
2023-10-09 23:37:26 -04:00
if ( ( pb = find ( start , addr , len , strlen ( start ) ) ) )
2023-10-09 23:04:59 -04:00
{
2023-10-09 23:37:26 -04:00
pb + = strlen ( start ) ;
2023-10-09 23:41:17 -04:00
pe = find ( stop , pb , len - ( pb - addr ) , strlen ( stop ) ) ;
2023-10-09 23:37:26 -04:00
if ( pe )
{ buf = strndup ( pb , ( pe - addr ) - ( pb - addr ) ) ; }
2023-10-09 23:04:59 -04:00
}
2023-10-09 23:37:26 -04:00
munmap ( addr , len ) ;
2023-10-09 23:04:59 -04:00
}
return buf ;
}
static char *
2023-10-11 07:59:40 -04:00
insert ( char * new , char * str , size_t offset , size_t shift )
2023-10-09 23:04:59 -04:00
{
size_t len , max ;
2023-10-09 23:37:26 -04:00
if ( ! new | | ! str ) { return NULL ; }
2023-10-09 23:04:59 -04:00
len = strlen ( new ) ;
max = ( strlen ( str ) + 1 - offset - shift ) ;
memmove ( str + offset + len , str + offset + shift , max ) ;
memcpy ( str + offset , new , len ) ;
return str ;
}
static char *
shorten ( char * fn )
{
size_t i , last = 0 , len ;
char * sh ;
len = strlen ( fn ) ;
sh = malloc ( len + 1 ) ;
if ( ! sh ) { return NULL ; }
for ( i = 0 ; i < len ; + + i )
{
if ( fn [ i ] = = ' . ' )
{ last = i ; }
}
last = last ? last : i ;
strncpy ( sh , fn , last ) ;
sh [ last ] = ' \0 ' ;
return sh ;
}
static size_t
expand_size ( char * buf )
{
size_t i , len , max ;
len = max = strlen ( buf ) + 1 ;
for ( i = 0 ; i < len ; + + i )
{
if ( buf [ i ] = = ' \\ ' )
{ i + = 2 ; continue ; }
else if ( buf [ i ] = = ' $ ' )
{
switch ( buf [ + + i ] )
{
case ' @ ' :
max + = strlen ( g_filename ) ;
break ;
case ' * ' :
if ( ! g_short )
{ g_short = shorten ( g_filename ) ; }
max + = g_short ? strlen ( g_short ) : 0 ;
break ;
}
}
}
return max ;
}
static char *
expand ( char * buf )
{
size_t i ;
char * ptr = NULL ;
buf = realloc ( buf , expand_size ( buf ) ) ;
if ( ! buf ) { return NULL ; }
for ( i = 0 ; buf [ i ] ; + + i )
{
if ( buf [ i ] = = ' \\ ' )
{ i + = 2 ; continue ; }
else if ( buf [ i ] = = ' $ ' )
{
switch ( buf [ + + i ] )
{
case ' @ ' :
ptr = g_filename ;
break ;
case ' * ' :
ptr = g_short ;
break ;
default : continue ;
}
buf = insert ( ptr , buf , i - 1 , 2 ) ;
}
}
free ( g_short ) ;
return buf ;
}
2023-10-09 23:37:26 -04:00
static void
swap ( char * a , char * b )
{
* a ^ = * b ;
* b ^ = * a ;
* a ^ = * b ;
}
2023-10-09 23:04:59 -04:00
static int
2023-10-09 23:37:26 -04:00
root ( char * root )
2023-10-09 23:04:59 -04:00
{
2023-10-09 23:37:26 -04:00
int ret ;
char x [ 1 ] = " \0 " ;
size_t len = strlen ( root ) ;
while ( len & & root [ len ] ! = ' / ' )
{ - - len ; }
if ( ! len )
{ return 0 ; }
swap ( root + len , x ) ;
ret = chdir ( root ) ;
swap ( root + len , x ) ;
return ret ;
2023-10-09 23:04:59 -04:00
}
int
main ( int argc , char * * argv )
{
2023-10-09 23:37:26 -04:00
char * buf ;
2023-10-09 23:04:59 -04:00
setlocale ( LC_ALL , " C " ) ;
2023-10-09 23:37:26 -04:00
if ( argc < 2 ) { goto help ; }
2023-10-09 23:04:59 -04:00
g_filename = argv [ 1 ] ;
2023-10-09 23:37:26 -04:00
buf = find_region ( g_filename , START , STOP ) ;
2023-10-09 23:04:59 -04:00
if ( ! buf )
{
if ( errno )
{ perror ( argv [ 0 ] ) ; }
else
{ fprintf ( stderr , " %s: File unrecognized. \n " , argv [ 0 ] ) ; }
return 1 ;
}
buf = expand ( buf ) ;
2023-10-09 23:37:26 -04:00
root ( argv [ 0 ] ) ;
fprintf ( stderr , " Exec: %s \n " , buf ) ;
if ( ! buf ) { return 1 ; }
fputs ( " Output: \n " , stderr ) ;
fflush ( stderr ) ;
system ( buf ) ;
2023-10-09 23:04:59 -04:00
free ( buf ) ;
2023-10-09 23:37:26 -04:00
return 0 ;
2023-10-09 23:04:59 -04:00
help :
fprintf ( stderr , " %s: %s " , argv [ 0 ] , HELP DESC ) ;
return 1 ;
}