(Osh) Omake Error: Unexpected Token: String: { - c

I am working on an assignment for class, in which we have to build a simple shell interface for a Unix system in C. I am using Ubuntu and when I run the source code in that was provided using this command:
osh> cat shell.c
I get an error:
*** omake error: File /home/cameron/cs426/Project1/shell.c: line 11, characters 20-24
unexpected token: string: {
This is my first time using osh, so does anyone have any ideas as to what the issue might be?
Also, here's the code, just in case.
#include<stdio.h>
#include<unistd.h>
#define MAX_LINE 80 /* 80 chars per line, per command */
int main(void)
{
char *args[MAX_LINE/2 + 1]; /* command line (of 80) has max of 40 arguments */
int should_run = 1;
while(should_run){
printf("osh>");
fflush(stdout);
/**
* After reading user input, the steps are:
* (1) fork a child process
* (2) the child process will invoke execvp()
* (3) if command included &, parent will invoke wait()
*/
}
return 0;
}

It looks like this code was intended to be a shell. What you need to do is:
Open a terminal that runs a real shell. osh is the OMake shell, and is probably not relevant this assignment. The code you gave prints "osh", but isn't the osh.
Compile with gcc -o shell-that-calls-itself-osh shell.c The -o flag tells gcc where to put the compiled binary.
Run with ./shell-that-calls-itself-osh The ./ is to run code in the current directory.

Related

Syntax error reported in basic C code - what is wrong?

The code is given below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main ( int argc, char *argv[] )
{
//FILE *fps;
char secret[512] =" ";
FILE *fps = fopen("/etc/comp2700/share/secret", "r");
if(fps == NULL)
{
printf("Secret file not found\n");
return 1;
}
fgets(secret, 512, fps);
printf("Secret: %s\n", secret);
fclose(fps);
return 0;
}
When I am trying to run this program it is repeatedly throwing the following error:
./attack1.c: line 4: syntax error near unexpected token `('
./attack1.c: line 4: `int main ( int argc, char *argv[] )'
You need to compile your source file with gcc as follows
gcc -o attack attack1.c
then run it with
./attack
You should read up on the difference between compiled versus interpreted languages.
There is a short video here explaining the difference.
You cannot run your C program from the command line as ./attack1.c. Normally the shell would refuse to execute the C source file because it should not have execute permission, but for some reason, on your system, it must have the x bits and is read by the default shell as a script.
Of course this fails because attack1.c contains C code, not a command file. Note that the #include lines are interpreted as comments by the shell and the error only occurs at line 4.
To run a C program, you must first compile it to produce an executable:
gcc -Wall -o attack1 attack1.c
And then run the executable if there were no compilation errors:
./attack1
You can combine these commands as
gcc -Wall -o attack1 attack1.c && ./attack1
First, you need to compile the attack.c code using the following command:
gcc attack.c
This will create one executable file a.out which you can run using the following command:
./a.out
Hope this helps you.

Errors when Compiling my First C Program

I am running Ubuntu on a virtual machine with gcc downloaded. I wrote up a code in gedit which contains:
#include <stdio.h>
/* This is a comment. */
int main(int argc, char *argv[])
{
int distance = 100;
// this is also a comment
printf("You are %d miles away.\n", distance);
return 0;
}
When I do the make Ex1.c it says that my file is 'up to date.' so I type in ./Ex1.c and it gives me these errors:
./Ex1.c: line 3: /bin: Is a directory
./Ex1.c: line 4: syntax error near unexpected token '('
./Ex1.c: line 4: 'int main(int arc, char*argv[])'
I don't understand this, I thought it might be how I am typing the code in but then I pasted the code in from the 'Learn C the Hard Way' GitHub and I still get these errors! I just want to run my dang code!
Do it this way.
Open terminal write gedit ex1.c
In the new gedit window write the code.
Close the gedit window.
In the terminal write gcc ex1.c
In the terminal write ./a.out
You're trying to run the source code file.
You have to run the compiled binary.
The compiled binary is often called a.out.
Try doing ./a.out

No error message when using system() to execute program with buffer overflow vulnerability

Consider the following program (vul.c) with buffer overflow vulnerability.
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
char buf[10];
strcpy(buf, argv[1]);
printf("%s\n", buf);
return 0;
}
Above program compiled using gcc -o vul vul.c and executed on arch linux - linux 4.4.16-1-lts x86-64 gave following output when executed in terminal with ./vul $(perl -e 'print "A"x100') command:
AAAAAAAAAAA...A
Segmentation fault (core dumped)
Then checking the program status using echo $? command gave 139 output.
Following program (exp.c) (for crashing the above program)
#include <stdlib.h>
int main(void)
{
printf("%d\n", system("./vul $(perl -e 'print \"A\"x100')"));
return 0;
}
compiled using gcc -o exp exp.c when executed with ./exp command on same system gave following output:
AAAAAAAAAAAA...A
139
I have two questions:
Why no error message was generated by 2nd program? and,
I need to compile the program with -fstack-protector flag to enable the *** stack smashing detected *** error messages in arch linux but not in Ubuntu. In Ubuntu, it might be that this flag is include by default in gcc or is there any other reason?
As I pointed out in my comment,system returns an int with the programs's return value, which is normally it's error code (0 if successful).
If you want to print the error as a nice looking message, you can probably use strerror.
According to #rht's comment (see my next edit) and the answers to the question referenced in that comment, the returned value will be 0 on success and on error it will be error | 0x80. To get the original error code, use 128 - err_code.
try this:
#include <stdlib.h>
#include <errno.h>
int main(void)
{
int tmp = system("./vul $(perl -e 'print \"A\"x100)");
if(tmp < 0)
error("Couldn't run system command");
else if(tmp >0)
printf(stderr, "System command returned error: %s", strerror(128 - tmp));
else
; // nothing
return 0;
}
The fact that vul.c does (or does not) print an error message should be irrelevant for your exp.c program, since it depends on vul.c's compile flags values and any default compiler flags - things exp.c can't control.
EDIT(2) - in answer to the comment.
It could be that the error message returned isn't an errno value, but a signal trap value.
These are sometimes hard to differentiate and I have no good advice about how you can tell which one it is without using memcmp against the answer.
In this case you know vul.c will never return it's errno value, which leaves you only with signal trap errors, so you can use strsignal to print the error message.
As pointed out in #rht's comment, which references this question:
Passing tmp to strsignal generates the same error message: "unknown signal 139". The reason is that there is no signal with this signal number. /usr/include/bits/s‌​ignum.h contains all the signals with their signal numbers. Passing tmp-128 to strsignal works.
i.e.
#include <stdlib.h>
#include <string>
int main(void)
{
int tmp = system("./vul $(perl -e 'print \"A\"x100)");
if(tmp < 0)
error("Couldn't run system command");
else if(tmp >0)
printf(stderr, "System command returned error: %s", strsignal(tmp - 128));
else
; // nothing
return 0;
}
EDIT
The question was edited because it's code was mis-copied. I altered the answer to reflect that change.
From my comment to #Myst 's answer for "passing tmp-128 to strsignal()" function, after experimenting a little I found that it does not work in situations where the program exited normally but returned status other than 0.
Following are the contents of my /usr/include/bits/waitstatus.h:
/* If WIFEXITED(STATUS), the low-order 8 bits of the status. */
#define __WEXITSTATUS(status) (((status) & 0xff00) >> 8)
/* If WIFSIGNALED(STATUS), the terminating signal. */
#define __WTERMSIG(status) ((status) & 0x7f)
/* Nonzero if STATUS indicates normal termination. */
#define __WIFEXITED(status) (__WTERMSIG(status) == 0)
/* Nonzero if STATUS indicates termination by a signal. */
#define __WIFSIGNALED(status) \
(((signed char) (((status) & 0x7f) + 1) >> 1) > 0)
Above code show that, exit status of a program is a 16bit number, the high order 8 bits of which are the status that the program returned and some/all of the remaining bits are set if the program exited because of a signal, 7 bits of which denote the signal that caused the program to exit. That's why subtracting 128 from the exit status returned by system() will not work in the situation as described above.
System()'s source code
Since system() function too uses fork() to create a new process and waits for the termination of the process, the same method of checking a child process's status in parent process can also be applied here. Following program demonstrates this:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
int main(void)
{
int status = system("prg_name");
if (WIFEXITED(status))
printf("Exited Normally, status = %d\n", WEXITSTATUS(status));
else if (WIFSIGNALED(status))
printf("Killed by Signal %d which was %s\n", WTERMSIG(status), strsignal(WTERMSIG(status)));
return 0;
}
Answering my own 2nd question.
gcc -Q -v vul.c command displayed the options passed to the gcc. The options in Ubuntu included -fstack-protector-strong flag but not in arch-linux. So in Ubuntu, the flag is passed by default to gcc.
There exists two problems in your vul.c and exp.c.
In vul.c,
char buf[10];
10 is not sufficient in this case, since the argv[1], i.e., $(perl -e 'print "A"x100', is larger than the buffer to be allocated. Enlarge the buf size should fix the segmentation fault.
In exp.c, you're missing one single quote, and should be modified as followed:
printf("%d\n", system("./vul $(perl -e 'print \"A\"x100')"));

executing a program in C linux using fork and exec

I want to execute a C program in Linux using fork and exec system calls.
I have written a program msg.c and it's working fine. Then I wrote a program msg1.c.
When I do ./a.out msg.c, it's just printing msg.c as output but not executing my program.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* for fork */
#include <sys/types.h> /* for pid_t */
#include <sys/wait.h> /* for wait */
int main(int argc,char** argv)
{
/*Spawn a child to run the program.*/
pid_t pid=fork();
if (pid==0)
{ /* child process */
// static char *argv[]={"echo","Foo is my name.",NULL};
execv("/bin/echo",argv);
exit(127); /* only if execv fails */
}
else
{ /* pid!=0; parent process */
waitpid(pid,0,0); /* wait for child to exit */
}
return 0;
}
argv[0] contains your program's name and you are Echo'ing it.
Works flawlessly ;-)
/bin/echo msg.c will print msg.c as output if you need to execute your msg binary then you need to change your code to execv("path/msg");
your exec executes the program echo which prints out whatever argv's value is;
furthermore you cannot "execute" msg.c if it is a sourcefile, you have to compile (gcc msg.c -o msg) it first, and then call something like exec("msg")
C programs are not executables (unless you use an uncommon C interpreter).
You need to compile them first with a compiler like GCC, so compile your msg.c source file into a msg-prog executable (using -Wall to get all warnings and -g to get debugging info from the gcc compiler) with:
gcc -Wall -g msg.c -o msg-prog
Take care to improve the msg.c till you get no warnings.
Then, you might want to replace your execv in your source code with something more sensible. Read execve(2) and execl(3) and perror(3). Consider using
execl ("./msg-prog", "msg-prog", "Foo is my name", NULL);
perror ("execl failed");
exit (127);
Read Advanced Linux Programming.
NB: You might name your executable just msg instead of msg-prog ....

printf doesn't work, even with newline and fflush()

I'm compiling the below C code with gcc. No errors are thrown during compilation or at runtime. I ran through the code with gdb, and the answer given in sum is correct at the end, yet the printf() does not display anything on the screen. I've tried all sorts of combinations of fprintf(), printf(), and fflush(), but nothing works.
What do I need to change so the program will print the result to stdout?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num = 9;
int i, sum; i = 1, sum = 0;
while (i < 2 * num) {
sum = sum + i * i;
++i;
}
printf("sum: %d\n", sum);
fflush(stdout);
return 0;
}
The code is correct, and should print sum: 1785 for any conforming implementation.
This is a guess (update: which turns out to be correct), but ...
You've named the source file test.c, and you compile it with:
$ gcc test.c -o test
(or something similar) and execute it with:
$ test
which produces no output.
The problem is that test is a standard Unix command (and also a built-in command in some shells). When you type a command name to the shell, it first looks for built-in commands, then for executables in directories specified in your $PATH environment variable.
To execute a command in the current directory, prepend ./ to the name:
$ ./test
sum: 1785
$
This applies to any command in the current directory. There are so many built-in commands that you can't reasonably avoid colliding with them. Cultivating the habit of running executables in the current directory by typing ./whatever means that name collisions don't matter.
(Don't be tempted to add . to the front of your $PATH; that's dangerous. Think about what could happen if you cd into a directory and type ls, if there happens to be a malicious ls command there.)
There is nothing wrong with your program. It has to work. Try running it with redirection:
./a.out > myout
..and see if you get any output. If not, I'd suspect there is a problem with some kind of standard library mismatch.
Another option to check would be to build using SUN C compiler as opposed to gcc and see if that works. If it does, gcc is the culprit.

Resources