Some of this code might not make any sense, (perhaps even I am perplexed) about how this happened and why? This code was intended for some other purpose, (i was trying to make a calculator, so the main source code [which had few problems] exists on this site as my question) i somehow broke it and so i modified it and extracted the code which initially broke it.
I tested it on Kali Linux.
Here's the code:
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
//Some of this might not make any sense, but its the way i was able to break it.. somehow
int main(int argc,char *argv[]) {
FILE *file = fopen(argv[2],"a");
if(file == NULL) {
printf("Error Opening File!");
return 1;
}
char ch;
int i;
printf("%i\n",argc);
printf("%i\n",argv);
while((ch = getopt(argc,argv,"d:"))!=EOF)
switch(ch) {
case 'd':
for(i=4; i<=48; i++) // This loop may vary on other system. On first run i used "i<=51" , and on different system, same os, its the mentioned condition
fprintf(file,"%s \n",argv[i]);
fclose(file);
break;
default:
fprintf(stderr,"No such command");
}
argc-=1;
argv+=1;
return 0;
}
The following result was produced upon running (the original source code. This code will write it to a file) :
value at argv= LS_COLORS=rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:mi=00:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:.tar=01;31:.tgz=01;31:.arc=01;31:.arj=01;31:.taz=01;31:.lha=01;31:.lz4=01;31:.lzh=01;31:.lzma=01;31:.tlz=01;31:.txz=01;31:.tzo=01;31:.t7z=01;31:.zip=01;31:.z=01;31:.Z=01;31:.dz=01;31:.gz=01;31:.lrz=01;31:.lz=01;31:.lzo=01;31:.xz=01;31:.zst=01;31:.tzst=01;31:.bz2=01;31:.bz=01;31:.tbz=01;31:.tbz2=01;31:.tz=01;31:.deb=01;31:.rpm=01;31:.jar=01;31:.war=01;31:.ear=01;31:.sar=01;31:.rar=01;31:.alz=01;31:.ace=01;31:.zoo=01;31:.cpio=01;31:.7z=01;31:.rz=01;31:.cab=01;31:.wim=01;31:.swm=01;31:.dwm=01;31:.esd=01;31:.jpg=01;35:.jpeg=01;35:.mjpg=01;35:.mjpeg=01;35:.gif=01;35:.bmp=01;35:.pbm=01;35:.pgm=01;35:.ppm=01;35:.tga=01;35:.xbm=01;35:.xpm=01;35:.tif=01;35:.tiff=01;35:.png=01;35:.svg=01;35:.svgz=01;35:.mng=01;35:.pcx=01;35:.mov=01;35:.mpg=01;35:.mpeg=01;35:.m2v=01;35:.mkv=01;35:.webm=01;35:.ogm=01;35:.mp4=01;35:.m4v=01;35:.mp4v=01;35:.vob=01;35:.qt=01;35:.nuv=01;35:.wmv=01;35:.asf=01;35:.rm=01;35:.rmvb=01;35:.flc=01;35:.avi=01;35:.fli=01;35:.flv=01;35:.gl=01;35:.dl=01;35:.xcf=01;35:.xwd=01;35:.yuv=01;35:.cgm=01;35:.emf=01;35:.ogv=01;35:.ogx=01;35:.aac=00;36:.au=00;36:.flac=00;36:.m4a=00;36:.mid=00;36:.midi=00;36:.mka=00;36:.mp3=00;36:.mpc=00;36:.ogg=00;36:.ra=00;36:.wav=00;36:.oga=00;36:.opus=00;36:.spx=00;36:.xspf=00;36:
value at argv= XDG_MENU_PREFIX=gnome-
value at argv= LANG=en_IN
value at argv= GDM_LANG=en_IN
value at argv= MANAGERPID=793
value at argv= DISPLAY=:1
value at argv= INVOCATION_ID=3e7f771adfde4001af637f9527e9cc9d
value at argv= COLORTERM=truecolor
value at argv= USERNAME=root
value at argv= XDG_VTNR=2
value at argv= SSH_AUTH_SOCK=/run/user/0/keyring/ssh
value at argv= S_COLORS=auto
value at argv= XDG_SESSION_ID=3
value at argv= USER=root
value at argv= DESKTOP_SESSION=gnome
value at argv= PWD=/media/root/F89AF7139AF6CCDE
value at argv= HOME=/root
value at argv= JOURNAL_STREAM=9:19456
value at argv= SSH_AGENT_PID=945
value at argv= QT_ACCESSIBILITY=1
value at argv= XDG_SESSION_TYPE=x11
value at argv= XDG_DATA_DIRS=/usr/share/gnome:/usr/local/share/:/usr/share/
value at argv= XDG_SESSION_DESKTOP=gnome
value at argv= DBUS_STARTER_ADDRESS=unix:path=/run/user/0/bus,guid=11c587e1337f9fb06858c2415bbac73a
value at argv= GTK_MODULES=gail:atk-bridge
value at argv= WINDOWPATH=2
value at argv= TERM=xterm-256color
value at argv= SHELL=/bin/bash
value at argv= VTE_VERSION=5002
value at argv= DBUS_STARTER_BUS_TYPE=session
value at argv= XDG_CURRENT_DESKTOP=GNOME
value at argv= GPG_AGENT_INFO=/run/user/0/gnupg/S.gpg-agent:0:1
value at argv= SHLVL=1
value at argv= XDG_SEAT=seat0
value at argv= LANGUAGE=en_IN:en
value at argv= WINDOWID=39845894
value at argv= GDMSESSION=gnome
value at argv= GNOME_DESKTOP_SESSION_ID=this-is-deprecated
value at argv= LOGNAME=root
value at argv= DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/0/bus,guid=11c587e1337f9fb06858c2415bbac73a
value at argv= XDG_RUNTIME_DIR=/run/user/0
value at argv= XAUTHORITY=/run/user/0/gdm/Xauthority
value at argv= PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
value at argv= SESSION_MANAGER=local/kali:@/tmp/.ICE-unix/894,unix/kali:/tmp/.ICE-unix/894
value at argv= _=./a.out
value at argv= (null)
My question that follows is, what actually are environment variables? And why did my give me such results?
// probably use one option at a time
//This code has some flaws, for example i didnt check if the file was opened
or not, etc, pardon me for it. This is the actual un-edited source of the
code.
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
int add(int a,int b){
return a+b;
}
int subtract(int a, int b){
return a-b;
}
int main(int argc, char *argv[]){
FILE *file1 = fopen("Results.txt","a");
char ch;
int res;
while((ch=getopt(argc,argv,"a:s:"))!=EOF)
switch (ch){
case 'a':
res = add(atoi(optarg),atoi(argv[3]));
fprintf(file1,"%i\n",res);
break;
case 's':
res = subtract(atoi(optarg),atoi(argv[3]));
printf("%i \n",res);
fprintf(file1,"%i\n",res);
break;
default:
fprintf(stderr,"No such option");
return 1;
}
//THe commented out section produces weird behaviour...
//printf("Opind = %i, argc = %i, argv = %i \n",optind,argc,argv);
argc-=optind;
//printf("value at optarg = %i value at argv_3= %s \n",optarg,argv[3]);
argv+=optind;
//printf("Opind = %i, argc = %i, argv = %i \n",optind,argc,argv);
//printf("value at optarg = %i value at argv_3= %s \n",optarg,argv[1]);
fprintf(file1,"\nWritten to file\n");
fclose(file1);
return 0;
}
First of all, going out of bounds of an array leads to undefined behavior. You probably do that when you iterate over the argv
array without checking for e.g. i < argc
(unless you actually provide over 48 arguments on the command line).
Secondly, as for why you print the environment variables when going out of bounds of argv
, it's because on POSIX systems (like Linux or macOS) there's a third argument to the main
function, usually called environ
. Similar to argv
it's an array of strings (declared the same way, e.g. char *environ[]
) that contains the environment variables. By going out of bounds of argv
you go into the memory for the environ
array.
On a related note, you use argv[2]
without any checking that the argument actually exists, or that it's not any other argument you parse with getopt
. Don't do that.
Also note that the getopt
function returns an int
. This is actually very significant and important for the check against -1
(not EOF
!).