OpenFilesScreen.c 6.75 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
3
4
5
6
7
/*
htop - OpenFilesScreen.c
(C) 2005-2006 Hisham H. Muhammad
Released under the GNU GPL, see the COPYING file
in the source distribution for its full text.
*/

Hisham Muhammad's avatar
Hisham Muhammad committed
8
9
10
11
12
#include "OpenFilesScreen.h"

#include "CRT.h"
#include "ProcessList.h"
#include "ListItem.h"
13
14
#include "IncSet.h"
#include "String.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
15
16

#include <string.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
17
18
19
20
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <unistd.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
21
#include <stdlib.h>
Hisham Muhammad's avatar
Hisham Muhammad committed
22
23
24
25
#include <fcntl.h>
#include <sys/types.h>
#include <sys/wait.h>

Hisham Muhammad's avatar
Hisham Muhammad committed
26
/*{
Hisham Muhammad's avatar
Hisham Muhammad committed
27
28
29
30
#include "Process.h"
#include "Panel.h"
#include "FunctionBar.h"

Hisham Muhammad's avatar
Hisham Muhammad committed
31
32
33
34
typedef struct OpenFiles_Data_ {
   char* data[256];
} OpenFiles_Data;

Hisham Muhammad's avatar
Hisham Muhammad committed
35
typedef struct OpenFiles_ProcessData_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
36
   OpenFiles_Data data;
37
   int error;
Hisham Muhammad's avatar
Hisham Muhammad committed
38
   struct OpenFiles_FileData_* files;
Hisham Muhammad's avatar
Hisham Muhammad committed
39
40
41
} OpenFiles_ProcessData;

typedef struct OpenFiles_FileData_ {
Hisham Muhammad's avatar
Hisham Muhammad committed
42
   OpenFiles_Data data;
Hisham Muhammad's avatar
Hisham Muhammad committed
43
44
45
46
47
   struct OpenFiles_FileData_* next;
} OpenFiles_FileData;

typedef struct OpenFilesScreen_ {
   Process* process;
48
   pid_t pid;
Hisham Muhammad's avatar
Hisham Muhammad committed
49
50
51
52
53
54
   Panel* display;
   FunctionBar* bar;
} OpenFilesScreen;

}*/

55
static const char* ofsFunctions[] = {"Search ", "Filter ", "Refresh", "Done   ", NULL};
Hisham Muhammad's avatar
Hisham Muhammad committed
56

57
static const char* ofsKeys[] = {"F3", "F4", "F5", "Esc"};
Hisham Muhammad's avatar
Hisham Muhammad committed
58

59
static int ofsEvents[] = {KEY_F(3), KEY_F(4), KEY_F(5), 27};
Hisham Muhammad's avatar
Hisham Muhammad committed
60
61
62
63

OpenFilesScreen* OpenFilesScreen_new(Process* process) {
   OpenFilesScreen* this = (OpenFilesScreen*) malloc(sizeof(OpenFilesScreen));
   this->process = process;
64
   this->display = Panel_new(0, 1, COLS, LINES-3, false, Class(ListItem));
65
66
67
68
   if (Process_isThread(process))
      this->pid = process->tgid;
   else
      this->pid = process->pid;
Hisham Muhammad's avatar
Hisham Muhammad committed
69
70
71
72
73
74
75
76
   return this;
}

void OpenFilesScreen_delete(OpenFilesScreen* this) {
   Panel_delete((Object*)this->display);
   free(this);
}

77
static void OpenFilesScreen_draw(OpenFilesScreen* this, IncSet* inc) {
Hisham Muhammad's avatar
Hisham Muhammad committed
78
79
   attrset(CRT_colors[METER_TEXT]);
   mvhline(0, 0, ' ', COLS);
80
   mvprintw(0, 0, "Snapshot of files open in process %d - %s", this->pid, this->process->comm);
Hisham Muhammad's avatar
Hisham Muhammad committed
81
82
   attrset(CRT_colors[DEFAULT_COLOR]);
   Panel_draw(this->display, true);
83
   IncSet_drawBar(inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
84
85
}

86
static OpenFiles_ProcessData* OpenFilesScreen_getProcessData(pid_t pid) {
Hisham Muhammad's avatar
Hisham Muhammad committed
87
   char command[1025];
Hisham Muhammad's avatar
Hisham Muhammad committed
88
   snprintf(command, 1024, "lsof -P -p %d -F 2> /dev/null", pid);
Hisham Muhammad's avatar
Hisham Muhammad committed
89
   FILE* fd = popen(command, "r");
90
   OpenFiles_ProcessData* pdata = calloc(1, sizeof(OpenFiles_ProcessData));
91
   OpenFiles_FileData* fdata = NULL;
Hisham Muhammad's avatar
Hisham Muhammad committed
92
   OpenFiles_Data* item = &(pdata->data);
93
   if (!fd) {
94
95
      pdata->error = 127;
      return pdata;
96
   }
Hisham Muhammad's avatar
Hisham Muhammad committed
97
98
   while (!feof(fd)) {
      int cmd = fgetc(fd);
Hisham Muhammad's avatar
Hisham Muhammad committed
99
      if (cmd == EOF)
Hisham Muhammad's avatar
Hisham Muhammad committed
100
101
         break;
      char* entry = malloc(1024);
Hisham Muhammad's avatar
Hisham Muhammad committed
102
103
104
105
      if (!fgets(entry, 1024, fd)) {
         free(entry);
         break;
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
106
107
108
      char* newline = strrchr(entry, '\n');
      *newline = '\0';
      if (cmd == 'f') {
Hisham Muhammad's avatar
Hisham Muhammad committed
109
         OpenFiles_FileData* nextFile = calloc(1, sizeof(OpenFiles_FileData));
110
111
         if (fdata == NULL) {
            pdata->files = nextFile;
Hisham Muhammad's avatar
Hisham Muhammad committed
112
         } else {
113
            fdata->next = nextFile;
Hisham Muhammad's avatar
Hisham Muhammad committed
114
         }
115
         fdata = nextFile;
Hisham Muhammad's avatar
Hisham Muhammad committed
116
         item = &(fdata->data);
Hisham Muhammad's avatar
Hisham Muhammad committed
117
118
119
      }
      item->data[cmd] = entry;
   }
120
121
   pdata->error = pclose(fd);
   return pdata;
Hisham Muhammad's avatar
Hisham Muhammad committed
122
123
}

124
125
126
127
128
129
static inline void addLine(const char* line, Vector* lines, Panel* panel, const char* incFilter) {
   Vector_add(lines, (Object*) ListItem_new(line, 0));
   if (!incFilter || String_contains_i(line, incFilter))
      Panel_add(panel, (Object*)Vector_get(lines, Vector_size(lines)-1));
}

Hisham Muhammad's avatar
Hisham Muhammad committed
130
131
132
133
134
135
static inline void OpenFiles_Data_clear(OpenFiles_Data* data) {
   for (int i = 0; i < 255; i++)
      if (data->data[i])
         free(data->data[i]);
}

136
static void OpenFilesScreen_scan(OpenFilesScreen* this, Vector* lines, IncSet* inc) {
Hisham Muhammad's avatar
Hisham Muhammad committed
137
   Panel* panel = this->display;
138
   int idx = Panel_getSelectedIndex(panel);
Hisham Muhammad's avatar
Hisham Muhammad committed
139
   Panel_prune(panel);
140
141
142
143
144
   OpenFiles_ProcessData* pdata = OpenFilesScreen_getProcessData(this->pid);
   if (pdata->error == 127) {
      addLine("Could not execute 'lsof'. Please make sure it is available in your $PATH.", lines, panel, IncSet_filter(inc));
   } else if (pdata->error == 1) {
      addLine("Failed listing open files.", lines, panel, IncSet_filter(inc));
Hisham Muhammad's avatar
Hisham Muhammad committed
145
   } else {
146
147
      OpenFiles_FileData* fdata = pdata->files;
      while (fdata) {
Hisham Muhammad's avatar
Hisham Muhammad committed
148
         char entry[1024];
Hisham Muhammad's avatar
Hisham Muhammad committed
149
         char** data = fdata->data.data;
Hisham Muhammad's avatar
Hisham Muhammad committed
150
         sprintf(entry, "%5s %4s %10s %10s %10s %s",
Hisham Muhammad's avatar
Hisham Muhammad committed
151
152
153
154
155
156
            data['f'] ? data['f'] : "",
            data['t'] ? data['t'] : "",
            data['D'] ? data['D'] : "",
            data['s'] ? data['s'] : "",
            data['i'] ? data['i'] : "",
            data['n'] ? data['n'] : "");
157
         addLine(entry, lines, panel, IncSet_filter(inc));
Hisham Muhammad's avatar
Hisham Muhammad committed
158
         OpenFiles_Data_clear(&fdata->data);
159
160
         OpenFiles_FileData* old = fdata;
         fdata = fdata->next;
Hisham Muhammad's avatar
Hisham Muhammad committed
161
162
         free(old);
      }
Hisham Muhammad's avatar
Hisham Muhammad committed
163
      OpenFiles_Data_clear(&pdata->data);
Hisham Muhammad's avatar
Hisham Muhammad committed
164
   }
165
166
   free(pdata);
   Vector_insertionSort(lines);
167
   Vector_insertionSort(panel->items);
Hisham Muhammad's avatar
Hisham Muhammad committed
168
   Panel_setSelected(panel, idx);
Hisham Muhammad's avatar
Hisham Muhammad committed
169
170
171
172
173
}

void OpenFilesScreen_run(OpenFilesScreen* this) {
   Panel* panel = this->display;
   Panel_setHeader(panel, "   FD TYPE     DEVICE       SIZE       NODE NAME");
174
175
176
177

   FunctionBar* bar = FunctionBar_new(ofsFunctions, ofsKeys, ofsEvents);
   IncSet* inc = IncSet_new(bar);
   
178
   Vector* lines = Vector_new(panel->items->type, true, DEFAULT_SIZE);
179
180
181

   OpenFilesScreen_scan(this, lines, inc);
   OpenFilesScreen_draw(this, inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
182
183
184
   
   bool looping = true;
   while (looping) {
185
   
Hisham Muhammad's avatar
Hisham Muhammad committed
186
      Panel_draw(panel, true);
187
188
189
      
      if (inc->active)
         move(LINES-1, CRT_cursorX);
Hisham Muhammad's avatar
Hisham Muhammad committed
190
      int ch = getch();
191
      
Hisham Muhammad's avatar
Hisham Muhammad committed
192
193
194
195
196
197
198
199
      if (ch == KEY_MOUSE) {
         MEVENT mevent;
         int ok = getmouse(&mevent);
         if (ok == OK)
            if (mevent.y >= panel->y && mevent.y < LINES - 1) {
               Panel_setSelected(panel, mevent.y - panel->y + panel->scrollV);
               ch = 0;
            } if (mevent.y == LINES - 1)
200
               ch = FunctionBar_synthesizeEvent(inc->bar, mevent.x);
Hisham Muhammad's avatar
Hisham Muhammad committed
201
      }
202
203
204
205
206
207

      if (inc->active) {
         IncSet_handleKey(inc, ch, panel, IncSet_getListItemValue, lines);
         continue;
      }

Hisham Muhammad's avatar
Hisham Muhammad committed
208
209
210
      switch(ch) {
      case ERR:
         continue;
211
212
213
214
215
216
217
218
      case KEY_F(3):
      case '/':
         IncSet_activate(inc, INC_SEARCH);
         break;
      case KEY_F(4):
      case '\\':
         IncSet_activate(inc, INC_FILTER);
         break;
Hisham Muhammad's avatar
Hisham Muhammad committed
219
220
      case KEY_F(5):
         clear();
221
222
         OpenFilesScreen_scan(this, lines, inc);
         OpenFilesScreen_draw(this, inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
223
224
225
         break;
      case '\014': // Ctrl+L
         clear();
226
         OpenFilesScreen_draw(this, inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
227
228
229
         break;
      case 'q':
      case 27:
230
      case KEY_F(10):
Hisham Muhammad's avatar
Hisham Muhammad committed
231
232
233
234
         looping = false;
         break;
      case KEY_RESIZE:
         Panel_resize(panel, COLS, LINES-2);
235
         OpenFilesScreen_draw(this, inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
236
237
238
239
240
         break;
      default:
         Panel_onKey(panel, ch);
      }
   }
241

242
   Vector_delete(lines);
243
244
   FunctionBar_delete((Object*)bar);
   IncSet_delete(inc);
Hisham Muhammad's avatar
Hisham Muhammad committed
245
}