File Handling in Linux 11


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

Previous Post Next Post