-1

c lang, ubuntu so i have a task - write a menu with these 3 options: 1. close program 2. show user id 3. show current working directory

i can only use 3 libraries - unistd.h, sys/syscall.h, sys/sysinfo.h. so no printf/scanf i need to use an array of a struct im given, that has a function pointer, to call the function the user wants to use.

problem is on options 2 & 3; when i pick 2, on the first time it works fine (i think) second time i pick 2, it works, but then when going to the third iteration, it doesn't wait for an input, it takes '\n' as an input for some reason, then it says invalid input. (i checked what it takes as input with printf, i printed index after recalculating it and it because -39, so it means selection[0] = 10 = '\n')

that's the first problem, that i just cant find the solution for.

second problem is on the current working directory function; the SYS_getcwd returns -1 for some reason, which means there's an error, but i cant figure it out.

any explanations for these things?

(also - slen and __itoa are functions i am given - slen returns the length of a string, __itoa returns a char*, that was the string representation of an integer)

helper.h:

typedef struct func_desc {
char *name;
void (*func)(void); 
} fun_desc;

main.c:

#include <unistd.h>
#include "helper.h"
#include <sys/syscall.h>
#include <sys/sysinfo.h>

void exitProgram();
void printID();
void currDir();

int main() {
    fun_desc arrFuncs[3];
    arrFuncs[0].name = "exitProgram";
    arrFuncs[0].func = &exitProgram;
    arrFuncs[1].name = "printID";
    arrFuncs[1].func = &printID;
    arrFuncs[2].name = "currDir";
    arrFuncs[2].func = &currDir;
    char selection[2];
    int index;
    const char* menu = "Welcome to the menu. Please pick one of the following actions:\n1.Close the program\n2.Print the current user's id\n3.Print the current directory's id\n";

    while(1 == 1) {
        syscall(SYS_write, 0, menu, slen(menu));
        syscall(SYS_write, 0, "Your selection: ", slen("Your selection: "));
        syscall(SYS_read, 1, selection, slen(selection));       //might be a problem
        selection[1] = '\0';
        index = selection[0] - '0' - 1;

        if(index > 2)
                syscall(SYS_write, 0, "Invalid input\n", slen("Invalid input\n"));
        else 
            arrFuncs[index].func();
    }
    return(0);
}


void exitProgram() {
    syscall(SYS_write, 0, "The program will close\n", slen("The program will close\n"));
    syscall(SYS_exit);
}

void printID() {        //problem
    char* uid = __itoa(syscall(SYS_getuid));
    syscall(SYS_write, 0, uid, slen(uid));
    syscall(SYS_write, 0, "\n", slen("\n"));
}

void currDir() {        //????  
    char* buf = __itoa(syscall(SYS_getcwd));
    syscall(SYS_write, 0, buf, slen(buf));
    syscall(SYS_write, 0, "\n", slen("\n"));
}
user3554255
  • 41
  • 2
  • 8

1 Answers1

1

You're passing the wrong number of arguments to some of these system calls. In particular:


syscall(SYS_exit);

_exit() takes one argument: the exit code.


char* buf = __itoa(syscall(SYS_getcwd));

getcwd() takes two arguments: a pointer to a buffer to write the string to, and the length of that buffer. In practice, this probably looks something like:

char pathbuf[PATH_MAX];
syscall(SYS_getcwd, pathbuf, sizeof(pathbuf));

If you don't have the header which defines PATH_MAX, define it yourself. 4096 is an appropriate value.

Note that getcwd() writes a string into the buffer passed to it — it does not return a numeric identifier.


As an aside, you may want to save yourself some time by implementing a wrapper to write a string, e.g.

void putstring(const char *str) {
    syscall(SYS_write, 0, str, slen(str));
}

since you seem to be doing that a lot.

  • your corrections helped the cwd function, but now it prints "25", and im pretty sure its wrong. Also, i still get the error after the second iteration, it prints the menu for the third time, acts as if it got an input, and then says Segmentation fault (core dumped) any idea why this happens? – user3554255 Nov 07 '14 at 21:06
  • `getcwd()` returns a string, not a number. –  Nov 07 '14 at 21:12
  • Im aware of that. But still - when i dont put itoa on the sys_cwd, i get a warning saying "initialization makes pointer from integer without a cast [enabled by default] char* path = syscall(SYS_getcwd, pathbuf, sizeof(pathbuf)); – user3554255 Nov 07 '14 at 21:15
  • also, when i try to run it without the itoa and ignore the warning, i get segmentation fault core dumped on the first go of option 3 – user3554255 Nov 07 '14 at 21:18
  • `syscall()` returns an `int` which signifies whether or not the system call executed successfully, or with an error. There's just no point trying to stuff it into a `char *`, and hoping it'll magically become a string containing the current working directory. – Crowman Nov 07 '14 at 21:31