Error when changing the console output to file in C - c

I'm new to stack overflow so bear with me :)
I am trying to create a custom linux shell as a project.
Right now I want to make the default output going to a file instead of console when the user uses > symbol for example ls > filename.txt
But , the program crashes and a Bad address error pops yet it writes the command output to the file.
#include <sys/wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
typedef char* string;
int main (int argc,char** argv) {
int error = 0;
int posIn=0; int posOut=0; int appendMark=0;
string Output,Input;
while (1) {
error=0;
char progName[255];
printf("\nmysh3 > ");
if(fgets(progName,500,stdin)==NULL){return 0 ;}
char dir[1024];
string params[40];
string pch=progName;
int i=0;
while ((pch = strtok (pch," \n")) != NULL){
params[i]=pch;
if (strcmp(pch,"<")==0) { posIn = i;params[i]=NULL;i--;} // < is skipped and we put only the name of the command on the params array
if (strcmp(pch,">")==0) { posOut = i;params[i]=NULL;i--;} //output
if (strcmp(pch,">>")==0) {appendMark=1;params[i]=NULL;i--;}
i++;
pch = NULL;
}
params[i]=NULL;
if(strlen(progName)>255){
printf("The commands can't be over 255 characters\n");
return 0;
}
if (posOut) {
int out = open(params[posOut], O_CREAT|O_TRUNC|O_WRONLY, 0777);
params[posOut]=NULL;
if (out < 0) {
error = 1;
fprintf(stderr,"open error: %d [%s]\n",errno,strerror(errno));
exit(1); }
int k = dup2(out,1);
if (k<0) {
error = 1;
perror("Cannot redirect output");
}
close(out);
}
pid_t proccess1,waitpid;
int status;
proccess1 = fork();
if (proccess1<0) {perror("Out of memory"); } //Monos tropos na apotyxei h fork einai na mhn yparxei mnhmh
else if (proccess1==0) {
execvp(params[0],params);
if (!error) {perror("Unknown command");}
}
else {
waitpid=wait(&status);
if (waitpid==-1) {perror("ERROR: A NEW ZOMBIE IS BORN 3:)");return 0;}
}
}
return 0; }

Related

How do I fix "copy: Bad file descriptor" in my C program

Hello I'm working on a program that prints all the characters like a cat program by using the POSIX functions, the program has to get more than one file when it does it writes the characters of all files in the destination file.
For example;
mycat.exe x.txt y.txt z.txt dest.txt
means write all the characters from x.txt, y.txt and z.txt in order to the file destination dest.txt that it's created after we run the program.
If any file not exits the program will not exit it prints a report that
file not exists
If any error occur, you have to exit the program.
When I compile it it compiles without any error(I'm compiling it in Windows 10), but when i try to run it it shows an error.
This is how I compile it:
gcc -o mycp.exe mycp.c
This is how i run it:
mycp.exe x.txt y.txt z.txt dest.txt
This is the error:
copy: Bad file descriptor
This is the code inside the mycp.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#define BUFSIZE 1024
void exit_sys(const char* msg)
{
perror(msg);
exit(EXIT_FAILURE);
}
void exit_fail(const char* msg)
{
fprintf(stderr, "%s\n", msg);
exit(EXIT_FAILURE);
}
void remove_dest_file(int fd, char** argv, int i)
{
_close(fd);
unlink(argv[i]);
}
int copy_file(int fdd, int fds)
{
char buf[BUFSIZE];
int n;
while ((n = read(fds, buf, BUFSIZE)) > 0)
{
_write(fdd, buf, n);
}
if (n < 0)
{
return n;
}
return 0;
}
int main(int argc, char** argv)
{
int fds, fdd;
int n;
char buf[BUFSIZE];
int ch;
int flags;
int argcm1;
int i;
flags = _O_WRONLY | _O_CREAT;
if (argc < 2)
exit_fail("usage:mycp.exe file1.exe file2.exe file3.exe ... filen filedest.exe");
argcm1 = argc - 1;
if (!access(argv[argcm1], F_OK)) {
printf("The file %s exists. Do you want to overwrite?[y]\n", argv[argcm1]);
ch = getchar();
if (ch == 'y' || ch == 'Y')
flags |= _O_TRUNC;
else
exit(EXIT_SUCCESS);
}
if ((fdd = _open(argv[argcm1], flags, _S_IREAD | _S_IWRITE)) < 0)
{
exit_sys("open for destination");
}
for (i = 0; i < argcm1; ++i)
{
if (fds = _open(argv[i], _O_RDONLY) < 0)
{
remove_dest_file(fdd, argv, argcm1);
exit_sys("open");
}
if (copy_file(fds, fdd) < 0)
{
remove_dest_file(fdd, argv, argcm1);
exit_sys("copy");
}
_close(fds);
}
printf("Succes");
_close(fdd);
return 0;
}

Problem doing a system call, the system call is not displaying to kernel

In Ubuntu, I wrote a new system call:
SYSCALL_DEFINE1(print_other, pid_t, targetpid)
{
struct task_struct *p;
int found = 0;
for(p = &init_task; next_task(p) != &init_task; p=next_task(p))
{
if(p->pid == targetpid)
{
found = 1;
break;
}
}
if (found)
{
for(p = current; p != &init_task; p = p->parent)
{
printk("Task:\n");
printk("Process ID: %d\n", p->pid);
printk("Running state: %ld\n", p->state);
printk("Program name: %s\n", p->comm);
printk("Start time: %llu\n", p->start_time);
printk("Virtual runtime: %llu\n\n", p->se.vruntime);
}
}
else
{
printk("Your process was not found");
}
return 0;
}
This is my testing file:
#include <linux/unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define __NR_print_other 337
int main(int argc, char *argv[])
{
char search[10];
char *error;
pid_t in_pid;
unsigned long pid;
while (true)
{
printf("Enter PID to search: ");
scanf("%s", search);
printf("passed scanf\n");
pid = strtoul(search, &error, 10);
printf("passed strtoul\n");
if (*error || error == argv[1] || ((pid_t)pid != pid ||
(pid_t)pid <= 0))
{
printf("in if statement\n");
printf("\nError: Invalid PID entered\n");
printf("Try again\n");
}
else
{
printf("in else statement\n");
in_pid = pid;
syscall(__NR_print_other, in_pid);
printf("about to return, in_pid = %d\n", in_pid);
return 0;
}
}
}
But the testing file is good. The system call is not doing anything and I cannot see why. What am I supposed to do that I am doing wrong?
I don't really have anything left to find. I checked the testing file and it runs properly. It returns that the in_pid is correct and runs the error bounds checks properly. There must be a logical error in the system call but I don't see what the problem would be.
Your system call is working and doing something. Just run dmesg and you should see something similar to this:
[ 3755.306897] Task:
[ 3755.306898] Process ID: 1
[ 3755.306899] Running state: 1
[ 3755.306900] Program name: systemd
[ 3755.306902] Start time: 371331827
[ 3755.306903] Virtual runtime: 1757840935

client/server print out array and write back

I am using C and putty to write a client/server program.
Both c files are on the same system.
I am currently having an issue with writing back to the client the frames it is using as well as printing out my frames. It prints out 3 0 9 8 but then it starts printing out 13456756 etc.
Here is what I have:
server:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
main (void)
{
int to_server; // to read from client
int from_server; // to write to client
int finish; // lets me know that client is done
int i,j,k,m,l; // because C needs this defined as int
int numClient;// number of clients
char temp[14];
int page_size = 128;
int pages_left;
int max_frames=10;
int used_frames =0;
int frameUpdate=0;
int freeframe[10] = {3,0,9,8,7,5,1,4,2,6}; //this is the array
int numpage=0;
int frames;
int check;
int option;
int byte;
int getPage;
int getOffset;
int physical_Addr;
int offset;
int req[3];
int again;
struct values{
char privFifo[14];
int memoryreq;
}cinput;
/* Create the fifos and open them */
if ((mkfifo("FIFO1",0666)<0 && errno != EEXIST))
{
perror("cant create FIFO1");
exit(-1);
}
if((to_server=open("FIFO1", O_RDONLY))<0){
printf("cant open fifo to write");
}
//get number of clients
printf("\nHow many clients?\n");
scanf("%d", &numClient);
for(j =1; j <= numClient; j++){
read(to_server, &cinput, sizeof(cinput));
printf("\n\nFifo_%d \nMemory request %d", &cinput.privFifo, cinput.memoryreq);
req[j-1] = cinput.memoryreq;
if((mkfifo(cinput.privFifo,0666)<0 && errno != EEXIST))
{
perror("cant create privFifo");
exit(-1);
}
if((from_server=open(cinput.privFifo, O_WRONLY)<0)){
printf("cant open fifo to write");
}
// find number of pages need for request
numpage = cinput.memoryreq/page_size;
if((numpage * page_size) < cinput.memoryreq){
numpage++;
}
sleep(1);
printf("\nPages needed %d", numpage);
write(from_server, &numpage, sizeof(numpage));
printf("\n******Main Memory******");
for(m = used_frames; m < numpage; m++){
printf("\n* client: %d\tframe: %d", j, freeframe[m]);
frames = freeframe[m];
write(from_server, &frames, sizeof(frames));
}
used_frames = max_frames - used_frames;
pages_left = max_frames - numpage;
//this is where I try to print out the available frames
printf("\n Frames available:");
for(l = pages_left; l!= 0; l--){
check = max_frames - l;
printf(" %d", freeframe[check]);
max_frames = check;
}
close(from_server);
unlink(cinput.privFifo);
}
printf("\nDONE!!!");
close(to_server);
unlink("FIFO1");
client:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
main (void)
{
int to_server; // to write to server
int from_server;
char temp[14]; // server puts string here
int clientID;
//int frames;
int numpage;
int i;
struct values{
char privFifo[14];
int memoryreq;
}cinput;
if((to_server=open("FIFO1", O_WRONLY))<0)
printf("cant open fifo to write\n");
printf("writing data to to_server\n");
printf("Client: Please enter number of memory units: ");
scanf("%d", &cinput.memoryreq);
printf("%d", cinput.memoryreq);
clientID = getpid();
sprintf(cinput.privFifo, "Fifo_%d", getpid());
printf("\nFifo name is %s", &cinput.privFifo);
write(to_server, &cinput, sizeof(cinput));//write client pid and memUnit to server
sleep(2); //give time to send
printf("\nClient: Got the character sent, now waiting for response ");
if ((mkfifo(cinput.privFifo,0666)<0 && errno != EEXIST))
{
perror("cant create FIFO1");
exit(-1);
}
if((from_server=open(cinput.privFifo, O_RDONLY))<0){
printf("cant open fifo to write");
}
read(from_server, &numpage, sizeof(numpage));
printf("\nFrames Occupied %d", numpage);
close(to_server);
close (from_server);
unlink(cinput.privFifo);
printf ("\nall done!\n");
}
Any help is greatly appreciated. Thank you.
I strongly suspect the problem is the line used_frames = max_frames - used_frames;. Since used_frames is initially 0, that sets it one past the end of the array for the second iteration, so you start printing values past the end of your frame array when you run for(m = used_frames; m < numpage; m++). (By the way: please indent properly.). But set a breakpoint and run in a debugger to be sure.

pass arguments to running C app

I am writing small C program which will act like daemon and do something every second. I managed it to run only single instance using filelock and last thing I need to know is if it is possible to send commandline arguments to running program, something like that:
first program start:
./sampleprogram
then decide to take some action/update setting
./sampleprogram -r
it will be another rotation script for my thinkpad X41 convertible:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
/*#include <stdbool.h>*/
#define TRUE 1
#define FALSE 0
#define NIL -1
int fdlock;
int get_lock(void)
{
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 1;
if((fdlock = open("oneproc.lock", O_WRONLY|O_CREAT, 0666)) == -1) { return 0; }
if(fcntl(fdlock, F_SETLK, &fl) == -1) { return 0; }
return 1;
}
int main() {
if(!get_lock()) {
fputs("Process already running!\n", stderr);
return 1;
}
int tabletmode;
int autorotate = TRUE;
int prevmode = NIL;
FILE *fstate;
char state[1];
FILE *fgyrovals;
char gyroval_a[1];
while (TRUE) {
fstate = fopen("/sys/devices/platform/thinkpad_acpi/hotkey_tablet_mode", "r");
fread(state, sizeof(state[0]), 1, fstate);
/*
printf("picaa");
fflush(stdout);
*/
/*tabletmode = atoi(state[0]);*/
tabletmode = state[0] - '0';
printf("koko: %d", tabletmode);
fflush(stdout);
fclose(fstate);
if (prevmode != tabletmode) {
if (tabletmode) {
system("notify-send 'Notebook v tablet móde'");
} else {
system("notify-send 'Notebook v štandartnom režime'");
}
}
if (tabletmode) {
if (autorotate) {
fgyrovals = fopen("/sys/devices/platform/hdaps/position", "r");
fclose(fgyrovals);
}
}
prevmode = tabletmode;
sleep(1);
}
return 0;
}

shell with input & output on files in C

I'm having some trouble to run an interactive shell (/bin/bash, /bin/sh for ins) in the background with input and output redirected in files. I tried different things but it does not work.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void) {
char *argve[2];
argve[0]="/bin/sh";
argve[1]=NULL;
FILE *fichin, *fichout;
fichin=fopen("/root/C/fichin.temp", "w+");
fichout=fopen("/root/C/fichout.temp", "w+");
dup2(fileno(fichin), 0); //stdin
dup2(fileno(fichout), 1); //stdout
dup2(fileno(fichout), 2); //stderr
/*freopen("/root/C/fichin.temp", "r", stdin);
freopen("/root/C/fichout.temp", "w+", stdout);*/
system("/bin/sh");
//execve("/bin/sh", argve, NULL);
return 0;
}
you want this :
/* shell interactive */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int main(int argc, char **argv) {
int file_input ;
int file_output;
int size_read = 0;
pid_t pid_command;
char _command[10];
char *read_one_char=NULL;
char command_separator;
int i=0;
/* open file input on READONLY */
/* open return file descriptor */
file_input = open("fichin.temp", O_RDONLY , 0666);
if (file_input <0 )
{
perror("can't open input file");
}
file_output = open("fichout.temp", O_CREAT | O_TRUNC | O_WRONLY , 0666) ;
if (file_output < 0)
{
perror("can't open output file");
}
read_one_char = malloc(sizeof(char));
if (read_one_char == NULL)
{
perror(" malloc failed ");
}
dup2(file_input, 0); //stdin
dup2(file_output, 1); //stdout
dup2(file_output, 2); //stderr
/*reading commands assuming that each line is a command
command 1
command 2
..
command n
you can change command_seperator
*/
command_separator = '\n';
do
{
size_read = read(file_input,(void*)read_one_char,1);
if (*read_one_char!=command_separator && size_read > 0)
{
_command[i]=*read_one_char;
i++;
}
else
{
_command[i--]='\0';
i=0;
write(1,"\n\t============ output for command ==========\n",45);
system(_command);
}
}while(size_read != 0);
return 0;
}
i wrote it quickly; try it and tell me if its that you want

Resources