Can I interact with an open vt from a c program? - c

Assume I have a state machine started as root to run one and only one program in a given reserved vt. The first call I use something like:
execl("/usr/bin/openvt", "/usr/bin/openvt", "-c 12", "-f", "-- su auser /home/auser/sbin/ascript.sh", (char *) 0);
Is the only way to find the PID's of all of the children (The shell script, the calls, etc) to search ps aux for the PID's that are generated on that vt (tty12) and kill them, as fork only will hold the PID of the openvt command which pretty much dies after the new vt is open?
Or is there a slick way to send a SIGINT to a known vt (i.e., /dev/vcs12 dev/tty12)?

The -t tty option to ps may be what you are looking for...
kill -INT `ps -t vcs12 -o pid=`
or, in a sh/bash-specific way:
kill -INT $(ps -t vcs12 -o pid=)

Related

Linux Command to Show Stopped and Running processes?

I'm presently executing the following Linux command in one of my c programs to display processes that are running. Is there anyway I can modify it to show stopped processes and running ones?
char *const parmList[] = {"ps","-o","pid,ppid,time","-g","-r",groupProcessID,NULL};
execvp("/bin/ps", parmList);
jobs -s list stopped process by SIGTSTP (20), no SIGSTOP (19). The main difference is that SIGSTOP cannot be ignored. More info with help jobs.
You can SIGTSTP a process with ^Z or from other shell with kill -TSTP PROC_PID (or with pkill, see below), and then list them with jobs.
But what about listing PIDs who had received SIGSTOP? One way to get this is
ps -A -o stat,command,pid | grep '^T '
From man ps:
-A Select all processes. Identical to -e.
T stopped by job control signal
I found very useful this two to stop/cont for a while some process (usually the browser):
kill -STOP $(pgrep procName)
kill -CONT $(pgrep procName)
Or with pkill or killall:
pkill -STOP procName
pkill -CONT procName
Credit to #pablo-bianchi, he gave me the oompff (starting point) to find SIGSTOP'd and SIGTSTP'd processes, however his answers are not completely correct.
Pablo's command should use T rather than S
$ ps -e -o stat,command,pid | grep '^T '
T /bin/rm -r 2021-07-23_22-00 1277441
T pyt 999 1290977
$ ps -e -o stat,command,pid | grep '^S ' | wc -l
153
$
From man ps:
PROCESS STATE CODES
Here are the different values that the s, stat and state output specifiers (header "STAT"
or "S") will display to describe the state of a process:
D uninterruptible sleep (usually IO)
I Idle kernel thread
R running or runnable (on run queue)
S interruptible sleep (waiting for an event to complete)
T stopped by job control signal
t stopped by debugger during the tracing
W paging (not valid since the 2.6.xx kernel)
X dead (should never be seen)
Z defunct ("zombie") process, terminated but not reaped by its parent
WRT pgrep, it is a real grep, the argument is NOT a program name; rather, it is a regular expression applied to the first item in /proc//cmdline (usually the name from the executing commandline (or execve()).
Therefore if you are trying to kill pyt, you would accidentally also kill all the python programs that are running:
$ pgrep -a pyt
7228 python3 /home/wwalker/bin/i3-alt-tab-ww --debug
1290977 pyt 999
You need to "anchor" the regular expression:
$ pgrep -a '^pyt$'
1290977 pyt 999
ps -e lists all processes.
jobs list all processes currently stopped or in background.
So, you can run jobs command using execvp:
char *arg = {"jobs", NULL};
execvp(arg[0], arg);

Linux Command Outputs Terminated Processes

I'm working in C and using the following code to execute the ps linux command:
char *const parmList[] = {"ps","-o","pid","-g",processGroupID,NULL};
execvp(parmList[0], parmList);
The problem is that it prints all the processes from the group including ones that have been terminated. I need to make sure that the group processes that have NOT been terminated are the only ones shown. Is there a way to do this?
ps command display's the list of active processes of that current tty terminal.
ps - axrgo pid or ps -axro pid -g
ps has an simple process selection option.
-a -------> Select all processes except both session leaders and processes not associated with a terminal. i.e includes all active terminals
-e -------> Includes all processes.
-g -------> Select by session OR by effective group name.
-r -------> Restrict the selection to only running processes.
-x -------> option causes ps to list all processes owned by you (same EUID as ps), or to list all processes when used together with the a option.
Add the a x r options to get only running processes.

Get information on PID

I'm trying to get the information on a PID via c or terminal (ideally I would like to get it both ways, multiple methods)
I have a PID and would like to figure out the time it was claimed. By claimed i mean when a program started using it. Or if a PID was reused, when the latest program that is using it, started to use it.
In Linux what I do is lstat "/proc/PID_HERE/exe" or lstat "/proc/PID_HERE/cmdline" but I cant figure out how to do this on Mac OS.
Note: I changed from stat to lstat because a single exe is being used with command line arguments to open multiple instances. So each instance gets a new pid, so I want info on that specific instance, thus on Linux I have to use lstat. So any lstat equivalent to get pid info on mac os?
I think you mean this:
ps -p <PID> -o start=
10:22am
where you substitute in your PID. The start= selects the start time and also suppresses the header line. If you want the header, use
ps -p <PID> -o start
STARTED
10:22am
Alternatively, you can get the start time formated more fully like this:
ps -p <PID> -o lstart=
Fri 26 Sep 10:22:50 2014
By the way, if you want a list of the keywords (like start and lstart above) you can either wade through the manage, or more simply, just give an invalid keyword and it will tell you all the ones it likes :-)
ps -o %rubbish
ps: %rubbish: keyword not found
ps: no valid keywords; valid keywords:
%cpu %mem acflag acflg args blocked caught comm command cpu cputime etime f flags gid group ignored
inblk inblock jobc ktrace ktracep lim login logname lstart majflt minflt msgrcv msgsnd ni nice nivcsw
nsignals nsigs nswap nvcsw nwchan oublk oublock p_ru paddr pagein pcpu pending pgid pid pmem ppid pri
pstime putime re rgid rgroup rss ruid ruser sess sig sigmask sl start stat state stime svgid svuid
tdev time tpgid tsess tsiz tt tty ucomm uid upr user usrpri utime vsize vsz wchan wq wqb wql wqr xstat

Testing if my program is executed from the bash/ksh/csh command line

I would like to know if my program is executed from a command line, or executed through system() call, or from a script.
I initially thought about getting parent id (getppid()), and looking up /proc/#pppid directory checking either the exe link or contents of the cmdline file. If it is /bin/bash, or /bin/csh, or /bin/sh I would know that it runs from the command line.
The problem is that it is not true, because a standalone script would also tell me /bin/bash.
Even if it worked, it could have been very specific Linux version approach and could stop working in a future.
Is there a better way to do that?
Thank you for any advice or pointing out to some direction.
Most shells written since 1980 support job control, which is implemented by assigning a process group to each process in a pipeline of commands. The process group is set by setpgrp(), which sets the process's pgrp to its pid.
The pgrp is inherited across forks.
So, if your shell is a relatively modern one, a program started by an interactive shell will have getpid() == getpgrp(), and any additional processes forked by that process (say, if it's a shell script or if it calls system()) will have getpid() != getpgrp().
Here's a test program, and its behavior under bash (it will behave the same under ksh93 and tcsh as well):
pp.c
#include <unistd.h>
#include <stdio.h>
main()
{
printf("pid=%d pgrp=%d\n", (int)getpid(), (int)getpgrp());
}
$ ./pp
pid=3164 pgrp=3164
$ ./pp &
[1] 3165
$ pid=3165 pgrp=3165
In a pipeline, the leftmost command is the process group leader. (This isn't documented, but bash, ksh93, and tcsh all do it this way).
$ ls|./pp
pid=3179 pgrp=3178
$ ./pp|cat
pid=3180 pgrp=3180
A program called with system() will have the same pgrp as its parent:
pps.c
#include <stdlib.h>
main()
{
system("./pp");
}
$ ./pps
pid=4610 pgrp=4608
In a shell script, the shell is the process group leader, and any command invoked by it will inherit the pgrp:
pp.sh
#!/bin/sh
./pp
$ ./pp.sh
pid=4501 pgrp=4500
But if the shell script execs a program, the pid doesn't change, and the execed program will be a process group leader, so you probably don't want to do that.
ppe.sh
#!/bin/sh
exec ./pp
$ ./ppe.sh
pid=4504 pgrp=4504
In the unlikely case that the user turns off job control, every command is going to have the same pgrp as the shell:
$ set +m
$ ./pp
pid=4521 pgrp=2990
$ ./pp
pid=4522 pgrp=2990
You can intercept signal from PID when the script is done and check "kill" for it.
Not sure if that solves your problem but environment variables can give you a good hint. For example:
$ set | grep "^_="
_=
$ bash -c "set" | grep "^_="
_=/bin/bash
$ sh -c "set" | grep "^_="
_='/bin/sh'

How do get the process name & process id pid of newly created child process using fork?

I am using fork to create the child process. Now I want to know the name and process id of the child process using putty. Which command I need to use to get this information. I am trying with ps and pstree. how can give the name of the child process while creating new child process? Is it possible to get this information using any linux/unix command?
I want to know how much time child is active and when it is terminated. mean timing information of child process.
root#mx6q:~# ps aux|grep "childprogram"
ps: invalid option -- 'a'
BusyBox v1.20.2 (2014-03-13 11:47:37 CET) multi-call binary.
Usage: ps
Show list of processes
w Wide output
l Long output
T Show threads
root#mx6q:~#
root#mx6q:~# ps | grep "childprogram"
1407 root 1908 S grep childprogram
root#mx6q:~# ps | grep "childprogram"
1409 root 1908 S grep childprogram
root#mx6q:~# ps | grep "childprogram"
1411 root 1908 S grep childprogram
For Parent:
root#mx6q:~# readlink /proc/670/exe
.asoundrc .gvfs/
.bashrc adit-30-09-2014.vnclicense
.gstreamer-0.10/ enable_usb_dr_host_mode.sh
root#mx6q:~# readlink /proc/670/exe
but I am not able to find child pid inside /proc/? What does it mean?
You tagged this as C and mentioned that you are the actor forking the new process so you have all this information available to you in the parent process that forks the child but you need to alter your code to capture it.
You have the child's pid because it is returned in the parent by fork.
You (probably) have the child's name because under most circumstances you are the one who wrote the exec call. If not, with the child's pid you can readlink /proc/<pid>/exe.
If you need to know the child's stats while it is running you can call getrusage with the RUSAGE_CHILDREN option.
If you just want the child's stat's after it is completed you can wait on it with wait4
Try this:
$ ps xf
And analyze the output and make some filters with grep sed and/or awk.
I am not very much familiar with BusyBox as I know it is a tiny distro with limited functions.

Resources