00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <stdio.h>
00030 #include <bool.h>
00031 #include <async.h>
00032 #include <ipc/ns.h>
00033 #include <ipc/services.h>
00034 #include <ipc/clipboard.h>
00035 #include <malloc.h>
00036 #include <fibril_synch.h>
00037 #include <errno.h>
00038
00039 #define NAME "clip"
00040
00041 static char *clip_data = NULL;
00042 static size_t clip_size = 0;
00043 static clipboard_tag_t clip_tag = CLIPBOARD_TAG_NONE;
00044 static FIBRIL_MUTEX_INITIALIZE(clip_mtx);
00045
00046 static void clip_put_data(ipc_callid_t rid, ipc_call_t *request)
00047 {
00048 char *data;
00049 int rc;
00050 size_t size;
00051
00052 switch (IPC_GET_ARG1(*request)) {
00053 case CLIPBOARD_TAG_NONE:
00054 fibril_mutex_lock(&clip_mtx);
00055
00056 if (clip_data)
00057 free(clip_data);
00058
00059 clip_data = NULL;
00060 clip_size = 0;
00061 clip_tag = CLIPBOARD_TAG_NONE;
00062
00063 fibril_mutex_unlock(&clip_mtx);
00064 async_answer_0(rid, EOK);
00065 break;
00066 case CLIPBOARD_TAG_DATA:
00067 rc = async_data_write_accept((void **) &data, false, 0, 0, 0, &size);
00068 if (rc != EOK) {
00069 async_answer_0(rid, rc);
00070 break;
00071 }
00072
00073 fibril_mutex_lock(&clip_mtx);
00074
00075 if (clip_data)
00076 free(clip_data);
00077
00078 clip_data = data;
00079 clip_size = size;
00080 clip_tag = CLIPBOARD_TAG_DATA;
00081
00082 fibril_mutex_unlock(&clip_mtx);
00083 async_answer_0(rid, EOK);
00084 break;
00085 default:
00086 async_answer_0(rid, EINVAL);
00087 }
00088 }
00089
00090 static void clip_get_data(ipc_callid_t rid, ipc_call_t *request)
00091 {
00092 fibril_mutex_lock(&clip_mtx);
00093
00094 ipc_callid_t callid;
00095 size_t size;
00096
00097
00098 switch (IPC_GET_ARG1(*request)) {
00099 case CLIPBOARD_TAG_DATA:
00100 if (!async_data_read_receive(&callid, &size)) {
00101 async_answer_0(callid, EINVAL);
00102 async_answer_0(rid, EINVAL);
00103 break;
00104 }
00105
00106 if (clip_tag != CLIPBOARD_TAG_DATA) {
00107
00108 async_answer_0(callid, EOVERFLOW);
00109 async_answer_0(rid, EOVERFLOW);
00110 break;
00111 }
00112
00113 if (clip_size != size) {
00114
00115 async_answer_0(callid, EOVERFLOW);
00116 async_answer_0(rid, EOVERFLOW);
00117 break;
00118 }
00119
00120 sysarg_t retval = async_data_read_finalize(callid, clip_data, size);
00121 if (retval != EOK) {
00122 async_answer_0(rid, retval);
00123 break;
00124 }
00125
00126 async_answer_0(rid, EOK);
00127 default:
00128
00129
00130
00131
00132 async_answer_0(rid, EINVAL);
00133 break;
00134 }
00135
00136 fibril_mutex_unlock(&clip_mtx);
00137 }
00138
00139 static void clip_content(ipc_callid_t rid, ipc_call_t *request)
00140 {
00141 fibril_mutex_lock(&clip_mtx);
00142
00143 size_t size = clip_size;
00144 clipboard_tag_t tag = clip_tag;
00145
00146 fibril_mutex_unlock(&clip_mtx);
00147 async_answer_2(rid, EOK, (sysarg_t) size, (sysarg_t) tag);
00148 }
00149
00150 static void clip_connection(ipc_callid_t iid, ipc_call_t *icall)
00151 {
00152
00153 async_answer_0(iid, EOK);
00154
00155 bool cont = true;
00156 while (cont) {
00157 ipc_call_t call;
00158 ipc_callid_t callid = async_get_call(&call);
00159
00160 switch (IPC_GET_IMETHOD(call)) {
00161 case IPC_M_PHONE_HUNGUP:
00162 cont = false;
00163 continue;
00164 case CLIPBOARD_PUT_DATA:
00165 clip_put_data(callid, &call);
00166 break;
00167 case CLIPBOARD_GET_DATA:
00168 clip_get_data(callid, &call);
00169 break;
00170 case CLIPBOARD_CONTENT:
00171 clip_content(callid, &call);
00172 break;
00173 default:
00174 async_answer_0(callid, ENOENT);
00175 }
00176 }
00177 }
00178
00179 int main(int argc, char *argv[])
00180 {
00181 printf(NAME ": HelenOS clipboard service\n");
00182
00183 async_set_client_connection(clip_connection);
00184
00185 if (service_register(SERVICE_CLIPBOARD) != EOK)
00186 return -1;
00187
00188 printf(NAME ": Accepting connections\n");
00189 async_manager();
00190
00191
00192 return 0;
00193 }