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