libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2011, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as 00008 * published by the Free Software Foundation; either version 3 of the 00009 * License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/ctype.h> 00021 #include <libexplain/ac/limits.h> /* for PATH_MAX on Solaris */ 00022 #include <libexplain/ac/stdio.h> 00023 #include <libexplain/ac/stdlib.h> 00024 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */ 00025 00026 #include <libexplain/lsof.h> 00027 #include <libexplain/option.h> 00028 00029 00030 void 00031 explain_lsof(const char *lsof_options, explain_lsof_t *context) 00032 { 00033 FILE *fp; 00034 char command[200]; 00035 00036 if (!lsof_options) 00037 lsof_options = ""; 00038 snprintf 00039 ( 00040 command, 00041 sizeof(command), 00042 "lsof -Ffnp0 %s %s %s", 00043 (lsof_options[0] ? "-a" : ""), 00044 lsof_options, 00045 (explain_option_debug() >= 2 ? "" : "2> /dev/null") 00046 ); 00047 fp = popen(command, "r"); 00048 if (!fp) 00049 return; 00050 context->pid = 0; 00051 context->fildes = -1; 00052 for (;;) 00053 { 00054 char line[PATH_MAX + 2]; 00055 char *lp; 00056 00057 lp = line; 00058 for (;;) 00059 { 00060 int c; 00061 00062 c = getc(fp); 00063 if (c == EOF) 00064 { 00065 *lp++ = '\0'; 00066 break; 00067 } 00068 if (c == '\0') 00069 { 00070 *lp++ = '\0'; 00071 /* 00072 * The lsof(1) man page says that -F0 NUL terminates the 00073 * lines, but it actually terminates them with "\0\n" 00074 * instead, except when it uses just "\0". Sheesh. 00075 */ 00076 c = getc(fp); 00077 if (c != EOF && c != '\n') 00078 ungetc(c, fp); 00079 break; 00080 } 00081 if (lp < line + sizeof(line) - 1) 00082 *lp++ = c; 00083 } 00084 switch (line[0]) 00085 { 00086 case '\0': 00087 pclose(fp); 00088 return; 00089 00090 case 'p': 00091 context->pid = atoi(line + 1); 00092 context->fildes = -1; 00093 break; 00094 00095 case 'f': 00096 context->fildes = atoi(line + 1); 00097 if (context->fildes == 0) 00098 { 00099 if (isalpha((unsigned char)line[1])) 00100 context->fildes = -line[1]; 00101 } 00102 break; 00103 00104 case 'n': 00105 if (context->n_callback) 00106 (*context->n_callback)(context, line + 1); 00107 break; 00108 00109 default: 00110 /* ignore everything else */ 00111 break; 00112 } 00113 } 00114 } 00115 00116 00117 /* vim: set ts=8 sw=4 et : */