Reading the process table -- SUNOS 4 version
#define _KMEMUSER
#include <sys/proc.h>
#include <kvm.h>
#include <fcntl.h>
char regexpstr[256];
#define INIT register char *sp=regexpstr;
#define GETC() (*sp++)
#define PEEKC() (*sp)
#define UNGETC(c) (--sp)
#define RETURN(pointer) return(pointer);
#define ERROR(val)
#include <regexp.h>
pid_t
getpidbyname(char *name,pid_t skipit)
{
kvm_t *kd;
char **arg;
int error;
char *p_name=NULL;
char expbuf[256];
char **freeme;
int curpid;
struct user * cur_user;
struct user myuser;
struct proc * cur_proc;
if((kd=kvm_open(NULL,NULL,NULL,O_RDONLY,NULL))==NULL){
return(-1);
}
sprintf(regexpstr,"^.*/%s$",name);
compile(NULL,expbuf,expbuf+256,'\0');
while(cur_proc=kvm_nextproc(kd)){
curpid = cur_proc->p_pid;
if((cur_user=kvm_getu(kd,cur_proc))!=NULL){
error=kvm_getcmd(kd,cur_proc,cur_user,&arg,NULL);
if(error==-1){
if(cur_user->u_comm[0]!='\0'){
p_name=cur_user->u_comm;
}
}
else{
p_name=arg[0];
}
}
if(p_name){
if(!strcmp(p_name,name)){
if(error!=-1){
free(arg);
}
if(skipit!=-1 && ourretval==skipit){
ourretval=-1;
}
else{
close(fd);
break;
}
break;
}
else{
if(step(p_name,expbuf)){
if(error!=-1){
free(arg);
}
break;
}
}
}
if(error!=-1){
free(arg);
}
p_name=NULL;
}
kvm_close(kd);
if(p_name!=NULL){
return(curpid);
}
return (-1);
}
Reading the process table -- SYSV version
pid_t
getpidbyname(char *name,pid_t skipit)
{
DIR *dp;
struct dirent *dirp;
prpsinfo_t retval;
int fd;
pid_t ourretval=-1;
if((dp=opendir("/proc"))==NULL){
return -1;
}
chdir("/proc");
while((dirp=readdir(dp))!=NULL){
if(dirp->d_name[0]!='.'){
if((fd=open(dirp->d_name,O_RDONLY))!=-1){
if(ioctl(fd,PIOCPSINFO,&retval)!=-1){
if(!strcmp(retval.pr_fname,name)){
ourretval=(pid_t)atoi(dirp->d_name);
if(skipit!=-1 && ourretval==skipit){
ourretval=-1;
}
else{
close(fd);
break;
}
}
}
close(fd);
}
}
}
closedir(dp);
return ourretval;
}
Reading the process table -- AIX 4.2 version
#include <stdio.h>
#include <procinfo.h>
int getprocs(struct procsinfo *, int, struct fdsinfo *,
int, pid_t *, int);
pid_t getpidbyname(char *name, pid_t *nextPid)
{
struct procsinfo pi;
pid_t retval = (pid_t) -1;
pid_t pid;
pid = *nextPid;
while(1)
{
if(getprocs(&pi, sizeof pi, 0, 0, &pid, 1) != 1)
break;
if(!strcmp(name, pi.pi_comm))
{
retval = pi.pi_pid;
*nextPid = pid;
break;
}
}
return retval;
}
int main(int argc, char *argv[])
{
int curArg;
pid_t pid;
pid_t nextPid;
if(argc == 1)
{
printf("syntax: %s <program> [program ...]\n",argv[0]);
exit(1);
}
for(curArg = 1; curArg < argc; curArg++)
{
printf("Process IDs for %s\n", argv[curArg]);
for(nextPid = 0, pid = 0; pid != -1; )
if((pid = getpidbyname(argv[curArg], &nextPid)) != -1)
printf("\t%d\n", pid);
}
}
Reading the process table using popen and ps
#include <stdio.h> /* FILE, sprintf, fgets, puts */
#include <stdlib.h> /* atoi, exit, EXIT_SUCCESS */
#include <string.h> /* strtok, strcmp */
#include <sys/types.h> /* pid_t */
#include <sys/wait.h> /* WIFEXITED, WEXITSTATUS */
char *procname(pid_t pid)
{
static char line[133], command[80], *linep, *token, *cmd;
FILE *fp;
int status;
if (0 == pid) return (char *)0;
sprintf(command, "ps -p %d 2>/dev/null", pid);
fp = popen(command, "r");
if ((FILE *)0 == fp) return (char *)0;
/* read the header line */
if ((char *)0 == fgets(line, sizeof line, fp))
{
pclose(fp);
return (char *)0;
}
/* figure out where the command name is from the column headings.
* (BSD-ish machines put the COMMAND in the 5th column, while SysV
* seems to put CMD or COMMAND in the 4th column.)
*/
for (linep = line; ; linep = (char *)0)
{
if ((char *)0 == (token = strtok(linep, " \t\n")))
{
pclose(fp);
return (char *)0;
}
if (0 == strcmp("COMMAND", token) || 0 == strcmp("CMD", token))
{ /* we found the COMMAND column */
cmd = token;
break;
}
}
/* read the ps(1) output line */
if ((char *)0 == fgets(line, sizeof line, fp))
{
pclose(fp);
return (char *)0;
}
/* grab the "word" underneath the command heading... */
if ((char *)0 == (token = strtok(cmd, " \t\n")))
{
pclose(fp);
return (char *)0;
}
status = pclose(fp);
if (!WIFEXITED(status) || 0 != WEXITSTATUS(status))
return (char *)0;
return token;
}
int main(int argc, char *argv[])
{
puts(procname(atoi(argv[1])));
exit(EXIT_SUCCESS);
}
Daemon utility functions
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
/* closeall() -- close all FDs >= a specified value */
void closeall(int fd)
{
int fdlimit = sysconf(_SC_OPEN_MAX);
while (fd < fdlimit)
close(fd++);
}
/* daemon() - detach process from user and disappear into the background
* returns -1 on failure, but you can't do much except exit in that case
* since we may already have forked. This is based on the BSD version,
* so the caller is responsible for things like the umask, etc.
*/
/* believed to work on all Posix systems */
int daemon(int nochdir, int noclose)
{
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0); /* exit the original process */
}
if (setsid() < 0) /* shoudn't fail */
return -1;
/* dyke out this switch if you want to acquire a control tty in */
/* the future -- not normally advisable for daemons */
switch (fork())
{
case 0: break;
case -1: return -1;
default: _exit(0);
}
if (!nochdir)
chdir("/");
if (!noclose)
{
closeall(0);
open("/dev/null",O_RDWR);
dup(0); dup(0);
}
return 0;
}
/* fork2() -- like fork, but the new process is immediately orphaned
* (won't leave a zombie when it exits)
* Returns 1 to the parent, not any meaningful pid.
* The parent cannot wait() for the new process (it's unrelated).
*/
/* This version assumes that you *haven't* caught or ignored SIGCHLD. */
/* If you have, then you should just be using fork() instead anyway. */
int fork2()
{
pid_t pid;
int rc;
int status;
if (!(pid = fork()))
{
switch (fork())
{
case 0: return 0;
case -1: _exit(errno); /* assumes all errnos are <256 */
default: _exit(0);
}
}
if (pid < 0 || waitpid(pid,&status,0) < 0)
return -1;
if (WIFEXITED(status))
if (WEXITSTATUS(status) == 0)
return 1;
else
errno = WEXITSTATUS(status);
else
errno = EINTR; /* well, sort of :-) */
return -1;
}
An example of using the above functions:
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <errno.h>
int daemon(int,int);
int fork2(void);
void closeall(int);
#define TCP_PORT 8888
void errexit(const char *str)
{
syslog(LOG_INFO, "%s failed: %d (%m)", str, errno);
exit(1);
}
void errreport(const char *str)
{
syslog(LOG_INFO, "%s failed: %d (%m)", str, errno);
}
/* the actual child process is here. */
void run_child(int sock)
{
FILE *in = fdopen(sock,"r");
FILE *out = fdopen(sock,"w");
int ch;
setvbuf(in, NULL, _IOFBF, 1024);
setvbuf(out, NULL, _IOLBF, 1024);
while ((ch = fgetc(in)) != EOF)
fputc(toupper(ch), out);
fclose(out);
}
/* This is the daemon's main work -- listen for connections and spawn */
void process()
{
struct sockaddr_in addr;
int addrlen = sizeof(addr);
int sock = socket(AF_INET, SOCK_STREAM, 0);
int flag = 1;
int rc = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
&flag, sizeof(flag));
if (rc < 0)
errexit("setsockopt");
addr.sin_family = AF_INET;
addr.sin_port = htons(TCP_PORT);
addr.sin_addr.s_addr = INADDR_ANY;
rc = bind(sock, (struct sockaddr *) &addr, addrlen);
if (rc < 0)
errexit("bind");
rc = listen(sock, 5);
if (rc < 0)
errexit("listen");
for (;;)
{
rc = accept(sock, (struct sockaddr *) &addr, &addrlen);
if (rc >= 0)
switch (fork2())
{
case 0: close(sock); run_child(rc); _exit(0);
case -1: errreport("fork2"); close(rc); break;
default: close(rc);
}
}
}
int main()
{
if (daemon(0,0) < 0)
{
perror("daemon");
exit(2);
}
openlog("test", LOG_PID, LOG_DAEMON);
process();
return 0;
}
Modem handling example
/* issue some simple modem commands
* requires the name of a serial device (preferably a dial-out device,
* or a non-modem-control device) as its only parameter.
* If you don't have functional dial-out devices, then move CLOCAL
* to CFLAGS_TO_SET instead.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/ioctl.h> /* maybe; system-dependent */
#include <termios.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#define CFLAGS_TO_SET (CREAD | HUPCL)
#define CFLAGS_TO_CLEAR (CSTOPB | PARENB | CLOCAL)
enum flowmode { NoFlow, HardFlow, SoftFlow };
/* system-dependent */
#define CFLAGS_HARDFLOW (CRTSCTS)
#define EXAMPLE_BAUD B19200
#define EXAMPLE_FLOW HardFlow
static void die(const char *msg)
{
fprintf(stderr, "%s\n", msg);
exit(1);
}
static int close_and_complain(int fd, const char *msg, int err)
{
fprintf(stderr, "%s: %s\n", msg, strerror(err));
if (fd >= 0)
close(fd);
errno = err;
return -1;
}
int open_port(const char *name, speed_t baud, enum flowmode flow)
{
int flags;
struct termios attr;
int fd = open(name, O_RDWR | O_NONBLOCK | O_NOCTTY);
if (fd < 0)
return close_and_complain(-1, "open", errno);
/* set vaguely sensibe settings */
if (tcgetattr(fd, &attr) < 0)
return close_and_complain(fd, "tcgetattr", errno);
/* no special input or output processing */
attr.c_iflag = (flow == SoftFlow) ? (IXON | IXOFF) : 0;
attr.c_oflag = 0;
/* set 8-bit character size and miscellanous control modes */
attr.c_cflag &= ~(CSIZE | CFLAGS_TO_CLEAR | CFLAGS_HARDFLOW);
attr.c_cflag |= (CS8 | CFLAGS_TO_SET);
if (flow == HardFlow)
attr.c_cflag |= CFLAGS_HARDFLOW;
/* local modes */
attr.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ISIG);
/* special characters -- most disabled by prior settings anyway */
{
int i;
#ifdef _POSIX_VDISABLE
attr.c_cc[0] = _POSIX_VDISABLE;
#else
attr.c_cc[0] = fpathconf(fd, _PC_VDISABLE);
To Look for similar posts on File handling in Linux explore the following links from the same blog as well.
Post a Comment