TraceScreen.c 4.83 KB
Newer Older
Hisham Muhammad's avatar
Hisham Muhammad committed
1
2
/*
htop - TraceScreen.c
Hisham Muhammad's avatar
Hisham Muhammad committed
3
(C) 2005-2006 Hisham H. Muhammad
Hisham Muhammad's avatar
Hisham Muhammad committed
4
5
6
7
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
#include "TraceScreen.h"

#include "CRT.h"
11
#include "InfoScreen.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
12
13
#include "ProcessList.h"
#include "ListItem.h"
14
#include "IncSet.h"
David Hunt's avatar
David Hunt committed
15
#include "StringUtils.h"
16
#include "FunctionBar.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
17

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

Hisham Muhammad's avatar
Hisham Muhammad committed
29
/*{
30
#include "InfoScreen.h"
Hisham Muhammad's avatar
Hisham Muhammad committed
31
32

typedef struct TraceScreen_ {
33
   InfoScreen super;
Hisham Muhammad's avatar
Hisham Muhammad committed
34
   bool tracing;
35
36
37
38
39
40
   int fdpair[2];
   int child;
   FILE* strace;
   int fd_strace;
   bool contLine;
   bool follow;
Hisham Muhammad's avatar
Hisham Muhammad committed
41
42
43
44
} TraceScreen;

}*/

45
static const char* TraceScreenFunctions[] = {"Search ", "Filter ", "AutoScroll ", "Stop Tracing   ", "Done   ", NULL};
Hisham Muhammad's avatar
Hisham Muhammad committed
46

47
static const char* TraceScreenKeys[] = {"F3", "F4", "F8", "F9", "Esc"};
Hisham Muhammad's avatar
Hisham Muhammad committed
48

49
static int TraceScreenEvents[] = {KEY_F(3), KEY_F(4), KEY_F(8), KEY_F(9), 27};
Hisham Muhammad's avatar
Hisham Muhammad committed
50

51
52
53
54
55
56
57
58
59
60
InfoScreenClass TraceScreen_class = {
   .super = {
      .extends = Class(Object),
      .delete = TraceScreen_delete
   },
   .draw = TraceScreen_draw,
   .onErr = TraceScreen_updateTrace,
   .onKey = TraceScreen_onKey,
};

Hisham Muhammad's avatar
Hisham Muhammad committed
61
TraceScreen* TraceScreen_new(Process* process) {
62
   TraceScreen* this = malloc(sizeof(TraceScreen));
63
   Object_setClass(this, Class(TraceScreen));
Hisham Muhammad's avatar
Hisham Muhammad committed
64
   this->tracing = true;
65
66
67
68
69
   this->contLine = false;
   this->follow = false;
   FunctionBar* fuBar = FunctionBar_new(TraceScreenFunctions, TraceScreenKeys, TraceScreenEvents);
   CRT_disableDelay();
   return (TraceScreen*) InfoScreen_init(&this->super, process, fuBar, LINES-2, "");
Hisham Muhammad's avatar
Hisham Muhammad committed
70
71
}

72
73
74
75
76
77
78
79
80
void TraceScreen_delete(Object* cast) {
   TraceScreen* this = (TraceScreen*) cast;
   if (this->child > 0) {
      kill(this->child, SIGTERM);
      waitpid(this->child, NULL, 0);
      fclose(this->strace);
   }
   CRT_enableDelay();
   free(InfoScreen_done((InfoScreen*)cast));
Hisham Muhammad's avatar
Hisham Muhammad committed
81
82
}

83
void TraceScreen_draw(InfoScreen* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
84
85
86
87
   attrset(CRT_colors[PANEL_HEADER_FOCUS]);
   mvhline(0, 0, ' ', COLS);
   mvprintw(0, 0, "Trace of process %d - %s", this->process->pid, this->process->comm);
   attrset(CRT_colors[DEFAULT_COLOR]);
88
   IncSet_drawBar(this->inc);
89
90
}

91
bool TraceScreen_forkTracer(TraceScreen* this) {
Hisham Muhammad's avatar
Hisham Muhammad committed
92
   char buffer[1001];
93
94
95
96
97
   int err = pipe(this->fdpair);
   if (err == -1) return false;
   this->child = fork();
   if (this->child == -1) return false;
   if (this->child == 0) {
98
      seteuid(getuid());
99
100
      dup2(this->fdpair[1], STDERR_FILENO);
      int ok = fcntl(this->fdpair[1], F_SETFL, O_NONBLOCK);
101
      if (ok != -1) {
102
         sprintf(buffer, "%d", this->super.process->pid);
103
104
         execlp("strace", "strace", "-p", buffer, NULL);
      }
105
      const char* message = "Could not execute 'strace'. Please make sure it is available in your $PATH.";
106
      ssize_t written = write(this->fdpair[1], message, strlen(message));
Christian Hesse's avatar
Christian Hesse committed
107
      (void) written;
Hisham Muhammad's avatar
Hisham Muhammad committed
108
109
      exit(1);
   }
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
   fcntl(this->fdpair[0], F_SETFL, O_NONBLOCK);
   this->strace = fdopen(this->fdpair[0], "r");
   this->fd_strace = fileno(this->strace);
   return true;
}

void TraceScreen_updateTrace(InfoScreen* super) {
   TraceScreen* this = (TraceScreen*) super;
   char buffer[1001];
   fd_set fds;
   FD_ZERO(&fds);
// FD_SET(STDIN_FILENO, &fds);
   FD_SET(this->fd_strace, &fds);
   struct timeval tv;
   tv.tv_sec = 0; tv.tv_usec = 500;
   int ready = select(this->fd_strace+1, &fds, NULL, NULL, &tv);
   int nread = 0;
   if (ready > 0 && FD_ISSET(this->fd_strace, &fds))
      nread = fread(buffer, 1, 1000, this->strace);
   if (nread && this->tracing) {
      char* line = buffer;
      buffer[nread] = '\0';
      for (int i = 0; i < nread; i++) {
         if (buffer[i] == '\n') {
            buffer[i] = '\0';
            if (this->contLine) {
               InfoScreen_appendLine(&this->super, line);
               this->contLine = false;
            } else {
               InfoScreen_addLine(&this->super, line);
140
            }
141
            line = buffer+i+1;
Hisham Muhammad's avatar
Hisham Muhammad committed
142
143
         }
      }
144
145
146
147
      if (line < buffer+nread) {
         InfoScreen_addLine(&this->super, line);
         buffer[nread] = '\0';
         this->contLine = true;
148
      }
149
150
151
152
153
154
155
156
      if (this->follow)
         Panel_setSelected(this->super.display, Panel_size(this->super.display)-1);
   }
}

bool TraceScreen_onKey(InfoScreen* super, int ch) {
   TraceScreen* this = (TraceScreen*) super;
   switch(ch) {
157
158
      case 'f':
      case KEY_F(8):
159
160
161
162
         this->follow = !(this->follow);
         if (this->follow)
            Panel_setSelected(super->display, Panel_size(super->display)-1);
         return true;
163
164
165
      case 't':
      case KEY_F(9):
         this->tracing = !this->tracing;
166
167
168
         FunctionBar_setLabel(super->display->defaultBar, KEY_F(9), this->tracing?"Stop Tracing   ":"Resume Tracing ");
         InfoScreen_draw(this);
         return true;
Hisham Muhammad's avatar
Hisham Muhammad committed
169
   }
170
171
   this->follow = false;
   return false;
Hisham Muhammad's avatar
Hisham Muhammad committed
172
}