If anyone could please help me out, that would be great :)
This seems to be a tough one. Starting from the process ID, I need to be able to grab:
How much CPU the process is taking up in %
How long the process has been using the CPU
This needs to be written in Cocoa/ Objective-C or C. It also needs to work on Tiger through Snow Leopard.
Thanks!
A crude way would be to spawn of a popen command and grab some output from ps.
Ie like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void get_process_info(int pid) {
char ps_cmd[256];
sprintf(ps_cmd, "ps -O %%cpu -p %d", pid); // see man page for ps
FILE *fp = popen(ps_cmd, "r");
if (fp) {
char line[4096];
while (line == fgets(line, 4096, fp)) {
if (atoi(line) == pid) {
char dummy[256];
char cpu[256];
char time[256];
// PID %CPU TT STAT TIME COMMAND
// 32324 0,0 s001 S+ 0:00.00 bc
sscanf(line, "%s %s %s %s %s", dummy, cpu, dummy, dummy, time);
printf("%s %s\n", cpu, time); // you will need to parse these strings
pclose(fp);
return;
}
}
pclose(fp);
}
}
int main() {
get_process_info(32324);
return 0;
}
Related
Note, I have looked at Using netcat/cat in a background shell script (How to avoid Stopped (tty input)? ), but it doesn't seem to apply to my case. I'm using the netcat (nc) that comes with busybox, and none of the workarounds I've found seem to work for me. Also, there is no -d option, nor are there any -q options.
I'm trying to use netcat to receive a file in a shell script, and this script is in a background process that apparently doesn't have a stdin. I have tried several different approaches, but none seem to work. Here's what I've tried:
nc -l -p 8888 > file returns the instant the remote sender connects, dropping the connection early.
nc -l -p 8888 < /dev/null > file does the same.
echo -n | nc -l -p 8888 > file does the same.
tail -f /dev/null | nc -l -p 8888 > file will receive the file, but it doesn't quit when the file transfer is finished.
I'm running out of ideas. Is this version of netcat fundamentally broken?
Well, it's been days, and nobody had an answer, so I had to roll my own. Below is the code, in case it's useful to anyone.
#include <signal.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/uio.h>
#include <unistd.h>
void bail(const char *s)
{
perror(s);
exit(-1);
}
int listen_socket;
struct sockaddr_in my_addr;
void setup_socket(int port)
{
int er;
listen_socket = socket(AF_INET, SOCK_STREAM, 0);
if (listen_socket < 0) bail("socket");
int on=1;
er = setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
if (er < 0) bail("setsockopt");
memset(&my_addr, 0, sizeof(my_addr));
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(port);
my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
er = bind(listen_socket, (struct sockaddr *)&my_addr,
(socklen_t)sizeof(struct sockaddr_in));
if (er < 0) bail("bind");
er = listen(listen_socket, 1);
if (er < 0) bail("listen");
}
int listen_wait()
{
socklen_t len = sizeof(struct sockaddr_in);
int s = accept(listen_socket, (struct sockaddr *)&my_addr, &len);
if (s < 0) bail("accept");
return s;
}
char buf[1024];
int main(int argc, char *argv[])
{
int port = 8888;
int sock;
int tryagain;
if (argc>1) {
port = atoi(argv[1]);
}
setup_socket(port);
sock = listen_wait();
do {
int i = read(sock, buf, 1024);
tryagain = (errno==EAGAIN);
if ((i<1) && (!tryagain)) {
shutdown(sock, 2);
close(sock);
return 0;
}
if (i>0) {
fwrite(buf, 1, i, stdout);
}
} while (1);
return 0;
}
This will do the trick
sleep 99999 | nc -l -p 8888 > file
I ran the following command in the Windows command prompt:
yacc -d calci.y
After successful execution it generates 2 files: calci.tab.c and calci.tab.h. But it should have generated y.tab.c and y.tab.h.
I am very new to lex and yacc, so I do not have an idea about the error.
Also, it gives me the following error when I try to run command:
cc lex.yy.c calci.tab.c -o out.exe:
error: calci.l:3:23: fatal error: y.tab.h: No such file or directory
compilation terminated.
Please give some suggestion.
yacc program:--->>
%{
#include <stdio.h>
int yylex(void);
void yyerror(char *);
%}
%token INTEGER
%%
program:
program expr '\n' { printf("%d\n", $2); }
|
;
expr:
INTEGER
| expr '+' expr { $$ = $1 + $3; }
| expr '-' expr { $$ = $1 - $3; }
;
%%
void yyerror(char *s) {
fprintf(stderr, "%s\n", s);
}
int main(void) {
yyparse();
return 0;
}
lex program:-->>>>
%{
#include "y.tab.h"
#include <stdlib.h>
void yyerror(char *);
%}
%%
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
[-+\n] { return *yytext; }
[ \t] ; /* skip whitespace */
. yyerror("Unknown character");
%%
int yywrap(void) {
return 1;
}
Just accept that bison will name its output files based on the name of its input file.
Creating files called y.tab.c and y.tab.h is the legacy behaviour of the original yacc tool; with current bison versions, you can achieve compatible behaviour by supplying the -y command-line option to bison. But I don't recommend doing that for new code; it will also change some details of the parser's behaviour in order to be legacy-compatible, and if you don't have legacy code those behaviours may not be desirable.
Basing the names of the bison-generated files on the input files makes it possible to have more than one bison source file in the same directory. If you don't want to use the name of the source file, you can specify an explicit output file name with the -o option (and the --defines option if you want the header file's name to have a different prefix than the source file).
All that means you need to change the name of the file being included into the lexer, so the line will become
#include "calci.tab.h"
(assuming you don't use the -o/--defines options.)
I've to do a project but I hit a issue.
I receive a string from a read but when I would see what data are in my buffer, it shows an "\n" at the end of the file. However I don't need it to use after to deal with a argument in my function.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
int main()
{
char buf[100];
read(1, buf, sizeof(buf));
printf("%s", &buf);
// If I write: "/tmp/", printf shows: "/tmp/\n"
DIR* drp = opendir(buf);
// Logically: no such file or directory
}
Thanks
The problem in how you read string from stdin. read function waits until you enter a newline or other EOF key. But it includes this last symbol in the result.
1) I think you better use scanf.
scanf("%s", buf);
2) Or you need to take care of the last symbol by yourself.
char buf[100];
char res[100];
int n = read(1, buf, sizeof(buf));
if(n > 0) {
memcpy(res, buf, n - 1);
} else {
printf("Error while reading\n");
}
I have recently tried using GNU Bison and Flex to write a interpreter. The text I want the interpreter to recognize is print "Hello" and I have tried the following:
flex file:
%{
#include <iostream>
using namespace std;
#define YY_DECL extern "C" int yylex()
#include "gbison.tab.h"
%}
%%
[ \t\n] ;
'\"' return QUOTE;
[a-zA-Z0-9]+ { yylval.sval = strdup(yytext); return STRING; }
%%
bison file:
%{
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
extern "C" int yylex();
extern "C" int yyparse();
extern "C" FILE* yyin;
void yyerror (const char* s);
%}
%union {
char* sval;
}
%token <sval> STRING
%token QUOTE
%%
str:
STRING QUOTE STRING QUOTE
{
if (strcmp($1, "print") == 0)
{
cout << $3 << flush;
}
if (strcmp($1, "println") == 0)
{
cout << $3 << endl;
}
}
;
%%
main(int argc, char* argv[])
{
FILE* input = fopen(argv[1], "r");
if (!input)
{
cout << "Bad input. Nonexistant file" << endl;
return -1;
}
yyin = input;
do
{
yyparse();
} while (!feof(yyin));
}
void yyerror(const char* s)
{
cout << "Error. " << s << endl;
exit(-1);
}
But when I pass print "hello" to the compiled program I get:
"Error. syntax error
I think that the issue is the STRING QUOTE STRING QUOTE but I am not sure. What is exactly is going wrong? How would I get the interpreter to print hello?
The answers are below, but I hope the following is more generally useful, as fishing instruction.
There are a variety of debugging tools which would help you. In particular, flex provides the -d flag:
-d, --debug
makes the generated scanner run in "debug" mode. Whenever a pattern is recognized and the global variable yy_flex_debug is non-zero (which is the default), the scanner will write to stderr a line… (flex manual)
bison also provides a debug facility. (bison manual)
There are several means to enable compilation of trace facilities:
the macro YYDEBUG…
the option -t (POSIX Yacc compliant)…
the option --debug (Bison extension)…
the directive %debug…
We suggest that you always enable the debug option so that debugging
is always possible.
…
Once you have compiled the program with trace facilities, the way to
request a trace is to store a nonzero value in the variable yydebug.
You can do this by making the C code do it (in main, perhaps), or you
can alter the value with a C debugger.
Also, remember that flex inserts an automatic rule which causes any otherwise unrecognized character to be echoed to the output. ("By default, any text not matched by a flex scanner is copied to the output" -- Some simple examples) That's why you have the extra " in the error message being printed by your program:
"Error. syntax error
^
That's a bit subtle, though. Tracing flex would have shown you that more directly.
So, finally, the problem(s):
The flex pattern '\"' does not match a ". It matches '"', because single quotes are not special to flex. That's definitely why your parse fails.
Fixing that will let your program parse a single command, but it will generate a syntax error if you try to give it two print commands in the same input. That's because bison always parses until it receives an END token from the lexer, and the lexer (by default) only provides an END token when it reaches the end of the input. You can change
the lexer behaviour (by sending END in other circumstances, for example a new-line) (not recommended)
the parser behaviour (by using ACCEPT) (possible, but rarely necessary)
the grammar, so that it recognizes any number of statements. (recommended)
how to parse from command line arguements in yacc ?
of course i undefined input in both lex & yacc and then wrote
int input(void)
{
printf("in input\n:");
char c;
if(target > limit)
return 0;
if((c = target[0][offset++]) != '\0')
return (c);
target++;
offset =0;
return (' ');
}
where target contains the command line arguements. But only the standard input is getting excueted how to make dis input function get executed.
Did you mean you want your generates parser accept command line arguments? Then you need to add those arguments to the main function. The lexer input is called FILE* yyin, and is initialized to stdin in the lexer. You can change the default behavior by
#include <stdio.h>
extern FILE* yyin;
int main(int argv, char** argv)
{
if(argc==2)
{
yyin = fopen(argv[1], "r");
if(!yyin)
{
fprintf(stderr, "can't read file %s\n", argv[1]);
return 1;
}
}
yyparse();
}
If you want your own function to be executed instead of the one provided by flex, you need to define the YY_INPUT macro.