kernel: ~Stack can grow now (upto 4MB)
[meinos.git] / apps / init / procfs.c
blobb7581a5518727330f4a7a09b5885caa5831592fe
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 path->pid = strtoul(tpath->parts[0],NULL,10);
142 path->proc = procfs_proc_find(path->pid);
143 //path->isdir = 1;
145 if (tpath->num_parts>1) {
146 size_t i;
147 for (i=0;procfs_files[i].name!=NULL;i++) {
148 if (strcmp(tpath->parts[1],procfs_files[i].name)==0) {
149 path->file = procfs_files+i;
150 path->isdir = (path->file->ftype==PROCFS_DIR);
154 if (tpath->num_parts>2) {
155 static char subfile_buf[256];
156 strncpy(subfile_buf,tpath->parts[2],256);
157 path->subfile = subfile_buf;
158 path->isdir = 0;
161 path_destroy(tpath);
164 static int procfs_open(const char *strpath,struct fuse_file_info *fi) {
165 procfs_path_t path;
167 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
168 else if (path.isdir) return -EISDIR;
169 else return 0;
172 static int procfs_close(const char *path,struct fuse_file_info *fi) {
173 return 0;
176 static int procfs_read(const char *strpath,char *buf,size_t count,off_t offset,struct fuse_file_info *fi) {
177 procfs_path_t path;
178 procfs_parse_path(strpath,&path);
180 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
181 else if (path.isdir) return -EISDIR;
182 else {
183 if (path.file->file.cb_read!=NULL) return path.file->file.cb_read(&path,buf,count,offset);
184 else return -ENOSYS;
188 static int procfs_write(const char *strpath,const char *buf,size_t count,off_t offset,struct fuse_file_info *fi) {
189 procfs_path_t path;
190 procfs_parse_path(strpath,&path);
192 if (path.pid!=0 && path.proc!=NULL) return -ENOENT;
193 else if (path.isdir) return -EISDIR;
194 else {
195 if (path.file->file.cb_write!=NULL) return path.file->file.cb_write(&path,buf,count,offset);
196 else return -ENOSYS;
200 static int procfs_readdir(const char *strpath,void *buf,fuse_fill_dir_t filler,off_t offset,struct fuse_file_info *fi) {
201 procfs_path_t path;
202 procfs_parse_path(strpath,&path);
204 if (!path.isdir) return -ENOTDIR;
205 else if (path.pid==0) {
206 // list all processes
207 size_t i;
208 procfs_proc_t *proc;
209 struct stat stbuf = {
210 /// @todo correct permissions
211 .st_mode = S_IFDIR|0777,
213 for (i=0;(proc = llist_get(procfs_processes,i));i++) {
214 char str_pid[16];
215 snprintf(str_pid,16,"%d",proc->pid);
216 stbuf.st_uid = proc->uid;
217 stbuf.st_gid = proc->gid;
218 filler(buf,str_pid,&stbuf,0);
220 return 0;
222 else if (path.proc!=NULL) return -ENOENT;
223 else {
224 if (path.file->dir.cb_readdir!=NULL) return path.file->dir.cb_readdir(&path,buf,filler,offset);
225 else return -ENOSYS;
229 static int procfs_getattr(const char *strpath,struct stat *stbuf) {
230 procfs_path_t path;
231 procfs_parse_path(strpath,&path);
233 memset(stbuf,0,sizeof(struct stat));
235 if (path.file!=NULL) {
236 if (path.file->ftype==PROCFS_DIR) stbuf->st_mode = S_IFDIR;
237 else if (path.file->ftype==PROCFS_SYMLINK) stbuf->st_mode = S_IFLNK;
238 else stbuf->st_mode = S_IFREG;
240 else stbuf->st_mode = S_IFDIR;
242 /// @todo correct permissions
243 stbuf->st_mode |= 0777;
245 return 0;
248 int procfs_init(pid_t *grub_modules) {
249 size_t i;
250 pid_t pid;
252 procfs_processes = llist_create();
254 // put init itself in process list
255 procfs_proc_new(1,"init",NULL);
257 // put GRUB modules in process list
258 for (i=0;(pid = grub_modules[i])!=0;i++) {
259 procfs_proc_new(pid,NULL,NULL);
262 return 0;
265 int procfs_run(void) {
266 // start FUSE
267 struct fuse_operations devfs_oper = {
268 .open = procfs_open,
269 .release = procfs_close,
270 .read = procfs_read,
271 .write = procfs_write,
272 .readdir = procfs_readdir,
273 .getattr = procfs_getattr
276 // fake argc/argv
277 int fake_argc = 2;
278 char *fake_argv[2] = { PROCFS_NAME,PROCFS_MOUNTPOINT };
279 fuse_main(fake_argc,fake_argv,&devfs_oper,NULL);
281 return 0;