commited some changes and added README
[meinos.git] / apps / init / procfs.c
blobe9d79cc8420422fb614c1a9c5981adf11f0bbeac
1 /*
2 meinOS - A unix-like x86 microkernel operating system
3 Copyright (C) 2008 Janosch Gräf <janosch.graef@gmx.net>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <fuse.h>
22 #include <llist.h>
23 #include <stdlib.h>
24 #include <path.h>
25 #include <proc.h>
26 #include <stdio.h>
28 #include "init.h"
30 #define PROCFS_NAME "procfs"
31 #define PROCFS_MOUNTPOINT "/proc"
33 typedef struct procfs_path_S procfs_path_t;
35 typedef struct {
36 pid_t pid;
37 char *exe;
38 char *name;
39 uid_t uid;
40 gid_t gid;
41 } procfs_proc_t;
43 typedef enum {
44 PROCFS_FILE,
45 PROCFS_DIR,
46 PROCFS_SYMLINK
47 } procfs_ftype_t;
49 typedef struct {
50 const char *name;
51 procfs_ftype_t ftype;
52 struct {
53 int (*cb_read)(procfs_path_t *path,char *buf,size_t size,off_t offset);
54 int (*cb_write)(procfs_path_t *path,const char *buf,size_t size,off_t offset);
55 } file;
56 struct {
57 int (*cb_readdir)(procfs_path_t *path,void *buf,fuse_fill_dir_t filler,off_t offset);
58 } dir;
59 struct {
60 } symlink;
61 } procfs_file_t;
63 struct procfs_path_S {
64 pid_t pid;
65 procfs_proc_t *proc;
66 procfs_file_t *file;
67 const char *subfile;
68 int isdir;
71 static int procfs_loginuid_read(procfs_path_t *path,char *buf,size_t size,off_t offset);
72 static int procfs_mem_read(procfs_path_t *path,char *buf,size_t size,off_t offset);
73 static int procfs_mem_write(procfs_path_t *path,const char *buf,size_t size,off_t offset);
74 static procfs_file_t procfs_files[] = {
75 { .name = "cwd", .ftype = PROCFS_SYMLINK },
76 { .name = "exe", .ftype = PROCFS_SYMLINK },
77 { .name = "loginuid", .ftype = PROCFS_FILE, .file = { .cb_read = procfs_loginuid_read } },
78 { .name = "mem", .ftype = PROCFS_FILE, .file = { .cb_read = procfs_mem_read, .cb_write = procfs_mem_write } },
79 { .name = NULL }
82 static llist_t procfs_processes;
84 static int procfs_loginuid_read(procfs_path_t *path,char *buf,size_t size,off_t offset) {
85 return 0;
88 static int procfs_mem_read(procfs_path_t *path,char *buf,size_t size,off_t offset) {
89 return 0;
92 static int procfs_mem_write(procfs_path_t *path,const char *buf,size_t size,off_t offset) {
93 return 0;
96 static procfs_proc_t *procfs_proc_find(pid_t pid) {
97 size_t i;
98 procfs_proc_t *proc;
99 for (i=0;(proc = llist_get(procfs_processes,i));i++) {
100 if (proc->pid==pid) return proc;
102 return NULL;
105 int procfs_proc_new(pid_t pid,const char *name,const char *exe) {
106 procfs_proc_t *proc = malloc(sizeof(procfs_proc_t));
107 proc->pid = pid;
108 proc->uid = getuidbypid(pid);
109 proc->gid = getgidbypid(pid);
110 if (name==NULL) proc->name = getname(pid);
111 else proc->name = strdup(name);
112 if (exe==NULL) proc->exe = NULL;
113 else proc->exe = strdup(exe);
114 llist_push(procfs_processes,proc);
115 return 0;
118 int procfs_proc_update(pid_t pid,const char *name,const char *exe) {
119 procfs_proc_t *proc = procfs_proc_find(pid);
120 if (proc!=NULL) {
121 if (name!=NULL) {
122 free(proc->name);
123 proc->name = strdup(name);
125 if (exe!=NULL) {
126 free(proc->exe);
127 proc->exe = strdup(exe);
129 return 0;
131 else return -1;
134 static void procfs_parse_path(const char *strpath,procfs_path_t *path) {
135 path_t *tpath = path_parse(strpath);
136 path_reject_dots(tpath);
138 memset(path,0,sizeof(procfs_path_t));
139 path->isdir = 1;
140 if (tpath->num_parts>0) {
141 if (strcmp(tpath->parts[0],"self")==0) {
142 path->pid = fuse_current_context->pid;
144 else {
145 path->pid = strtoul(tpath->parts[0],NULL,10);
147 path->proc = procfs_proc_find(path->pid);
148 //path->isdir = 1;
150 if (tpath->num_parts>1) {
151 size_t i;
152 for (i=0;procfs_files[i].name!=NULL;i++) {
153 if (strcmp(tpath->parts[1],procfs_files[i].name)==0) {
154 path->file = procfs_files+i;
155 path->isdir = (path->file->ftype==PROCFS_DIR);
159 if (tpath->num_parts>2) {
160 static char subfile_buf[256];
161 strncpy(subfile_buf,tpath->parts[2],256);
162 path->subfile = subfile_buf;
163 path->isdir = 0;
166 path_destroy(tpath);
169 static int procfs_open(const char *strpath,struct fuse_file_info *fi) {
170 procfs_path_t path;
172 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
173 else if (path.isdir) return -EISDIR;
174 else return 0;
177 static int procfs_close(const char *path,struct fuse_file_info *fi) {
178 return 0;
181 static int procfs_read(const char *strpath,char *buf,size_t count,off_t offset,struct fuse_file_info *fi) {
182 procfs_path_t path;
183 procfs_parse_path(strpath,&path);
185 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
186 else if (path.isdir) return -EISDIR;
187 else {
188 if (path.file->file.cb_read!=NULL) return path.file->file.cb_read(&path,buf,count,offset);
189 else return -ENOSYS;
193 static int procfs_write(const char *strpath,const char *buf,size_t count,off_t offset,struct fuse_file_info *fi) {
194 procfs_path_t path;
195 procfs_parse_path(strpath,&path);
197 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
198 else if (path.isdir) return -EISDIR;
199 else {
200 if (path.file->file.cb_write!=NULL) return path.file->file.cb_write(&path,buf,count,offset);
201 else return -ENOSYS;
205 static int procfs_readdir(const char *strpath,void *buf,fuse_fill_dir_t filler,off_t offset,struct fuse_file_info *fi) {
206 procfs_path_t path;
207 procfs_parse_path(strpath,&path);
209 if (!path.isdir) return -ENOTDIR;
210 else if (path.pid==0) {
211 // list all processes
212 size_t i;
213 procfs_proc_t *proc;
214 struct stat stbuf = {
215 /// @todo correct permissions
216 .st_mode = S_IFDIR|0777,
218 for (i=0;(proc = llist_get(procfs_processes,i));i++) {
219 char str_pid[16];
220 snprintf(str_pid,16,"%d",proc->pid);
221 stbuf.st_uid = proc->uid;
222 stbuf.st_gid = proc->gid;
223 filler(buf,str_pid,&stbuf,0);
225 return 0;
227 else if (path.proc!=NULL) return -ENOENT;
228 else {
229 if (path.file->dir.cb_readdir!=NULL) return path.file->dir.cb_readdir(&path,buf,filler,offset);
230 else return -ENOSYS;
234 static int procfs_getattr(const char *strpath,struct stat *stbuf) {
235 procfs_path_t path;
236 procfs_parse_path(strpath,&path);
238 memset(stbuf,0,sizeof(struct stat));
240 if (path.file!=NULL) {
241 if (path.file->ftype==PROCFS_DIR) stbuf->st_mode = S_IFDIR;
242 else if (path.file->ftype==PROCFS_SYMLINK) stbuf->st_mode = S_IFLNK;
243 else stbuf->st_mode = S_IFREG;
245 else stbuf->st_mode = S_IFDIR;
247 /// @todo correct permissions
248 stbuf->st_mode |= 0777;
250 return 0;
253 int procfs_init(pid_t *grub_modules) {
254 size_t i;
255 pid_t pid;
257 procfs_processes = llist_create();
259 // put init itself in process list
260 procfs_proc_new(1,"init",NULL);
262 // put GRUB modules in process list
263 for (i=0;(pid = grub_modules[i])!=0;i++) {
264 procfs_proc_new(pid,NULL,NULL);
267 return 0;
270 int procfs_run(void) {
271 // start FUSE
272 struct fuse_operations devfs_oper = {
273 .open = procfs_open,
274 .release = procfs_close,
275 .read = procfs_read,
276 .write = procfs_write,
277 .readdir = procfs_readdir,
278 .getattr = procfs_getattr
281 // fake argc/argv
282 int fake_argc = 2;
283 char *fake_argv[2] = { PROCFS_NAME,PROCFS_MOUNTPOINT };
284 fuse_main(fake_argc,fake_argv,&devfs_oper,NULL);
286 return 0;