#include #include #include #include #include #include // Allows Ground to access the POSIX standard library. // Read more here: https://en.wikipedia.org/wiki/Unistd.h // Misc functions GroundValue groundCrypt(GroundScope* scope, List args) { char* hash = crypt(args.values[0].data.stringVal, args.values[1].data.stringVal); if (hash == NULL) { ERROR(strerror(errno), "CryptError"); } return groundCreateValue(STRING, hash); } GroundValue groundGetHostId(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) gethostid()); } GroundValue groundSetHostId(GroundScope* scope, List args) { int result = sethostid((long) args.values[0].data.intVal); if (result < 0) { ERROR(strerror(errno), "SetHostIdError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundGetHostname(GroundScope* scope, List args) { char* buf = malloc(256); if (buf == NULL) { ERROR("Couldn't allocate memory to store hostname", "GetHostnameError"); } int result = gethostname(buf, 255); if (result < 0) { ERROR(strerror(errno), "GetHostnameError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetHostname(GroundScope* scope, List args) { int result = sethostname(args.values[0].data.stringVal, strlen(args.values[0].data.stringVal)); if (result < 0) { ERROR(strerror(errno), "SetHostnameError"); } return groundCreateValue(INT, (int64_t) result); } // Signals GroundValue groundAlarm(GroundScope* scope, List args) { unsigned result = alarm((unsigned) args.values[0].data.intVal); return groundCreateValue(INT, (int64_t) result); } GroundValue groundPause(GroundScope* scope, List args) { int result = pause(); ERROR(strerror(errno), "PauseError"); } // Filesystem GroundValue groundAccess(GroundScope* scope, List args) { int result = access(args.values[0].data.stringVal, (int) args.values[1].data.intVal); return groundCreateValue(INT, (int64_t) result); } GroundValue groundChdir(GroundScope* scope, List args) { int result = chdir(args.values[0].data.stringVal); if (result < 0) { ERROR(strerror(errno), "ChdirError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundChown(GroundScope* scope, List args) { int result = chown(args.values[0].data.stringVal, (uid_t) args.values[1].data.intVal, (gid_t) args.values[2].data.intVal); if (result < 0) { ERROR(strerror(errno), "ChownError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundLink(GroundScope* scope, List args) { int result = link(args.values[0].data.stringVal, args.values[1].data.stringVal); if (result < 1) { ERROR(strerror(errno), "LinkError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundRmdir(GroundScope* scope, List args) { int result = rmdir(args.values[0].data.stringVal); if (result < 1) { ERROR(strerror(errno), "RmdirError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSymlink(GroundScope* scope, List args) { int result = symlink(args.values[0].data.stringVal, args.values[1].data.stringVal); if (result < 1) { ERROR(strerror(errno), "SymlinkError"); } return groundCreateValue(INT, (int64_t) result); } // Process GroundValue groundExit(GroundScope* scope, List args) { _exit(args.values[0].data.intVal); ERROR("Couldn't exit (huh?)", "ExitError"); } GroundValue groundExecv(GroundScope* scope, List args) { char** argv = malloc(sizeof(char*) * args.values[1].data.listVal.size + 1); if (argv == NULL) { ERROR("Couldn't allocate memory for execv list", "ExecvError"); } for (size_t i = 0; i < args.values[1].data.listVal.size; i++) { if (args.values[1].data.listVal.values[i].type != STRING) { ERROR("Expecting all arguments in list to be of String type", "ExecvError"); } argv[i] = args.values[1].data.listVal.values[i].data.stringVal; } argv[args.values[1].data.listVal.size] = NULL; int result = execv(args.values[0].data.stringVal, argv); ERROR(strerror(errno), "ExecvError"); } GroundValue groundExecvp(GroundScope* scope, List args) { char** argv = malloc(sizeof(char*) * args.values[1].data.listVal.size + 1); if (argv == NULL) { ERROR("Couldn't allocate memory for execv list", "ExecvpError"); } for (size_t i = 0; i < args.values[1].data.listVal.size; i++) { if (args.values[1].data.listVal.values[i].type != STRING) { ERROR("Expecting all arguments in list to be of String type", "ExecvpError"); } argv[i] = args.values[1].data.listVal.values[i].data.stringVal; } argv[args.values[1].data.listVal.size] = NULL; int result = execvp(args.values[0].data.stringVal, argv); ERROR(strerror(errno), "ExecvpError"); } GroundValue groundFork(GroundScope* scope, List args) { pid_t id = fork(); if (id < 0) { ERROR(strerror(errno), "ForkError"); } return groundCreateValue(INT, id); } GroundValue groundGetPid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) getpid()); } GroundValue groundGetPPid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) getppid()); } GroundValue groundGetSid(GroundScope* scope, List args) { pid_t result = getsid((pid_t) args.values[0].data.intVal); if (result < 0) { ERROR(strerror(errno), "GetSidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundNice(GroundScope* scope, List args) { int result = nice((int) args.values[0].data.intVal); if (result < 0) { ERROR(strerror(errno), "NiceError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetSid(GroundScope* scope, List args) { pid_t result = setsid(); if (result < 0) { ERROR(strerror(errno), "SetSidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSleep(GroundScope* scope, List args) { unsigned int result = sleep((unsigned int) args.values[0].data.intVal); return groundCreateValue(INT, (int64_t) result); } // User/Group GroundValue groundGetGid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) getgid()); } GroundValue groundGetEGid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) getegid()); } GroundValue groundGetUid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) getuid()); } GroundValue groundGetEUid(GroundScope* scope, List args) { return groundCreateValue(INT, (int64_t) geteuid()); } GroundValue groundGetLogin(GroundScope* scope, List args) { char* login = getlogin(); if (login == NULL) { ERROR(strerror(errno), "GetLoginError"); } return groundCreateValue(STRING, login); } GroundValue groundSetEUid(GroundScope* scope, List args) { int result = seteuid((uid_t) args.values[0].data.intVal); if (result < -1) { ERROR(strerror(errno), "SetEUidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetEGid(GroundScope* scope, List args) { int result = setegid((uid_t) args.values[0].data.intVal); if (result < -1) { ERROR(strerror(errno), "SetEGidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetREUid(GroundScope* scope, List args) { int result = setreuid((uid_t) args.values[0].data.intVal, (uid_t) args.values[1].data.intVal); if (result < -1) { ERROR(strerror(errno), "SetREUidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetREGid(GroundScope* scope, List args) { int result = setregid((gid_t) args.values[0].data.intVal, (gid_t) args.values[1].data.intVal); if (result < -1) { ERROR(strerror(errno), "SetREGidError"); } return groundCreateValue(INT, (int64_t) result); } GroundValue groundSetUid(GroundScope* scope, List args) { int result = setuid((uid_t) args.values[0].data.intVal); if (result < -1) { ERROR(strerror(errno), "SetUidError"); } return groundCreateValue(INT, (int64_t) result); } void ground_init(GroundScope* scope) { // Misc groundAddNativeFunction(scope, "unistd_Crypt", groundCrypt, STRING, 2, STRING, "key", STRING, "value"); groundAddNativeFunction(scope, "unistd_GetHostId", groundGetHostId, INT, 0); groundAddNativeFunction(scope, "unistd_SetHostId", groundSetHostId, INT, 1, INT, "hostid"); groundAddNativeFunction(scope, "unistd_GetHostname", groundGetHostname, STRING, 0); groundAddNativeFunction(scope, "unistd_SetHostname", groundSetHostname, INT, 1, STRING, "name"); // Signals groundAddNativeFunction(scope, "unistd_Alarm", groundAlarm, INT, 1, INT, "seconds"); groundAddNativeFunction(scope, "unistd_Pause", groundPause, INT, 0); // Filesystem groundAddValueToScope(scope, "unistd_F_OK", groundCreateValue(INT, F_OK)); groundAddValueToScope(scope, "unistd_R_OK", groundCreateValue(INT, R_OK)); groundAddValueToScope(scope, "unistd_W_OK", groundCreateValue(INT, W_OK)); groundAddValueToScope(scope, "unistd_X_OK", groundCreateValue(INT, X_OK)); groundAddNativeFunction(scope, "unistd_Access", groundAccess, INT, 2, STRING, "path", INT, "mode"); groundAddNativeFunction(scope, "unistd_Chdir", groundAccess, INT, 1, STRING, "path"); groundAddNativeFunction(scope, "unistd_Chown", groundChown, INT, 3, STRING, "path", INT, "owner", INT, "group"); groundAddNativeFunction(scope, "unistd_Link", groundLink, INT, 2, STRING, "oldpath", STRING, "newpath"); groundAddNativeFunction(scope, "unistd_Rmdir", groundRmdir, INT, 1, STRING, "path"); groundAddNativeFunction(scope, "unistd_Symlink", groundSymlink, INT, 2, STRING, "target", STRING, "linkpath"); // Process groundAddNativeFunction(scope, "unistd_Exit", groundExit, INT, 1, INT, "status"); groundAddNativeFunction(scope, "unistd_Execv", groundExecv, INT, 2, STRING, "path", LIST, "argv"); groundAddNativeFunction(scope, "unistd_Execvp", groundExecvp, INT, 2, STRING, "path", LIST, "argv"); groundAddNativeFunction(scope, "unistd_Fork", groundFork, INT, 0); groundAddNativeFunction(scope, "unistd_GetPid", groundGetPid, INT, 0); groundAddNativeFunction(scope, "unistd_GetPPid", groundGetPPid, INT, 0); groundAddNativeFunction(scope, "unistd_GetSid", groundGetSid, INT, 1, INT, "pid"); groundAddNativeFunction(scope, "unistd_Nice", groundNice, INT, 1, INT, "inc"); groundAddNativeFunction(scope, "unistd_SetSid", groundSetSid, INT, 0); groundAddNativeFunction(scope, "unistd_Sleep", groundSleep, INT, 1, INT, "seconds"); // User/Group groundAddNativeFunction(scope, "unistd_GetGid", groundGetGid, INT, 0); groundAddNativeFunction(scope, "unistd_GetEGid", groundGetEGid, INT, 0); groundAddNativeFunction(scope, "unistd_GetUid", groundGetUid, INT, 0); groundAddNativeFunction(scope, "unistd_GetEUid", groundGetEUid, INT, 0); groundAddNativeFunction(scope, "unistd_GetLogin", groundGetLogin, STRING, 0); groundAddNativeFunction(scope, "unistd_SetEUid", groundSetEUid, INT, 1, INT, "euid"); groundAddNativeFunction(scope, "unistd_SetEGid", groundSetEGid, INT, 1, INT, "egid"); groundAddNativeFunction(scope, "unistd_SetREUid", groundSetEGid, INT, 1, INT, "ruid", INT, "euid"); groundAddNativeFunction(scope, "unistd_SetREGid", groundSetEGid, INT, 1, INT, "rgid", INT, "egid"); }