1 #ifndef __linux__
Java_gnu_io_CommPortIdentifier_native_1psmisc_1report_1owner(JNIEnv * env,jobject obj,jstring arg)2 JNIEXPORT jstring JNICALL Java_gnu_io_CommPortIdentifier_native_1psmisc_1report_1owner (JNIEnv *env, jobject obj, jstring arg)
3 {
4 return (*env)->NewStringUTF(env, "Unknown Application");
5 }
6 #else
7
8 /* loosly based on fuser.c by Werner Almesberger. */
9 /* fuser.c - identify processes using files */
10
11 /* Copyright 1993-1998 Werner Almesberger. See file COPYING for details.
12 psmisc (fuser, killall and pstree) program code, documentation and
13 auxiliary programs are
14 Copyright 1993-1998 Werner Almesberger.
15 All rights reserved.
16
17 Redistribution and use in source and binary forms of parts of or the
18 whole original or derived work are permitted provided that the
19 original work is properly attributed to the author. The name of the
20 author may not be used to endorse or promote products derived from
21 this software without specific prior written permission. This work
22 is provided "as is" and without any express or implied warranties.
23 */
24 #include <stdio.h>
25 #include <string.h>
26 #include <dirent.h>
27 #include <pwd.h>
28 #include <signal.h>
29 #include <sys/stat.h>
30 #include <linux/major.h>
31 #include <unistd.h>
32 #include <sys/types.h>
33 #include <stdlib.h>
34 #include "gnu_io_CommPortIdentifier.h"
35
36 #define COMM_LEN 16
37 #define PROC_BASE "/proc"
38 #define UID_UNKNOWN -1
39 #define NAME_FIELD 20 /* space reserved for file name */
40 #define REF_FILE 1 /* an open file */
41 #define REF_ROOT 2 /* current root */
42 #define REF_CWD 4 /* current directory */
43 #define REF_EXE 8 /* executable */
44 #define REF_MMAP 16 /* mmap'ed file or library */
45 #define FLAG_UID 2 /* show uid */
46 #define FLAG_VERB 4 /* show verbose output */
47 #define FLAG_DEV 8 /* show all processes using this device */
48
49
50 char returnstring[256];
51 void parse_args(const char *);
52 typedef struct {
53 const char *name;
54 } SPACE_DSC;
55
56 typedef enum { it_proc,it_mount,it_loop,it_swap } ITEM_TYPE;
57
58 typedef struct item_dsc {
59 ITEM_TYPE type;
60 union {
61 struct {
62 pid_t pid;
63 int uid; /* must also accept UID_UNKNOWN */
64 int ref_set;
65 } proc;
66 struct {
67 const char *path;
68 } misc;
69 } u;
70 struct item_dsc *next;
71 } ITEM_DSC;
72
73 typedef struct file_dsc {
74 const char *name; /* NULL if previous entry has name */
75 dev_t dev;
76 ino_t ino;
77 int flags,sig_num;
78 SPACE_DSC *name_space; /* or NULL if no indication */
79 ITEM_DSC *items;
80 struct file_dsc *named,*next;
81 } FILE_DSC;
82
83 static SPACE_DSC name_spaces[] = { };
84 static FILE_DSC *files = NULL;
85 static FILE_DSC *last_named = NULL;
86 static int all = 0,found_item = 0;
87
add_file(const char * path,unsigned long device,unsigned long inode,pid_t pid,int ref)88 static void add_file(const char *path,unsigned long device,unsigned long inode, pid_t pid,int ref)
89 {
90 struct stat st;
91 FILE_DSC *file,*next;
92 ITEM_DSC **item,*this;
93 unsigned long mount_dev;
94
95 if (device) mount_dev = device;
96 for (file = files; file; file = next) {
97 next = file->next;
98 if (file->flags & FLAG_DEV ? mount_dev && mount_dev == file->dev :
99 device == file->dev && inode == file->ino) {
100 if (!file->name) file = file->named;
101 for (item = &file->items; *item; item = &(*item)->next)
102 if ((*item)->type == it_proc && (*item)->u.proc.pid >= pid)
103 break;
104 if (*item && (*item)->u.proc.pid == pid) this = *item;
105 else {
106 if (!(this = malloc(sizeof(ITEM_DSC)))) {
107 perror("malloc");
108 exit(1);
109 }
110 this->type = it_proc;
111 this->u.proc.pid = pid;
112 this->u.proc.uid = UID_UNKNOWN;
113 this->u.proc.ref_set = 0;
114 this->next = *item;
115 *item = this;
116 found_item = 1;
117 }
118 this->u.proc.ref_set |= ref;
119 if ((file->flags & (FLAG_UID | FLAG_VERB)) && this->u.proc.uid == UID_UNKNOWN && lstat(path,&st) >= 0)
120 this->u.proc.uid = st.st_uid;
121 }
122 }
123 }
124
check_dir(const char * rel,pid_t pid,int type)125 static void check_dir(const char *rel,pid_t pid,int type)
126 {
127 DIR *dir;
128 struct dirent *de;
129 char path[PATH_MAX+1];
130 struct stat st;
131
132 if (!(dir = opendir(rel))) return;
133 while (de = readdir(dir))
134 if (strcmp(de->d_name,".") && strcmp(de->d_name,"..")) {
135 sprintf(path,"%s/%s",rel,de->d_name);
136 if (stat(path,&st) >= 0)
137 add_file(path,st.st_dev,st.st_ino,pid,type);
138 }
139 (void) closedir(dir);
140 }
141
142
scan_fd(void)143 extern void scan_fd(void)
144 {
145 DIR *dir;
146 struct dirent *de;
147 char path[PATH_MAX+1];
148 pid_t pid;
149 int empty;
150
151 if (!(dir = opendir(PROC_BASE))) {
152 perror(PROC_BASE);
153 exit(1);
154 }
155 empty = 1;
156 while (de = readdir(dir))
157 if (pid = atoi(de->d_name)) {
158 empty = 0;
159 sprintf(path,"%s/%d",PROC_BASE,pid);
160 if (chdir(path) >= 0) {
161 check_dir("fd",pid,REF_FILE);
162 }
163 }
164 (void) closedir(dir);
165 if (empty) {
166 fprintf(stderr,PROC_BASE " is empty (not mounted ?)\n");
167 exit(1);
168 }
169 }
170
show_user(const char tstring[],char * rs)171 extern void show_user(const char tstring[],char *rs)
172 {
173 const ITEM_DSC *item;
174 FILE *f;
175 const struct passwd *pw;
176 const char *user,*scan;
177 char tmp[10],path[PATH_MAX+1],comm[COMM_LEN+1];
178 int dummy;
179 int keeper;
180 pid_t self;
181 const char *name;
182 int uid;
183 char temp[80];
184
185 parse_args(tstring);
186 scan_fd();
187 if (seteuid(getuid()) < 0) {
188 sprintf(rs, "%s", "Unknown Linux Application");
189 return;
190 }
191 self = getpid();
192 if (!files->name || !(files->items || all))
193 {
194 sprintf(rs, "%s", "Unknown Linux Application");
195 return;
196 }
197 scan = files->name;
198 strcat(returnstring," ");
199 item = files->items;
200 sprintf(path,PROC_BASE "/%d/stat",item->u.proc.pid);
201 strcpy(comm,"???");
202 if (f = fopen(path,"r")) {
203 (void) fscanf(f,"%d (%[^)]",&dummy,comm);
204 (void) fclose(f);
205 }
206 name = comm;
207 uid = item->u.proc.uid;
208 if (uid == UID_UNKNOWN) user = "???";
209 else if (pw = getpwuid(uid)) user = pw->pw_name;
210 else {
211 sprintf(tmp,"%d",uid);
212 user = tmp;
213 }
214 strcat(returnstring,user);
215 strcat(returnstring," PID = ");
216 sprintf(temp,"%6d ",item->u.proc.pid);
217 strcat(returnstring,temp);
218 strcat(returnstring,"Program = ");
219 if (name)
220 {
221 for (scan = name; *scan; scan++)
222 {
223 if (*scan == '\\')
224 {
225 sprintf(temp,"\\\\");
226 strcat(returnstring,temp);
227 }
228 else if (*scan > ' ' && *scan <= '~')
229 {
230 keeper=strlen(returnstring);
231 returnstring[keeper]= *scan;
232 returnstring[keeper+1]= '\0';
233 }
234 else {
235 sprintf(temp,"\\%03o", scan);
236 strcat(returnstring,temp);
237 }
238 }
239 }
240 strcpy(rs,returnstring);
241 }
enter_item(const char * name,int flags,int sig_number,dev_t dev,ino_t ino,SPACE_DSC * name_space)242 static void enter_item(const char *name,int flags,int sig_number,dev_t dev, ino_t ino,SPACE_DSC *name_space)
243 {
244 static FILE_DSC *last = NULL;
245 FILE_DSC *new;
246
247 if (!(new = malloc(sizeof(FILE_DSC)))) {
248 perror("malloc");
249 exit(1);
250 }
251 if (last_named && !strcmp(last_named->name,name) &&
252 last_named->name_space == name_space) new->name = NULL;
253 else if (!(new->name = strdup(name))) {
254 perror("strdup");
255 exit(1);
256 }
257 new->flags = flags;
258 new->sig_num = sig_number;
259 new->items = NULL;
260 new->next = NULL;
261 new->dev = dev;
262 new->ino = ino;
263 new->name_space = name_space;
264 if (last) last->next = new;
265 else files = new;
266 last = new;
267 new->named = last_named;
268 if (new->name) last_named = new;
269 }
parse_args(const char * argv)270 void parse_args(const char *argv)
271 {
272 SPACE_DSC *name_space;
273 int flags,sig_number,no_files;
274 SPACE_DSC *this_name_space;
275 struct stat st;
276
277 flags = 0;
278 sig_number = SIGKILL;
279 name_space = name_spaces;
280 no_files = 1;
281 flags |= FLAG_UID;
282 no_files = 0;
283 last_named = NULL;
284 this_name_space = name_space;
285 if (this_name_space == name_spaces) {
286 if (stat(argv,&st) < 0) {
287 perror(argv);
288 exit(0);
289 }
290 if (!S_ISSOCK(st.st_mode) || (flags & FLAG_DEV))
291 enter_item(argv,flags,sig_number,st.st_dev,st.st_ino,NULL);
292 }
293 }
294
295
Java_gnu_io_CommPortIdentifier_native_1psmisc_1report_1owner(JNIEnv * env,jobject obj,jstring arg)296 JNIEXPORT jstring JNICALL Java_gnu_io_CommPortIdentifier_native_1psmisc_1report_1owner (JNIEnv *env, jobject obj, jstring arg)
297 {
298 char returnstring[256];
299 const char *str = (*env)->GetStringUTFChars(env, arg, 0);
300 show_user(str,returnstring);
301 (*env)->ReleaseStringUTFChars(env, arg, str);
302 return (*env)->NewStringUTF(env, returnstring);
303 }
304 #endif /* __linux__ */
305