/** SmS.c 1.2 by bob@dtors.net
 *
**/



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <getopt.h>
#include <time.h>

#define FOO_SIZE 160 /* Defines the size of the spam that sms2mail services
			 add to the end of your mail. The size doesnt need
			 to be precise. It must be at least 160 as thats the
			 max size of an SMS */

FILE *fp; // right, we need to open a file 
int l=0,d=0,k=0,p=0,o=0; // is option 1?
char log[40], spool[40], oaddy[20]; // too lazy to give it as a function argument

void usage (char *progname); // quite obvious ? 
void body (char exec[]); // the core bart of the loop 
void commandk (char pass[]); // if -k is used 
void commandnok (char pass[],char spool[]); // if -k is not used 
void commandnok (char pass[],char spool[]); // if -k is not used 

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

int option,i;
char pass[5]; // yeah, pass shouldnt be bigger then 5 chars

if (argc<5) usage(argv[0]); // enough args given ?

while((option=getopt(argc,argv,"kdhu:l:p:o:"))!=EOF){ // checking the args 
switch(option){
	case 'u': strncpy(spool,optarg,sizeof(spool)); break;
	case 'l': l=1; strncpy(log,optarg,sizeof(log)); break;
	case 'p': p=1; strncpy(pass,optarg,sizeof(pass)); break;
	case 'o': o=1; strncpy(oaddy,optarg,sizeof(oaddy)); break;
	case 'k': k=1; break;
	case 'd': d=1; break;
	case 'h': d=1; usage(argv[0]);
	default:usage(argv[0]);}
 }
// hiding the command in ps
strcpy(argv[0],"SmS_RA");
i=1;
while(i<argc){
	strcpy(argv[i],"                                          "); // alot of spaces, i know
	i++;
} // finished hiding the command in ps
if ((fp=fopen(spool,"a+"))==NULL){
	puts("Error: Cant read/write spool file!");
	sleep(1); exit(1);}

/* doing some passwd checking */
if(p!=1){
	puts("No password given!\nLeaving..."); 
	sleep(1);
	exit(1);}
if ((strlen(pass))<2){
	puts("Whats that for a strange passwd?\nLeaving...");
	sleep(1); exit(1);}
if ((strchr(pass,':'))!=0){
	puts("Never use a \":\" in a password!\nLeaving...");
	sleep(1); exit(1);}
/* ok, now the password is ok :) */
if(d==0){
	puts("Waiting for mail...");
	puts("CTRL-C to ABORT!\n");
}

if(d==1){
	puts("Going into daemon mode...");
	puts("Bye!\n");
	if (daemon(1, 1) < 0){
		puts("Going into daemon mode failed!\nLeaving...");
		sleep(1); exit(1);}
}
if(k==1) commandk(pass); // if -k is given 
if(k==0) { // if -k is not given
	truncate(spool,0);
	commandnok(pass,spool); }

fclose(fp);
return 0;
}

void usage (char *progname){
	printf("SMS-RA Usage: %s <-u> <-p> [options]\n",progname);
	puts("-u path:  Path to the spool file");
	puts("-l file:  Filename to log executed commands");
	puts("-p pass:  Passwd to use before command.");
	puts("-o addy:  Address to send command output to."); //can be an sms to mail service
	puts("-k:       Keep command mails in spool file");
	puts("-d:       Enter to daemon mode");
	puts("-h:       Your reading it!\n");
	puts("The -o addy syntax can also be used inside commands!\n");
	puts("Coded by bob and cjk.");
	exit(1);

}

	
void commandk (char pass[]){
int i=0, j=0; // i and j are often use to get incremnted, same here 
int ret=0; // needed to define some return values for my while loops 
long pos; // saves the offset of the position-file-pointer 
char command[160]; // where the sms we sent will get saved in
char executed[10]; // has the command already be executed?
char exec[160]; // the final string which will be executed 
while(1){
	sleep(2); // thats fast enough, doesn't need to be faster
	fseek(fp,0,SEEK_END); pos=ftell(fp);rewind(fp);
	if(pos<=FOO_SIZE) continue;
	fseek(fp,-FOO_SIZE,SEEK_END);
	while(!feof(fp)){
		i=0; j=0; ret=0;
		fgets(command,sizeof(command),fp); 
		pos=ftell(fp);
		if((strstr(command,pass))==NULL){ret=1; continue;}
		while(i<strlen(pass)){ // checking if the passwd is correct
			if(pass[i]!=command[i]){ret=1; break;}
			i++;
		}
		if(ret!=1) break;
	}
	if(ret==1) continue;
	fgets(executed,sizeof(executed),fp);
	fgets(executed,sizeof(executed),fp); // because we need to jump a line
	if((strstr(executed,"EXECUTED!"))!=NULL) continue; 
	// we dont wanna get a command execute twice, dont we

	
	i++; // + 1 to grep the command after the ":"
	while(i<strlen(command)){ // grepping the real command (no passwd)
		exec[j]=command[i];
		j++; i++;
	}
	
	exec[--j]='\0';
	body(exec); // now we call the body to do waht we need
	fseek(fp,pos,SEEK_SET);
	fputs("EXECUTED!\n",fp); // mark the command as executed 
		
 } 
}	


void commandnok (char pass[], char spool[]){ 
int i=0, j=0; // i and j are often use to get incremnted, same here 
int ret=0; // needed to define some return values for my while loops 
long pos; // saves the offset of the position-file-pointer 
char command[160]; // where the sms we sent will get saved in
char exec[160]; // the final string which will be executed 
while(1){
	sleep(2); // thats fast enough, doesn't need to be faster
	fseek(fp,0,SEEK_END); pos=ftell(fp);rewind(fp);
	if(pos<=FOO_SIZE) continue;
	
	while(!feof(fp)){
		i=0; j=0; ret=0;
		fgets(command,sizeof(command),fp); 
		if((strstr(command,pass))==NULL){ret=1;continue;}
		while(i<strlen(pass)){ // checking if the passwd is correct
			if(pass[i]!=command[i]){ret=1;break;} 
			i++;
		}
		if(ret!=1) break;
	}

	if(ret==1) continue;
	i++; // + 1 to grep the command after the ":"
	while(i<strlen(command)){ // grepping the real command (no passwd)
		exec[j]=command[i];
		j++; i++;
	}
	
	exec[--j]='\0';
	body(exec); // now we call the body to do waht we need
	fseek(fp,pos,SEEK_SET);
	fclose(fp);
	truncate(spool,0);
	if ((fp=fopen(spool,"r+"))==NULL){
		puts("Encounted an error!\nLeaving...");
		sleep(1); exit(1);}

 } 
}	



void body (char exec[]){  

char execlog[200]; // when we need to log... 
FILE *outp,*logp,*ftemp; // yep, three more Filer pointers are needed
char output[500]; // ouput of the command is kept in this string
char tempf[10], outaddy[20];
int out=0; // same as -o, but it the command body
time_t now; // needed to get the time
struct tm *zgr; // needed to get the time
int i=0, j=0; // i and j are often use to get incremnted, same here 

/* get the time */
time(&now);
zgr=localtime(&now);
/* finished, we got the time */

/* lets check if someone wants the output mailed */
if((strstr(exec,"-o"))==NULL) goto jump;
if ((strchr(exec,'@'))==0) goto jump;
i=(strstr(exec,"-o")-exec)+3; // position before "-o" +3 for the "-, the "o" and the " "
while(i<strlen(exec)){
	outaddy[j]=exec[i];
	i++; j++;
}
out=1;
exec[strstr(exec,"-o")-exec]='\0';
outaddy[j]='\0';
/* well noone seems to want the ouput mailed */

jump:  // we jumper here because the -o switch was not used

if (out==1 || o==1){ // it seems that we need to mail some output
	mkstemp(tempf);
	if ((ftemp=fopen(tempf,"w+"))==NULL){
        puts("Something happened!\nLeaving...");
	sleep(1); exit(1);}
}	
if(l==1){if ((logp=fopen(log,"a+"))==NULL){
        puts("Something happened!\nLeaving...");
        sleep(1); exit(1);}
}
if(d==0){
	puts("Command found in mail.");
	printf("*** EXECUTING COMMAND : %s\n",exec);
}
if((outp=popen(exec,"r"))==NULL){;
	puts("Something happened!\nLeaving...");
	sleep(1); exit(1);}
if(l==1) { // write output to the logfile
	fprintf(logp,"# DATE\n%s",asctime(zgr)); //logfile
	fprintf(logp,"# COMMAND\n%s\n",exec); //logfile
        fprintf(logp,"# RESULTS\n");}  //logfile
if (out==1 || o==1){ // write output to mailfile
	fprintf(ftemp,"# DATE\n%s",asctime(zgr)); //mailfile
	fprintf(ftemp,"# COMMAND\n%s\n",exec); //mailfile
        fprintf(ftemp,"# RESULTS\n");} //mailfile
while(!feof(outp)){
	fgets(output,sizeof(output),outp);
	if(d==0)printf(output);
	if(l==1)fprintf(logp,output); //logfile
	if(o==1 || out==1)fprintf(ftemp,output); //mailfile
	}
pclose(outp); // closing the process
if(l==1){fputs("# NEXT COMMAND ==========\n",logp);
	fclose(logp);}
if(o==1 || out==1){
	if(o==1){snprintf(execlog,sizeof(execlog),"cat %s | mail %s -s Commandreport",tempf,oaddy);
		 system(execlog);}
	if(out==1){snprintf(execlog,sizeof(execlog),"cat %s | mail %s -s Commandreport",tempf,outaddy);
		 system(execlog);}
	fclose(ftemp);
	remove(tempf);
 }
}
