Never been to CodeSnippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world (or not, you can keep them private!)

argmax (See related posts)


getconf ARG_MAX           # Mac OS X 10.6.7:  262144 bytes
sysctl -n kern.argmax

# get the (rough) maximum number of bytes for an argument list in the current shell 
# uses command line tools only; for a C version see argmax.c below
# cf. http://www.in-ulm.de/~mascheck/various/argmax/
(
argmaxbytes="$(expr $(getconf ARG_MAX) - $(env | wc -c) - $(env | wc -l) \* 4 - 2048)"
printf '\n%s\n\n' "argmaxbytes: $argmaxbytes"
bash -c ':' _ $(jot -n -s '' ${argmaxbytes} 1 1)
printf '%s\n\n' "exit status: $?"
)


# get the exact maximum number of bytes for an argument list in the current shell 
# see also argmax.c below
(
exec 2> >(nl -n ln)
exitval=1
argmaxbytes=$(getconf ARG_MAX)

until [[ $exitval -eq 0 ]]; do
  bash -c ':' _ $(jot -n -s '' ${argmaxbytes} 1 1)
  exitval=$?
  (( argmaxbytes = argmaxbytes - 1 ))
done

(( argmaxbytes = argmaxbytes + 1 ))

printf '\n%s\n' "argmaxbytes: $argmaxbytes"

printf '\n%s\n' "test 1 using argmaxbytes:"
bash -c ':' _ $(jot -n -s '' ${argmaxbytes} 1 1)
echo "exit status: $?"

printf '\n%s\n' "test 2 using argmaxbytes + 1:"
(( argmaxbytes = argmaxbytes + 1 ))
bash -c ':' _ $(jot -n -s '' ${argmaxbytes} 1 1)
echo "exit status: $?"
)




argmax.c

/*

argmax - get the maximum number of bytes for an argument list in the current shell

References: 
- man execve
- http://www.in-ulm.de/~mascheck/various/argmax/
- http://man.yolinux.com/cgi-bin/man2html?cgi_command=execve
- http://www.semicomplete.com/blog/geekery/shebang-fix.html
- http://semicomplete.googlecode.com/svn/codesamples/shebang.c


compile with:
gcc -O3 -Wall -Wextra -Werror -ansi -pedantic -std=c99 -o argmax argmax.c


command line tests:

getconf ARG_MAX           # Mac OS X 10.6.7:  262144 bytes
sysctl -n kern.argmax


# enable "for debugging only" code in C source code
./argmax echo 5 1>/dev/null
./argmax "printf '%s\n'" 5  1>/dev/null

./argmax echo $(getconf ARG_MAX) 1>/dev/null


# cf. http://www.in-ulm.de/~mascheck/various/argmax/
(
argmaxbytes="$(expr $(getconf ARG_MAX) - $(env | wc -c) - $(env | wc -l) \* 4 - 2048)"
printf '\n%s\n\n' "argmaxbytes: $argmaxbytes"
./argmax echo "${argmaxbytes}" 1>/dev/null
printf '%s\n\n' "exit status: $?"
)

# get the exact maximum number of bytes for an argument list in the current shell
(
exec 2> >(nl -n ln)
exitval=1
argmaxbytes=$(getconf ARG_MAX)
until [[ $exitval -eq 0 ]]; do
  ./argmax echo "$argmaxbytes"  1>/dev/null
  exitval=$?
  (( argmaxbytes = argmaxbytes - 1 ))
done
(( argmaxbytes = argmaxbytes + 1 ))
printf '\n%s\n' "argmaxbytes: $argmaxbytes"
printf '\n%s\n' "test 1 using argmaxbytes:"
./argmax echo "$argmaxbytes"  1>/dev/null; echo "exit status: $?"
printf '\n%s\n' "test 2 using argmaxbytes + 1:"
./argmax echo $((argmaxbytes + 1))  1>/dev/null; echo "exit status: $?"
)

*/

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>


char *const *environ;

int main(int argc, char **argv) {

   if (argc != 3) return 1;

   int i=0, j=0, bytes=0, idx=0;

   bytes = atoi(argv[2]);


   // create a character string containing: cmd + 1 space + args + '\0'
   // + 2 for added space and final null byte '\0'
   // example: 
   // "./argmax echo 5 1>/dev/null" on the command line will be converted into:
   // char cmd[11] = {'e', 'c', 'h', 'o', ' ', '1', '1', '1', '1', '1', '\0' };

   char cmd[strlen(argv[1]) + bytes + 2];  

   // create char array with command as argv[1] + one space 
   idx=-1;
   for (i = 1; i < 2; i++)
   {
      for (j = 0; argv[i][j]; j++)
      {
         cmd[idx+=1]=argv[i][j];
      }
      cmd[idx+=1]='\x20';
   }


   idx=idx;
   for (i = 1; i <= bytes; i++)
   {
         cmd[idx+=1] = '1';
   }

   cmd[idx+=1]='\0';     // add a final zero byte '\0'


/*
   // for debugging only
   for (i = 0; cmd[i]; i++)
   {
      fprintf(stderr, "%i: %c\n", i, cmd[i]);
   }
   if (cmd[idx+=1] == '\0') fprintf(stderr, "%i: %s\n", i, "'\\0'");;

   fprintf(stderr, "sizeof(cmd): %zu\n", sizeof(cmd));
   fprintf(stderr, "last array index: %i\n", idx);
   //fprintf(stderr, "cmd: %s\n", cmd);
*/

   char *newargv[4] = {0};

   newargv[0] = "/bin/sh";
   newargv[1] = "-c";
   newargv[2] = cmd;
   newargv[3] = 0;


   execve("/bin/sh", newargv, environ);
   perror("execve");   /* execve() only returns on error */
   exit(errno);


/*

    // fork-exec alternative
   int status = 0;
   if(!fork())  // run child
   {
      execve("/bin/sh", newargv, environ);
      perror("execve");   /* execve() only returns on error */
      //printf("errno: %i\n", errno);
      _exit(errno);
   }
   wait(&status); 
   //fprintf(stderr, "child's exit code: %d\n", WEXITSTATUS(status));
   exit(WEXITSTATUS(status)); 

*/

}


You need to create an account or log in to post comments to this site.