#pragma implementation /* Find the process connected to a given terminal */ #include #include #include #include #include #include #include #include #include "procterm.h" #if 0 /* Read the first line of a file Return -1 if any error. */ static int procterm_readfile (const char *path, char *buf, int sizebuf) { int ret = -1; // No error message signaled as "path" is a file under /proc/pid // and the process may vanish while we are reading it. FILE *fin = fopen (path,"r"); if (fin != NULL){ if (fgets (buf,sizebuf-1,fin)!=NULL){ ret = 0; } fclose (fin); } return ret; } struct PS_PROC { char cmdline[256], user[10], cmd[40], state, ttyc[4]; int uid, pid, ppid, pgrp, session, tty, tpgid, utime, stime, cutime, cstime, counter, priority, start_time, signal, blocked, sigignore, sigcatch; unsigned int flags, min_flt, cmin_flt, maj_flt, cmaj_flt, timeout, it_real_value, vsize, rss, rss_rlim, start_code, end_code, start_stack, kstk_esp, kstk_eip, wchan; }; /* Read the file /proc/pid/stat into the struct PS_PROC Return -1 if any error. */ static int procterm_readstat(pid_t pid, PS_PROC &_psp) { int ret = -1; char tmppath[PATH_MAX]; sprintf (tmppath,"/proc/%d/stat",pid); char buf[PATH_MAX]; if (procterm_readfile (tmppath,buf,sizeof(buf))!=-1){ PS_PROC psp; sscanf(buf, "%d %s %c %d %d %d %d %d %u %u " "%u %u %u %d %d %d %d %d %d %u " "%u %d %u %u %u %u %u %u %u %u %u " "%u %u %u %u\n", &psp.pid, psp.cmd, &psp.state, &psp.ppid, &psp.pgrp, &psp.session, &psp.tty, &psp.tpgid, &psp.flags, &psp.min_flt, &psp.cmin_flt, &psp.maj_flt, &psp.cmaj_flt, &psp.utime, &psp.stime, &psp.cutime, &psp.cstime, &psp.counter, &psp.priority, &psp.timeout, &psp.it_real_value, &psp.start_time, &psp.vsize, &psp.rss, &psp.rss_rlim, &psp.start_code, &psp.end_code, &psp.start_stack, &psp.kstk_esp, &psp.kstk_eip, &psp.signal, &psp.blocked, &psp.sigignore, &psp.sigcatch, &psp.wchan); _psp = psp; ret = 0; } return ret; } #endif PUBLIC PROCTERM::PROCTERM( int _pid, int _inode, unsigned long _ip, unsigned _port) { pid = _pid; inode = _inode; ip = _ip; port = _port; uid = (uid_t)-1; // Will be loaded on demand ppid = (pid_t)-1; } PRIVATE void PROCTERM::loadprcinfo() { char path[PATH_MAX]; sprintf (path,"/proc/%u/status",pid); FILE *fin = fopen (path,"r"); if (fin != NULL){ char buf[200]; while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ if (strncmp(buf,"Uid:",4)==0){ uid = atoi(str_skip(buf+4)); }else if (strncmp(buf,"PPid:",5)==0){ ppid = atoi(str_skip(buf+5)); } } fclose (fin); } } /* Return the user ID associated with this socket */ PUBLIC uid_t PROCTERM::getuid() { if (uid == (uid_t)-1){ loadprcinfo(); } return uid; } /* Return the process ID of this process parent */ PUBLIC pid_t PROCTERM::getppid() { if (ppid == (pid_t)-1){ loadprcinfo(); } return ppid; } /* Return the path of the command associated with this socket */ PUBLIC const char *PROCTERM::getexepath() { if (command.is_empty()){ char path[PATH_MAX]; sprintf (path,"/proc/%u/exe",pid); char buf[PATH_MAX]; int len = readlink (path,buf,sizeof(buf)-1); if (len > 0){ buf[len] = '\0'; command.setfrom (buf); } } return command.get(); } PUBLIC PROCTERM *PROCTERMS::getitem(int no) const { return (PROCTERM*)ARRAY::getitem(no); } /* Extract the list of processes connected to this IP. Return the number of processes collected. */ PUBLIC int PROCTERMS::extractip (const char *ip, PROCTERMS &extr) const { int start = extr.getnb(); extr.neverdelete(); int n = getnb(); unsigned long uip = ipnum_aip2l (ip); for (int i=0; iip == uip) extr.add (t); } return extr.getnb() - start; } struct TBSOCK{ int inode; unsigned long ip; unsigned port; }; /* Extract the list of process connected to a host on a given port. Return the number of processes found. If ipstr is NULL, then all process having a tcp connection to a given port are extracted. If portstr is NULL, all process having a tcp connection to a given host are extracted. If both are NULL, all process having a TCP connection are extracted. */ int procterm_get ( const char *ipstr, // Remote IP or NULL const char *portstr, // Remote port or NULL bool showlisten, PROCTERMS &tb) { int nbsock; TBSOCK *tbsock; PROCTERMS *tb; glocal.tb = &tb; glocal.nbsock = 0; glocal.tbsock = (TBSOCK*)malloc(1024*sizeof(TBSOCK)); int maxsock = 1024; int ret = -1; int start = tb.getnb(); FILE *fin = fopen ("/proc/net/tcp","r"); if (fin != NULL){ char buf[1000]; // Skip the header unsigned long ip = ipstr != NULL ? ipnum_aip2l(ipstr) : 0; ip = htonl (ip); unsigned port = portstr != NULL ? atoi(portstr) : 0; if (fgets(buf,sizeof(buf)-1,fin)!=NULL){ ret = 0; // port = htons (port); while (fgets(buf,sizeof(buf)-1,fin)!=NULL){ unsigned long ip1,ip2; unsigned port1,port2; unsigned inode; char skip[30]; // fprintf (stderr,"read %s\n",buf); if (sscanf (buf,"%s %lx:%x %lx:%x %s %s %s %s %s %s %u" ,skip ,&ip1,&port1 ,&ip2,&port2 ,skip,skip,skip,skip,skip,skip ,&inode)==12 && (ip1 != 0 || showlisten)){ if ((ip == 0 || ip == ip2) && (port == 0 || port == port2)){ if (glocal.nbsock == maxsock){ maxsock += 1024; glocal.tbsock = (TBSOCK*)realloc(glocal.tbsock ,maxsock*sizeof(TBSOCK)); assert (glocal.tbsock != NULL); } int no = glocal.nbsock++; TBSOCK *ptsock = glocal.tbsock + no; ptsock->inode = inode; ptsock->ip = ntohl(ip2); ptsock->port = port2 == 0 ? port1 : port2; // fprintf (stderr,"Collect %08lx %d %08lx %d %u:%u\n",ip1,port1,ip2,port2,inode,ntohs(inode)); }else{ // fprintf (stderr,"Reject %08lx %d %08lx %d %u:%u\n",ip1,port1,ip2,port2,inode,ntohs(inode)); } } } } fclose (fin); } if (0){ TBSOCK *ptsock = glocal.tbsock; for (int i=0; iinode ,ptsock->ip ,ptsock->port); } } ("/proc"); int pid; if (isdigit(basename[0])){ char fdpath[PATH_MAX]; snprintf (fdpath,sizeof(fdpath),"%s/fd",path); glocal.pid = atoi(basename); (fdpath); char s[20]; int n = readlink(path,s,sizeof(s)-1); if (n > 0){ s[n] = '\0'; if (strncmp(s,"socket:[",8)==0){ int inode = atoi(s+8); TBSOCK *ptsock = glocal.tbsock; for (int i=0; iinode == inode){ glocal.tb->add (new PROCTERM(glocal.pid ,inode,ptsock->ip,ptsock->port)); break; } } } } } return false; free (glocal.tbsock); return ret == -1 ? -1 : tb.getnb() - start; }