diff --git a/src/cpulimit.c b/src/cpulimit.c index 9b25b87c..e1c03a28 100644 --- a/src/cpulimit.c +++ b/src/cpulimit.c @@ -38,7 +38,9 @@ #include #include #include +#ifndef __sun__ #include +#endif #include #include #include @@ -173,9 +175,7 @@ int get_pid_max() } fclose(fd); return atoi(buffer); -#elif defined __FreeBSD__ - return 99998; -#elif defined __APPLE__ +#else return 99998; #endif } @@ -319,7 +319,11 @@ int main(int argc, char **argv) { int include_children = 0; //get program name +#ifdef __sun__ + char *p = strrchr(argv[0], (unsigned int)'/'); +#else char *p = (char*)memrchr(argv[0], (unsigned int)'/', strlen(argv[0])); +#endif program_name = p==NULL ? argv[0] : (p+1); //get current pid cpulimit_pid = getpid(); diff --git a/src/process_group.c b/src/process_group.c index f1be4591..a798f433 100644 --- a/src/process_group.c +++ b/src/process_group.c @@ -27,6 +27,10 @@ #include +#ifdef __sun__ +#include +#endif + #include "process_iterator.h" #include "process_group.h" #include "list.h" diff --git a/src/process_iterator.c b/src/process_iterator.c index 8b4019d2..2964df57 100644 --- a/src/process_iterator.c +++ b/src/process_iterator.c @@ -22,7 +22,9 @@ #include #include #include -#ifndef __APPLE__ +#ifdef __sun__ +#include +#elif !defined __APPLE__ #include #endif #include @@ -42,6 +44,10 @@ #include "process_iterator_apple.c" +#elif defined __sun__ + +#include "process_iterator_solaris.c" + #else #error Platform not supported diff --git a/src/process_iterator.h b/src/process_iterator.h index 70520b68..a8d25808 100644 --- a/src/process_iterator.h +++ b/src/process_iterator.h @@ -72,7 +72,7 @@ struct process_filter { }; struct process_iterator { -#ifdef __linux__ +#if defined __linux__ || defined __sun__ DIR *dip; int boot_time; #elif defined __FreeBSD__ diff --git a/src/process_iterator_solaris.c b/src/process_iterator_solaris.c new file mode 100644 index 00000000..cd636310 --- /dev/null +++ b/src/process_iterator_solaris.c @@ -0,0 +1,118 @@ +/** + * + * process_iterator_solaris.c + * Copyright (C) 2016 by Jim Mason + * + * Adapted from process_iterator_linux.c + * Copyright (C) 2005-2012, by: Angelo Marletta + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +int init_process_iterator(struct process_iterator *it, struct process_filter *filter) { + // open a directory stream to /proc directory + if (!(it->dip = opendir("/proc"))) { + perror("opendir"); + return -1; + } + it->filter = filter; + return 0; +} + +static int read_process_info(pid_t pid, struct process *p) { + psinfo_t psinfo; + char statfile[32]; + + p->pid = pid; + sprintf(statfile, "/proc/%ld/psinfo", (long)pid); + FILE *fd = fopen(statfile, "r"); + if (!fd) return -1; + if (!fread(&psinfo, sizeof(psinfo), 1, fd)) { + fclose(fd); + return -1; + } + fclose(fd); + + p->ppid = psinfo.pr_ppid; + p->cputime = psinfo.pr_time.tv_sec * 1.0e03 + psinfo.pr_time.tv_nsec / 1.0e06; + p->starttime = psinfo.pr_start.tv_sec * 1.0e03 + psinfo.pr_start.tv_nsec / 1.0e06; + strcpy(p->command, psinfo.pr_psargs); + + return 0; +} + +static pid_t getppid_of(pid_t pid) { + psinfo_t psinfo; + char statfile[32]; + + sprintf(statfile, "/proc/%ld/psinfo", (long)pid); + FILE *fd = fopen(statfile, "r"); + if (!fd) return -1; + if (!fread(&psinfo, sizeof(psinfo), 1, fd)) { + fclose(fd); + return -1; + } + fclose(fd); + + return psinfo.pr_ppid; +} + +static int is_child_of(pid_t child_pid, pid_t parent_pid) { + int ppid = child_pid; + while(ppid > 1 && ppid != parent_pid) + ppid = getppid_of(ppid); + return ppid == parent_pid; +} + +int get_next_process(struct process_iterator *it, struct process *p) { + if (!it->dip) { + // end of processes + return -1; + } + + if (it->filter->pid != 0 && !it->filter->include_children) { + int ret = read_process_info(it->filter->pid, p); + closedir(it->dip); + it->dip = NULL; + return ret; + } + + // read in from /proc and seek for process dirs + struct dirent *dit; + while ((dit = readdir(it->dip))) { + p->pid = atoi(dit->d_name); + if (it->filter->pid != 0 && it->filter->pid != p->pid && !is_child_of(p->pid, it->filter->pid)) continue; + read_process_info(p->pid, p); + break; + } + + if (!dit) { + // end of processes + closedir(it->dip); + it->dip = NULL; + return -1; + } + + return 0; +} + +int close_process_iterator(struct process_iterator *it) { + if (it->dip && closedir(it->dip) == -1) { + perror("closedir"); + return 1; + } + it->dip = NULL; + return 0; +}