What is causing this command line error? - objective-c

I am trying to programatically call the "top" command. The following is the code used:
char buffer [128];
char* threadsPointer;
char* procPointer;
NSString* numberOfThreadsString;
NSString* numberOfProcString;
FILE* output = popen("/usr/bin/top", "r");
while (fgets(buffer, sizeof(buffer), output) != NULL)
{
if ((procPointer = strstr(buffer, "Processes:")) != NULL)
{
procPointer += strlen("Proceses: ");
strcpy(buffer, procPointer);
numberOfProcString = [NSString stringWithUTF8String: buffer];
}
if ((threadsPointer = strstr(buffer, "sleeping,")) != NULL)
{
threadsPointer += strlen("sleeping, ");
strcpy(buffer, threadsPointer);
numberOfThreadsString = [NSString stringWithUTF8String: buffer];
}
}
NSLog(#"Proc: %#\nThreads: %#\n\n\n", numberOfProcString, numberOfThreadsString);
Instead of giving valid output, I keep getting the error: "Error opening terminal: unknown". I commended out the whole piece of code to identify the problem, and realized that its the line: FILE* output = popen ("/usr/bin/top", "r"); that is causing the error.
Does anyone have an idea of what I am doing wrong? Note I am on Mountain Lion OS X building an app for OSX not iOS.

top on MacOSX requires that its standard output or standard error be connected to a valid terminal to run. When you invoke it without a terminal (or a $TERM environment variable set to a valid terminal name, like "vt100"), it gives you that error: Error opening terminal: unknown.
You really shouldn't be using top for this, since it's an interactive program that requires a terminal. You should just be using ps.

you can try "top -l 1".
"-l 1" mean 1 sample, I think it should run top in non-interactive mode, print the result and exit.
On linux the command is "top -n 1" ("-n 1" mean run only 1 iteration, which should be equivalent to "top -l 1" on mac osx).

If you want specific information or all the details you should use "/proc" filesystem.
You can readdir() and fopen() all the files in /proc which contains currently running processes and get a lot of information, like for example what files are open by some process, or what ports is the process listening on.
'top' command opens a terminal and waits for user input. You won't be able to use it in a an automated script

Related

Colon functions and $ variables in c++?

I'm still a bit new to c++ and I'm having trouble understanding what this piece of code is doing:
#include <net/sock.h>
BEGIN
{
printf("%-8s %-6s %-16s %-2s %-16s %-5s\n", "TIME", "PID", "COMM",
"IP", "RADDR", "RPORT");
}
kprobe:ip4_datagram_connect,
kprobe:ip6_datagram_connect
{
$sk = (struct sock *)arg0;
$sa = (struct sockaddr *)arg1;
if (($sa->sa_family == AF_INET || $sa->sa_family == AF_INET6) &&
$sk->sk_protocol == IPPROTO_UDP) {
time("%H:%M:%S ");
if ($sa->sa_family == AF_INET) {
$s = (struct sockaddr_in *)arg1;
$port = ($s->sin_port >> 8) |
(($s->sin_port << 8) & 0xff00);
printf("%-6d %-16s 4 %-16s %-5d\n", pid, comm,
ntop(AF_INET, $s->sin_addr.s_addr), $port);
} else {
$s6 = (struct sockaddr_in6 *)arg1;
$port = ($s6->sin6_port >> 8) |
(($s6->sin6_port << 8) & 0xff00);
printf("%-6d %-16s 6 %-16s %-5d\n", pid, comm,
ntop(AF_INET6, $s6->sin6_addr.in6_u.u6_addr8),
$port);
}
}
}
I think the "BEGIN" portion of this is defining a macro, but I'm not fully sure. What I'm really confused about is the
kprobe:ip4_datagram_connect,
kprobe:ip6_datagram_connect
{
What is this doing? It seems like a function declaration, but what does the single colon mean in this context? Is this some sort initialization list but for functions? Is this setting both ip4 and ip6 to that function?
Also, do the dollar sign variable names have any sort of significance? or are they just a valid way of declaring variables?
This is the code for udpconnect.bt from bcc tools. I'm try to convert it to python.
As mentioned in the comments, this is a script for bpftrace. You probably want to look at the reference guide for this tool.
The BEGIN block is run at the start of your program (just like with awk scripts, if you are familiar with it). In this case it is used to print the header row for an array to the console output.
Then the block:
kprobe:ip4_datagram_connect,
kprobe:ip6_datagram_connect
{
... defines instructions that will be translated to an eBPF program (with an intermediary step as LLVM intermediate representation), and attached to one or several hooks in the Linux kernel. In the current case, the kprobe:... define the hooks: The program will run as a kprobe function for the functions ip4_datagram_connect and its IPv6 counterpart in the kernel. In other words, it will run each time the kernel enters those functions.
On a quick look, I think the program is supposed to print, each time a UDP flow starts, the time, PID and name of the process opening the socket, the IP address, remote address and remote port. The first if checks that the packet is (IPv4 or IPv6) and UDP, the if/else below splits the two cases IPv4/IPv6.

Detect if a Tcl script is run in a background process

I'm looking for a preferably cross-platform way to detect from within a Tcl script if the interpreter is running in a foreground or in a background process.
I've seen how to do it via ps (or /proc/$$/stat on Linux); is there a better way or do I have to hack something around that approach? I already have a utility library written in C so exposing the lowlevel API that ps also uses so I don't have to parse process output (or special file content) would be fine.
There's no truly cross-platform notion of foreground, but the main platforms do have ways of doing it according to the notion they have of foreground.
Linux, macOS, and other Unix:
For determining if a process is foreground or not, you need to check if its process group ID is the terminal's controlling process group ID. For Tcl, you'd be looking to surface the getpgrp() and tcgetpgrp() system calls (both POSIX). Tcl has no built-in exposure of either, so you're talking either a compiled extension (may I recommend Critcl for this?) or calling an external program like ps. Fortunately, if you use the latter (a reasonable option if this is just an occasional operation) you can typically condition the output so that you get just the information you want and need to do next to no parsing.
# Tested on macOS, but may work on other platforms
proc isForeground {{pid 0}} {
try {
lassign [exec ps -p [expr {$pid ? $pid : [pid]}] -o "pgid=,tpgid="] pgid tpgid
} on error {} {
return -code error "no such process"
}
# If tpgid is zero, the process is a daemon of some kind
expr {$pgid == $tpgid && $tpgid != 0}
}
Windows
There's code to do it, and the required calls are supported by the TWAPI extension so you don't need to make your own. (WARNING! I've not tested this!)
package require twapi_ui
proc isForeground {{pid 0}} {
set forground_pid [get_window_thread [get_foreground_window]]
return [expr {($pid ? $pid : [pid]) == $foreground_pid}]
}
Thanks to Donal I came up with the implementation below that should work on all POSIX Unix variants:
/*
processIsForeground
synopsis: processIsForeground
Returns true if the process is running in the foreground or false
if in the background.
*/
int IsProcessForegroundCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
/* Check the arg count */
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, NULL);
return TCL_ERROR;
}
int fd;
errno = 0;
if ((fd = open("/dev/tty", O_RDONLY)) != -1) {
const pid_t pgrp = getpgrp();
const pid_t tcpgrp = tcgetpgrp(fd);
if (pgrp != -1 && tcpgrp != -1) {
Tcl_SetObjResult(interp, Tcl_NewBooleanObj(pgrp == tcpgrp));
close(fd);
return TCL_OK;
}
close(fd);
}
Tcl_SetErrno(errno);
Tcl_ResetResult(interp);
Tcl_AppendResult(interp, "processIsForeground: ", (char *)Tcl_PosixError(interp), NULL);
return TCL_ERROR;
}
int Pextlib_Init(Tcl_Interp *interp)
{
if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
return TCL_ERROR;
// SNIP
Tcl_CreateObjCommand(interp, "processIsForeground", IsProcessForegroundCmd, NULL, NULL);
if (Tcl_PkgProvide(interp, "Pextlib", "1.0") != TCL_OK)
return TCL_ERROR;
return TCL_OK;
}

How can I read from stdin instead of the command line?

FILE * file;
file = fopen(argv[2] , "r");
float val;
if (file) {
while (fscanf(file, "%s", str)!=EOF){
val = atof(str);
root = insert(root, val);
}
fclose(file);
}else{
exit(1);
}
That is a section of the code I have right now. Im trying to change it so that it will read from stdin instead of from the command line. For example running the program would be "./a.out x < file.txt" instead of "./a.out x file.txt".
Instead of using fopen() to open a file, use the fdopen() call to obtain a FILE * that sits on top of the file descriptor for standard input. That's file descriptor 0, or you can use the literal STDIN_FILENO from the unistd.h header if you want to make your program easier for someone to read. It will look like this:
file = fdopen(STDIN_FILENO, "r");
The rest of your program stays the same.

objective-c get list of processes, their paths AND arguments

Getting the list of processes and their path is quite easy;
int numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0);
pid_t pids[1024];
bzero(pids, 1024);
proc_listpids(PROC_ALL_PIDS, 0, pids, sizeof(pids));
for (int i = 0; i < numberOfProcesses; ++i) {
if (pids[i] == 0) { continue; }
char pathBuffer[PROC_PIDPATHINFO_MAXSIZE];
bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE);
proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer));
char arguments[KERN_PROCARGS2];
if (strlen(pathBuffer) > 0) {
printf("path: %s\n", pathBuffer);
}
}
However, I would also like to get any arguments that were used to launch these processes. I can't seem to find how to do this. Any pointers?
A pointer? The ps command lists them and its source is available as part of Apple's open source: ps folder.
./build64.sh # Build cmdline app for 64-bit Intel Mac
# Enumerate all processes running and print the argvs
./xproc --pid-enum | xargs -L1 ./xproc --cmd-from-pid
Calling the functions directly will be faster than running a new task.
Source code can be built for Windows, MacOS, Linux, and FreeBSD.
Feel free to borrow any portion of code you may need from it:
https://github.com/time-killer-games/xproc

Dead-simple example of an interactive command-line application in c or objective-c?

I'd like to write a simple interactive command line program in C or Objective-C. Something that prompts the user for input and then acts on that input, then prompts the user for more input. I've googled "interactive command line application" and several variations on that theme but am not coming up with any simple examples of what I'm looking for.
This seems like an absolutely elementary, fundamental programming example, like a step after "hello world". Can anyone point me to an example of such a program, or tell me what I should be searching for?
Xcode 4 - Foundation Command Line Tool
File > New > New Project
Mac OS X > Application > Command Line Tool
Choose Name
Type > Foundation
Next
Create
Open the main.m file
Paste the code below
Hit run
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
#autoreleasepool {
int inputOne;
NSLog (#"Enter number: ");
scanf("%i", &inputOne);
int inputTwo;
NSLog (#"Enter another number: ");
scanf("%i", &inputTwo);
NSLog (#"%i + %i = %d", inputOne, inputTwo, inputOne + inputTwo);
}
return 0;
}
Note: In case the command line interface does not appear, hit the second button:
Now you can interact with the command line tool.
There are many ways you can get input into a program. One of the most basic is scanf.
#include <stdio.h>
int main(void) {
int age;
printf("Enter your age: ");
fflush(stdout);
if (scanf("%d", &age) == 1) {
if (age < 18) printf("baby\n");
else if (age < 65) printf("adult\n");
else printf("old\n");
} else {
printf("Invalid input\n");
}
return 0;
}
Create a new file in Xcode
select the command line tool, under the mac at the right side tab.
As for type, select foundation for objective-c, and c for c.
you now get a stubbed-out project, with some stuff already made. You type your code where is has the first "NSLog" statement. Simply remove that statement, and type in your own.
Notice: NSLog is an objective-C form of getting stuff printed in the console, and for each NSLog call it will appear on a new line.
Printf is the c way of doing the same thing, but in order to print to a new line you must use \n - as a convention, it is normal that printf calls always ends with a \n
Try it out for yourself, take this into a command line project (at the place where it already has an NSLog statement) - replace it with 2 NSLog calls and 2 printf functions.