-1

I would like to make a program that can block some programs from being opened, or stop them after they've started. I can only code in C and would also like to add a GUI, so I cannot use bash and kill. Is there a way to close another program from C?

I want to basically create a "time-delay" so I cannot start minecraft during the school day.

I would like to keep the code as efficient as possible, and have not been able to find any tools like a service that would efficiently close apps or block them from starting in the first place.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 2
    [kill](https://man7.org/linux/man-pages/man2/kill.2.html) is available as a C API. – kaylum Dec 01 '20 at 03:47
  • 1
    Why does having a GUI prevent you from using bash and kill? – John Kugelman Dec 01 '20 at 03:50
  • I want to stop another program, not a child process. – valkyrie_pilot Dec 01 '20 at 03:53
  • I can't find a question about killing in general, but the answer is the same. Ignore the "by the parent process" part. The other questions I'm seeing are about killing from shell scripts, or about more advanced killing (e.g. an entire tree of processes). – John Kugelman Dec 01 '20 at 03:54
  • 1
    Thanks, is there an equivalent so I can use the name instead of the PID? – valkyrie_pilot Dec 01 '20 at 03:54
  • Sharing your research helps everyone. Tell us what you've tried and why it didn’t meet your needs. This demonstrates that you’ve taken the time to try to help yourself, it saves us from reiterating obvious answers, and most of all it helps you get a more specific and relevant answer. See also: [ask] – John Kugelman Dec 01 '20 at 03:57
  • I have looked in to several things that would allow me to create a service, however the serveice denies permission for even the root user. – valkyrie_pilot Dec 01 '20 at 03:59
  • 1
    Please [edit] your question and share what you've tried. – John Kugelman Dec 01 '20 at 04:00
  • 1
    I also want to ensure the program induces the least drag on my PC, and so for all of the other things I want to use C. – valkyrie_pilot Dec 01 '20 at 04:00
  • 1
    You really don't need to write code for this sort of thing. You could for example only allow a certain login access to the minecraft app using Linux permissions. Then you can use techniques such as [these](https://unix.stackexchange.com/questions/150705/restrict-the-times-a-user-is-allowed-to-log-in) to prevent login for that account during certain times. – kaylum Dec 01 '20 at 04:06
  • FYI there's no need to use C. No language, whether that's Bash or Python or anything else, will have any noticeable CPU load. Unless you just want to sharpen your C skills it's not buying you anything except unnecessary complexity. It's the wrong tool for the job, IMO. – John Kugelman Dec 01 '20 at 04:06
  • I will try in bash, however I do still need to be able to use the computer, just block specific applications. – valkyrie_pilot Dec 01 '20 at 04:07
  • @Joshua One of the answers [recommends `pkill -f`](https://stackoverflow.com/a/27820938/68587), which is perfect for the job. – John Kugelman Dec 01 '20 at 04:08

1 Answers1

0

So what we want to do is locate the process and kill() it. It's not so hard. It's just very long because the executable isn't minecraft, it's java, so we look for the .jar file.

#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>

void kill_minecraft()
{
    char buf[8192];
    DIR *dir = opendir("/proc");
    struct dirent *dirent;
    while ((dirent = readdir(dir)))
    {
        pid_t pid = atol(dirent->d_name);
        if (pid > 0)
        {
            sprintf(buf, "/proc/%s/cmdline", dirent->d_name);
            FILE *in = fopen(buf, "r");
            if (in)
            {
                size_t nmem = fread(buf, 1, 8192, in);
                fclose(in);
                buf[8192] = 0;
                // Recognize minecraft's jar in the command line
                if (nmem > 0 && (char *ptr = (char*)memmem(buf, "minecraft/versions/", nmem)))
                {
                     char *p1 = (char*)strstr(ptr, ":");
                     char *p2 = (char*)strstr(ptr, ".jar");
                     if (p2 && (!p1 || p1 > p2))
                     {
                         // Match! Goodbye!
                         kill(pid, 9);
                     }
                }
                fclose(in);
            }
        }
    }
    closedir(dir);
}

Whew. Let's break this down. This function iterates over all running processes and reads in its command line. Once having done so, it checks the command line for minecraft's pattern; that is having a command line argument of minecraft/versions/something/something.jar. In java, the jar arguments are glommed together separated by : characters, so it handles that. On getting a match, it calls kill.

Scheduling this function is left as an exercise for the reader. See time() and sleep() functions. As for running it, the lazy way is to stick a call to it into /etc/rc.local.

You can do this with pkill -f in a loop, but that regex is hard to write and I don't want to figure it out.

Joshua
  • 40,822
  • 8
  • 72
  • 132