Tried to fix whole execution system (Shell, Unnamed Pipes)
[meinos.git] / apps / lib / libmeinos / rpc.c
blobed7de82d282941ad25a7bc2baf1c4d75f1dbda26
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 Lesser 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <sys/types.h>
20 #include <syscall.h>
21 #include <errno.h>
22 #include <pack.h>
23 #include <stdarg.h>
24 #include <llist.h>
25 #include <rpc.h>
26 #include <misc.h>
27 #include <dyncall.h>
28 #include <unistd.h>
30 int rpc_func_create(const char *name,void *func,const char *synopsis,size_t paramsz) {
31 int ret = syscall_call(SYSCALL_RPC_CREATE,4,name,func,synopsis,paramsz);
32 errno = ret<0?-ret:0;
33 return ret<0?-1:ret;
36 int rpc_func_destroy(int id) {
37 int ret = syscall_call(SYSCALL_RPC_DESTROY,1,id);
38 errno = ret<0?-ret:0;
39 return ret<0?-1:ret;
42 int rpc_vcall(const char *name,int ret_params,va_list args) {
43 int ret,id,error;
44 char synopsis[RPC_SYNOPSIS_MAXLEN];
45 size_t paramsz,i;
46 pack_t params;
48 id = syscall_call(SYSCALL_RPC_GETINFO,8,-1,name,0,0,&paramsz,synopsis,RPC_SYNOPSIS_MAXLEN,0);
49 if (id>=0) {
50 // pack parameters
51 params = pack_malloc(paramsz);
52 int *param_list = malloc(strlen(synopsis)*sizeof(int));
53 for (i=0;synopsis[i];i++) {
54 param_list[i] = va_arg(args,int);
55 if (synopsis[i]=='b') pack8(params,param_list[i]);
56 else if (synopsis[i]=='w') pack16(params,param_list[i]);
57 else if (synopsis[i]=='d') pack32(params,param_list[i]);
58 else if (synopsis[i]=='c') packc(params,param_list[i]);
59 else if (synopsis[i]=='s') packs(params,param_list[i]);
60 else if (synopsis[i]=='i') packi(params,param_list[i]);
61 else if (synopsis[i]=='l') packl(params,param_list[i]);
62 else if (synopsis[i]=='$') packstr(params,(const char*)param_list[i]);
65 // call function
66 if (syscall_call(SYSCALL_RPC_CALL,5,id,pack_data(params),&ret,ret_params?pack_data(params):NULL,&error)==0) error = 1;
68 if (error==0 || 1) { /// @todo fix error detection
69 if (ret_params) {
70 pack_reset(params);
71 for (i=0;synopsis[i];i++) {
72 int null;
73 char *str;
74 if (synopsis[i]=='b') unpack8(params,&null);
75 else if (synopsis[i]=='w') unpack16(params,&null);
76 else if (synopsis[i]=='d') unpack32(params,&null);
77 else if (synopsis[i]=='c') unpackc(params,&null);
78 else if (synopsis[i]=='s') unpacks(params,&null);
79 else if (synopsis[i]=='i') unpacki(params,&null);
80 else if (synopsis[i]=='l') unpackl(params,&null);
81 else if (synopsis[i]=='$') {
82 unpackstr(params,&str);
83 strncpy((char*)param_list[i],str,strlen((char*)param_list[i])+1);
87 errno = 0;
90 free(param_list);
91 pack_free(params);
92 return ret;
94 else pack_free(params);
96 errno = EINVAL;
97 return -1;
100 int rpc_call(const char *name,int ret_params,...) {
101 va_list args;
102 va_start(args,ret_params);
103 int ret = rpc_vcall(name,ret_params,args);
104 va_end(args);
105 return ret;
108 int rpc_vcallself(const char *name,void *func,int ret_params,va_list args) {
109 char synopsis[RPC_SYNOPSIS_MAXLEN];
110 int id = syscall_call(SYSCALL_RPC_GETINFO,8,-1,name,getpid(),0,NULL,synopsis,RPC_SYNOPSIS_MAXLEN,1);
111 if (id>=0) {
112 int ret;
113 size_t num_params = strlen(synopsis);
114 size_t i;
115 int *param_list = malloc(num_params*sizeof(int));
116 for (i=0;i<num_params;i++) param_list[i] = va_arg(args,int);
118 ret = dyn_call(func,param_list,num_params);
120 free(param_list);
121 return ret;
123 else return -1;
126 int rpc_callself(const char *name,void *func,int ret_params,...) {
127 va_list args;
128 va_start(args,ret_params);
129 int ret = rpc_vcallself(name,func,ret_params,args);
130 va_end(args);
131 return ret;
134 int rpc_poll(int id) {
135 size_t paramsz,num_params;
136 char synopsis[RPC_SYNOPSIS_MAXLEN];
137 pack_t params;
138 int (*func)(void);
139 int ret;
141 id = syscall_call(SYSCALL_RPC_GETINFO,8,id,NULL,getpid(),1,&paramsz,synopsis,RPC_SYNOPSIS_MAXLEN,1);
142 if (id>=0) {
143 num_params = strlen(synopsis);
144 params = pack_malloc(paramsz);
145 if (syscall_call(SYSCALL_RPC_POLL,4,id,&func,pack_data(params),&rpc_curpid)==0) {
146 int *param_list = malloc(num_params*sizeof(int));
147 size_t i;
148 for (i=0;i<num_params;i++) {
149 if (synopsis[i]=='b') unpack8(params,param_list+i);
150 else if (synopsis[i]=='w') unpack16(params,param_list+i);
151 else if (synopsis[i]=='d') unpack32(params,param_list+i);
152 else if (synopsis[i]=='c') unpackc(params,param_list+i);
153 else if (synopsis[i]=='s') unpacks(params,param_list+i);
154 else if (synopsis[i]=='i') unpacki(params,param_list+i);
155 else if (synopsis[i]=='l') unpackl(params,param_list+i);
156 else if (synopsis[i]=='$') unpackstr(params,(char**)param_list+i);
159 ret = dyn_call(func,param_list,num_params);
161 free(param_list);
163 if (syscall_call(SYSCALL_RPC_RETURN,3,id,ret,pack_data(params))==0) {
164 errno = 0;
165 return 0;
169 errno = EINVAL;
170 return -1;
173 int rpc_mainloop(int id) {
174 init_ready();
175 while (1) rpc_poll(id);
178 llist_t rpc_list() {
179 llist_t list = llist_create();
180 size_t i;
181 for (i=0;;i++) {
182 size_t size = syscall_call(SYSCALL_RPC_LIST,3,i,NULL,0);
183 if (size==0) break;
184 char *buf = malloc(size);
185 syscall_call(SYSCALL_RPC_LIST,3,i,buf,size);
186 llist_push(list,buf);
188 return list;