C wrapper to remove users on command "ps" - c

I have one question maybe someone here can help me. If i do "ps aux --sort user" on linux console I have one list of users and their processes runing on the machine. My question is how do I remove the users name and print that list like this in a C program:
for example:
(…)
--------------------------------------------------------------------------
user: APACHE
--------------------------------------------------------------------------
3169 0.0 1.2 39752 12352 ? S 04:10 0:00 /usr/sbin/httpd
--------------------------------------------------------------------------
user: VASCO
--------------------------------------------------------------------------
23030 0.0 0.1 4648 1536 pts/1 Ss 20:02 0:00 –bash
(…)
I print the user name then I print his processes... any ideas ?
thx

ps aux --sort user | perl -npe 's/^(\w+)//g; if ($user ne $1) {$user=$1; print "user: " . uc($user) . "\n";}'

You have a number of options depending on how much of it you want to do in C.
The simplest is to use system() to run a shell command (such as the one I posted earlier) to do the whole lot. system() will actually spawn a shell, so things like redirection will all work just as they do from the command line.
If you want to avoid using system() you could do it yourself, spawning two processes and linking them together. Look up pipe() and dup2(). Probably a waste of time.
You can run the ps program and parse its output in C. Again pipe() and dup2() are relevant. For the actual parsing, I'd just do it using the normal C string handling routines, as it's really quite straightforward. Obviously you could use a regex library instead but I think in this case it would result in more complicated code than without it.
Of course, you could do the whole lot in C by looking at files in /proc.

Not really an answer to your question, but user names are case-sensitive in unix, so capitalising them all probably isn't a good idea. If you want to make them stand out visually then "USER: apache" would be better.
Apart from that bmdhacks' answer is good (but not quite right). You could do something similar in awk, but it would be rather more complicated.

This should work:
ps haux --sort user | perl -npe 's/^(\S+)\s+//; if ($user ne $1) {$user=$1; print "user: " . uc($user) . "\n";}'
Based on bmdhacks's answer, but with the following fixes:
a) it counts any non-whitespace as part of the user name,
b) it deletes any whitespace after the user name, like your example output had, otherwise things wouldn't line up
c) I had to remove the g to get it to work. I think because with the g it can potentially match lots of times, so perl doesn't set $1 as it could be ambiguous.
d) Added h to the ps command so that it doesn't output a header.

that's command line for linux to make what i said... but that's not what i want... i want to make that in some C program... I hav to wrote C program that makes that... so i use fork() to create one process that executes ps aux --sort user... and then i want with another process to control the print of the processes and users... sry, if i explain my problem rong.
The command that i want to run is like this: ps aux --sort user | sort_by_user... this option sort_by_user doesn.t exists.. Make some process in C to run that command is simple with the commands fork() and execlp(), but create some option to that command in C i don´t hav any ideas.

Use popen and manipulate the redirected stdout string in your C program

I solved my problem by redirecting the stdout put and editing it.

Related

Estimating the execution time of code on local linux system

I spend most of my time solving problems on Topcoder/SPOJ. So definitely I thought of performance (execution time) of my code on my system before submitting the code.
So, on searching I found time command in linux. But the problem is that it also includes the time for inputting the values for several test cases, in addition to processing time. So I thought of making an input file and sending that content to my code.
Something like
cat input.txt > ./myprogram
But this doesn't work. (I am not good at linux pipelining). Can anyone point out the mistake, or a better approach to judge my code execution time?
EDIT
All of my programs read from stdin
You need this:
./myprogram < input.txt
Or if you insist on the Useless Use of Cat:
cat input.txt | ./myprogram
You can put time in front of ./myprogram in either case.
You might want to look at xargs.
Something along the lines of
cat input.txt | xargs ./myprogram
You can add below code in your script for
assign the file descriptor to file for input and output fd # 3 is
Input file
exec 3< input.txt
Use read command in while loop to read the file line by line
while read -u 3 -r a
do

Another Linux command output (Piped) as input to my C program

I'm now working on a small C program in Linux. Let me explain you what I want to do with a sample Linux command below
ls | grep hello
The above command is executed in the below passion (Let me know if I've got this wrong)
ls command will be executed first
Output will be given to grep command which will again generate output by matching "hello"
Now I would like to write a C program which takes the piped output of one command as input. Means, In the similar passion of how "grep" program was able to get the input from ls command (in my example above).
Similar question has been asked by another user here, but for some reason this thread has been marked as "Not a valid question"
I initially thought we can get this as a command line argument to C program. But this is not the case.
If you pipe the output from one command into another, that output will be available on the receiving process's standard input (stdin).
You can access it using the usual scanf or fread functions. scanf and the like operate on stdin by default (in the same way that printf operates on stdout by default; in the absence of a pipe, stdin is attached to the terminal), and the C standard library provides a FILE *stdin for functions like fread that read from a FILE stream.
POSIX also provides a STDIN_FILENO macro in unistd.h, for functions that operate one file descriptors instead. This will essentially always be 0, but it's bad form to rely on that being the case.
If fact, ls and grep starts at the same time.
ls | grep hello means, use ls's standard output as grep's standard input. ls write results to standard output, grep waits and reads any output from standard input at once.
Still have doubts? Do an experiment. run
find / | grep usr
find / will list all files on the computer, it should take a lot of time.
If ls runs first, then OS gives the output to grep, we should wait a long time with blank screen until find finished and grep started. But, we can see the results at once, that's a proof for that.

Shell script vs C performance

I was wondering how bad would be the impact in the performance of a program migrated to shell script from C.
I have intensive I/O operations.
For example, in C, I have a loop reading from a filesystem file and writing into another one. I'm taking parts of each line without any consistent relation. I'm doing this using pointers. A really simple program.
In the Shell script, to move through a line, I'm using ${var:(char):(num_bytes)}. After I finish processing each line I just concatenate it to another file.
"$out" >> "$filename"
The program does something like:
while read line; do
out="$out${line:10:16}.${line:45:2}"
out="$out${line:106:61}"
out="$out${line:189:3}"
out="$out${line:215:15}"
...
echo "$out" >> "outFileName"
done < "$fileName"
The problem is, C takes like half a minute to process a 400MB file and the shell script takes 15 minutes.
I don't know if I'm doing something wrong or not using the right operator in the shell script.
Edit: I cannot use awk since there is not a pattern to process the line
I tried commenting the "echo $out" >> "$outFileName" but it doesn't gets much better. I think the problem is the ${line:106:61} operation. Any suggestions?
Thanks for your help.
I suspect, based on your description, that you're spawning off new processes in your shell script. If that's the case, then that's where your time is going. It takes a lot of OS resource to fork/exec a new process.
As donitor and Dietrich sugested, I did a little research about the AWK language and, again, as they said, it was a total success. here is a little example of the AWK program:
#!/bin/awk -f
{
option=substr($0, 5, 9);
if (option=="SOMETHING"){
type=substr($0, 80, 1)
if (type=="A"){
type="01";
}else if (type=="B"){
type="02";
}else if (type=="C"){
type="03";
}
print substr($0, 7, 3) substr($0, 49, 8) substr($0, 86, 8) type\
substr($0, 568, 30) >> ARGV[2]
}
}
And it works like a charm. It takes barely 1 minute to process a 500mb file
What's wrong with the C program? Is it broken? Too hard to maintain? Too inflexible? You are more of a Shell than a C expert?
If it ain't broke, don't fix it.
A look at Perl might be an option, too. Easier than C to modify and still speedy I/O; and it's much harder to create useless forks in Perl than in the shell.
If you told us exactly what the C program does, maybe there's a simple and faster-than-light solution with sed, grep, awk or other gizmos in the Unix tool box. In other words, tell us what you actually want to achieve, don't ask us to solve some random problem you ran into while pursuing what you think is a step towards your actual goal.
Alright, one problem with your shell script is the repeated open in echo "$out" >> "outFileName". Use this instead:
while read line; do
echo "${line:10:16}.${line:45:2}${line:106:61}${line:189:3}${line:215:15}..."
done < "$fileName" > "$outFileName"
As an alternative, simply use the cut utility (but note that it doesn't insert the dot after the first part):
cut -c 10-26,45-46,106-166 "$fileName" > "$outFileName"
You get the idea?

Get full path of executable of running process on AIX

This is most similar to Get full path of executable of running process on HPUX…, except for AIX.
The basic question is: how, on AIX, can I determine the full path to the current executable? Having to do this before doing anything else (e.g., chdir) is fine.
The most accurate answer I've found so far is to check the output from
svmon -P $$ -O format=nolimit,filename=on,filtertype=client
(where $$ has its shell meaning: current pid). That's not only heavy amounts of C, but svmon is also not very fast and can easily overwhelm the runtime of the rest of the application.
The next best answer seems to be to simply look at argv[0], and, if it has a slash in it, it's either a full path name (starts with a leading /) or a relative-to-current-dir name (does not start with a leading /). If it doesn't have a slash in it, it's relative to something in PATH.
And if, after this resolution, I end up with a symlink, then there's all the resolution of symlink(s) to deal with as well (hard links are probably beyond the scope of any solution). This solution looks like it's relatively cross-platform, but is also very heavy in the C code (should be faster than svmon). And I expect there are race-conditions and such to deal with.
Thanks,
Update: I'm looking for a solution to submit to the perl devs. And they're going to worry about an insecure PATH, especially in setuid/setgid scenarios. See perlsec. I think that we could be okay here, but if you combined setuid with faking argv[0], you could force perl to think it's somewhere else, and load the wrong modules. The "next best" answer above only really works when not in perl's taint-mode.
Why can't you use ps options as a base line? Granted, you'll still need to process the cmd value to see if has a leading '/' or not. Something like
ps -o pid,env,cwd,cmd | grep youAppName | awk -f programToRationalizePathName
I don't have access to AIX anymore, but I did work on it for 2 1/2 years and I know I've used this sort of feature. I didn't think it was slow, but I might have had different requirements than you do.
I get the impression you want a utility function, a 1-at-time call that returns the full path, but if you need an on-going process and are concerned about re-starting ps every 1 minute (for example), look at the AIX specific nmon utility. Not sure if it can generate output similar to the ps -o cmd but it can be set up to run as long as you want, as often as you want (down to 1 second intervals) and it is just one process, whose output can be redirected as needed. (Nmon is not part of the std install, but most organizations do install it, as it is IBM blessed (if not supported directly)).
Of course all of the 'not 100%' caveats apply from the similar questions mentioned by you and in the comments.
I hope this helps.
Use ps to get executable path address
ps -aef | grep app | awk '{print $8}'
above command gives your app executable path address

Shell redirection vs explicit file handling code

I am not a native english speaker so please excuse the awkward title of this question. I just not knew how to phrase it better.
I am on a FreeBSD box and I have a little filter tool written in C which reads a list of data via stdin and outputs a processed list via stdout. I invoke it somewhat like this: find . -type f | myfilter > /tmp/processed.txt.
Now I want to give my filter a little bit more exposure and publish it. Convention says that tools should allow something like this: find . -type f | myfilter -f - -o /tmp/processed.text
This would force me to write code that simply is not needed since the shell can do the job, therefore I tend to leave it out.
My question is: Do I miss some argument (other but convention) why the reading and writing of files should be done in my code an not delegated to shell redirection?
There's absolutely nothing wrong with this. Your filter would have an interface similar to, say, c++filt.
You might consider file handling if you wanted to automatically choose an output file based on the name of an input file or if you wanted to special handling for processing multiple files in a single command.
If you don't want to do any either of these then there's nothing wrong with being a simple filter. Anyone can provide a set of simple shell wrappers to provide a cmd infile outfile syntax if they wish.
That's a needlessly limiting interface. Accepting arguments from the command line is more flexible,
grep foo file | myfilter > /tmp/processed.text
and it doesn't preclude find from being used
find . -type f -exec myfilter {} + > /tmp/processed.text
Actually to have the same effect as shell redirection you can do this:
freopen( "filename" , "wb" , stdout );
and so if you have used printf throughout your code, outputs will be redirected to the file. So you don't need to modify any of the code you've written before and easily adapt to the convention.
It is nice to have as option run any command with filename argument. As in your example:
myfilter [-f ./infile] [-o ./outfile] #or
myfilter [-o outfile] [filename] #and (the best one)
myfilter [-f file] [-o file] #so, when the input and output are the same file - the filter should working correctly anyway
For the nice example check the sort command. Usually used as filer in pipes, but can do [-o output] and correctly handle the same input/output problem too...
And why it is good? For example, when want run the command from "C" by "fork/exec" and don't want start the shell for handling I/O. In this case is much easier (and faster) execve(.....) with arguments as start the cmd with a shell wrapper.

Resources