Merge branch 'master' of ssh://swildner@crater.dragonflybsd.org/repository/git/dragonfly
[dragonfly.git] / lib / libncp / ncpl_subr.c
blob1550edd6c5f8e50f79e6b5293aad6c8401372526
1 /*
2 * Copyright (c) 1999, Boris Popov
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Boris Popov.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
32 * $FreeBSD: src/lib/libncp/ncpl_subr.c,v 1.3 2000/01/01 14:21:31 bp Exp $
33 * $DragonFly: src/lib/libncp/ncpl_subr.c,v 1.5 2008/09/30 16:57:05 swildner Exp $
36 #include <sys/param.h>
37 #include <sys/types.h>
38 #include <sys/errno.h>
39 #include <sys/sysctl.h>
40 #include <sys/syscall.h>
41 #include <unistd.h>
42 #include <ctype.h>
43 #include <string.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <stdarg.h>
48 #include <netncp/ncp_lib.h>
49 #include <netncp/ncp_rcfile.h>
50 #include <netncp/ncp_nls.h>
51 /*#include <netncp/ncp_cfg.h>*/
52 #include "ncp_mod.h"
54 extern char *__progname;
56 int sysentoffset;
58 void
59 ncp_add_word_lh(struct ncp_buf *conn, u_int16_t x) {
60 setwle(conn->packet, conn->rqsize, x);
61 conn->rqsize += 2;
62 return;
65 void
66 ncp_add_dword_lh(struct ncp_buf *conn, u_int32_t x) {
67 setdle(conn->packet, conn->rqsize, x);
68 conn->rqsize += 4;
69 return;
72 void
73 ncp_add_word_hl(struct ncp_buf *conn, u_int16_t x){
74 setwbe(conn->packet, conn->rqsize, x);
75 conn->rqsize += 2;
76 return;
79 void
80 ncp_add_dword_hl(struct ncp_buf *conn, u_int32_t x) {
81 setdbe(conn->packet, conn->rqsize, x);
82 conn->rqsize += 4;
83 return;
86 void
87 ncp_add_mem(struct ncp_buf *conn, const void *source, int size) {
88 memcpy(conn->packet+conn->rqsize, source, size);
89 conn->rqsize += size;
90 return;
93 void
94 ncp_add_mem_nls(struct ncp_buf *conn, const void *source, int size) {
95 ncp_nls_mem_u2n(conn->packet+conn->rqsize, source, size);
96 conn->rqsize += size;
97 return;
100 void
101 ncp_add_pstring(struct ncp_buf *conn, const char *s) {
102 int len = strlen(s);
103 if (len > 255) {
104 ncp_printf("ncp_add_pstring: string too long: %s\n", s);
105 len = 255;
107 ncp_add_byte(conn, len);
108 ncp_add_mem(conn, s, len);
109 return;
112 void
113 ncp_add_handle_path(struct ncp_buf *conn, nuint32 volNumber, nuint32 dirNumber,
114 int handleFlag, const char *path)
116 ncp_add_byte(conn, volNumber);
117 ncp_add_dword_lh(conn, dirNumber);
118 ncp_add_byte(conn, handleFlag);
119 if (path) {
120 ncp_add_byte(conn, 1); /* 1 component */
121 ncp_add_pstring(conn, path);
122 } else {
123 ncp_add_byte(conn, 0);
127 void
128 ncp_init_request(struct ncp_buf *conn) {
129 conn->rqsize = 0;
130 conn->rpsize = 0;
133 void
134 ncp_init_request_s(struct ncp_buf *conn, int subfn) {
135 ncp_init_request(conn);
136 ncp_add_word_lh(conn, 0);
137 ncp_add_byte(conn, subfn);
140 u_int16_t
141 ncp_reply_word_hl(struct ncp_buf *conn, int offset) {
142 return getwbe(ncp_reply_data(conn, offset), 0);
145 u_int16_t
146 ncp_reply_word_lh(struct ncp_buf *conn, int offset) {
147 return getwle(ncp_reply_data(conn, offset), 0);
150 u_int32_t
151 ncp_reply_dword_hl(struct ncp_buf *conn, int offset) {
152 return getdbe(ncp_reply_data(conn, offset), 0);
155 u_int32_t
156 ncp_reply_dword_lh(struct ncp_buf *conn, int offset) {
157 return getdle(ncp_reply_data(conn, offset), 0);
162 ncp_connect(struct ncp_conn_args *li, int *connHandle) {
163 return syscall(NCP_CONNECT,li,connHandle);
167 ncp_disconnect(int cH) {
168 DECLARE_RQ;
170 ncp_init_request(conn);
171 ncp_add_byte(conn, NCP_CONN_CONNCLOSE);
172 return ncp_conn_request(cH, conn);
176 ncp_request(int connHandle,int function, struct ncp_buf *ncpbuf){
177 int err = syscall(SNCP_REQUEST,connHandle,function,ncpbuf);
178 return (err<0) ? errno : 0;
182 ncp_conn_request(int connHandle, struct ncp_buf *ncpbuf){
183 return syscall(SNCP_REQUEST, connHandle, NCP_CONN, ncpbuf);
187 ncp_conn_scan(struct ncp_conn_loginfo *li, int *connid) {
188 return syscall(NCP_CONNSCAN,li, connid);
191 NWCCODE
192 NWRequest(NWCONN_HANDLE cH, nuint16 fn,
193 nuint16 nrq, NW_FRAGMENT* rq,
194 nuint16 nrp, NW_FRAGMENT* rp)
196 int error;
197 struct ncp_conn_frag nf;
198 DECLARE_RQ;
200 ncp_init_request(conn);
201 ncp_add_byte(conn, NCP_CONN_FRAG);
202 nf.fn = fn;
203 nf.rqfcnt = nrq;
204 nf.rqf = rq;
205 nf.rpf = rp;
206 nf.rpfcnt = nrp;
207 ncp_add_mem(conn, &nf, sizeof(nf));
208 error = ncp_conn_request(cH, conn);
209 return error;
214 ncp_initlib(void){
215 int error;
216 int len = sizeof(sysentoffset);
217 int kv, kvlen = sizeof(kv);
218 static int ncp_initialized;
220 if (ncp_initialized)
221 return 0;
222 error = sysctlbyname("net.ncp.sysent", &sysentoffset, &len, NULL, 0);
223 if (error) {
224 fprintf(stderr, "%s: can't find kernel module\n", __func__);
225 return error;
227 error = sysctlbyname("net.ncp.version", &kv, &kvlen, NULL, 0);
228 if (error) {
229 fprintf(stderr, "%s: kernel module is old, please recompile it.\n", __func__);
230 return error;
232 if (NCP_VERSION != kv) {
233 fprintf(stderr, "%s: kernel module version(%d) don't match library(%d).\n", __func__, kv, NCP_VERSION);
234 return EINVAL;
236 if ((error = ncp_nls_setrecode(0)) != 0) {
237 fprintf(stderr, "%s: can't initialise recode\n", __func__);
238 return error;
240 if ((error = ncp_nls_setlocale("")) != 0) {
241 fprintf(stderr, "%s: can't initialise locale\n", __func__);
242 return error;
244 ncp_initialized++;
245 return 0;
251 int ncp_opterr = 1, /* if error message should be printed */
252 ncp_optind = 1, /* index into parent argv vector */
253 ncp_optopt, /* character checked for validity */
254 ncp_optreset; /* reset getopt */
255 char *ncp_optarg; /* argument associated with option */
257 #define BADCH (int)'?'
258 #define BADARG (int)':'
259 #define EMSG ""
262 ncp_getopt(int nargc, char * const *nargv, const char *ostr)
264 static char *place = EMSG; /* option letter processing */
265 char *oli; /* option letter list index */
266 int tmpind;
268 if (ncp_optreset || !*place) { /* update scanning pointer */
269 ncp_optreset = 0;
270 tmpind = ncp_optind;
271 while (1) {
272 if (tmpind >= nargc) {
273 place = EMSG;
274 return (-1);
276 if (*(place = nargv[tmpind]) != '-') {
277 tmpind++;
278 continue; /* lookup next option */
280 if (place[1] && *++place == '-') { /* found "--" */
281 ncp_optind = ++tmpind;
282 place = EMSG;
283 return (-1);
285 ncp_optind = tmpind;
286 break;
288 } /* option letter okay? */
289 if ((ncp_optopt = (int)*place++) == (int)':' ||
290 !(oli = strchr(ostr, ncp_optopt))) {
292 * if the user didn't specify '-' as an option,
293 * assume it means -1.
295 if (ncp_optopt == (int)'-')
296 return (-1);
297 if (!*place)
298 ++ncp_optind;
299 if (ncp_opterr && *ostr != ':')
300 (void)fprintf(stderr,
301 "%s: illegal option -- %c\n", __progname, ncp_optopt);
302 return (BADCH);
304 if (*++oli != ':') { /* don't need argument */
305 ncp_optarg = NULL;
306 if (!*place)
307 ++ncp_optind;
309 else { /* need an argument */
310 if (*place) /* no white space */
311 ncp_optarg = place;
312 else if (nargc <= ++ncp_optind) { /* no arg */
313 place = EMSG;
314 if (*ostr == ':')
315 return (BADARG);
316 if (ncp_opterr)
317 (void)fprintf(stderr,
318 "%s: option requires an argument -- %c\n",
319 __progname, ncp_optopt);
320 return (BADCH);
322 else /* white space */
323 ncp_optarg = nargv[ncp_optind];
324 place = EMSG;
325 ++ncp_optind;
327 return (ncp_optopt); /* dump back option letter */
330 * misc options parsing routines
333 ncp_args_parserc(struct ncp_args *na, char *sect, ncp_setopt_t *set_callback) {
334 int len, error;
336 for (; na->opt; na++) {
337 switch (na->at) {
338 case NCA_STR:
339 if (rc_getstringptr(ncp_rc,sect,na->name,&na->str) == 0) {
340 len = strlen(na->str);
341 if (len > na->ival) {
342 fprintf(stderr,"rc: Argument for option '%c' (%s) too long\n",na->opt,na->name);
343 return EINVAL;
345 set_callback(na);
347 break;
348 case NCA_BOOL:
349 error = rc_getbool(ncp_rc,sect,na->name,&na->ival);
350 if (error == ENOENT) break;
351 if (error) return EINVAL;
352 set_callback(na);
353 break;
354 case NCA_INT:
355 if (rc_getint(ncp_rc,sect,na->name,&na->ival) == 0) {
356 if (((na->flag & NAFL_HAVEMIN) &&
357 (na->ival < na->min)) ||
358 ((na->flag & NAFL_HAVEMAX) &&
359 (na->ival > na->max))) {
360 fprintf(stderr,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
361 return EINVAL;
363 set_callback(na);
365 break;
366 default:
367 break;
370 return 0;
374 ncp_args_parseopt(struct ncp_args *na, int opt, char *optarg, ncp_setopt_t *set_callback) {
375 int len;
377 for (; na->opt; na++) {
378 if (na->opt != opt) continue;
379 switch (na->at) {
380 case NCA_STR:
381 na->str = optarg;
382 if (optarg) {
383 len = strlen(na->str);
384 if (len > na->ival) {
385 fprintf(stderr,"opt: Argument for option '%c' (%s) too long\n",na->opt,na->name);
386 return EINVAL;
388 set_callback(na);
390 break;
391 case NCA_BOOL:
392 na->ival = 0;
393 set_callback(na);
394 break;
395 case NCA_INT:
396 errno = 0;
397 na->ival = strtol(optarg, NULL, 0);
398 if (errno) {
399 fprintf(stderr,"opt: Invalid integer value for option '%c' (%s).\n",na->opt,na->name);
400 return EINVAL;
402 if (((na->flag & NAFL_HAVEMIN) &&
403 (na->ival < na->min)) ||
404 ((na->flag & NAFL_HAVEMAX) &&
405 (na->ival > na->max))) {
406 fprintf(stderr,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na->opt,na->name,na->min,na->max);
407 return EINVAL;
409 set_callback(na);
410 break;
411 default:
412 break;
414 break;
416 return 0;
420 * Print a (descriptive) error message
421 * error values:
422 * 0 - no specific error code available;
423 * -999..-1 - NDS error
424 * 1..32767 - system error
425 * the rest - requester error;
427 void
428 ncp_error(char *fmt, int error,...) {
429 va_list ap;
431 fprintf(stderr, "%s: ", __progname);
432 va_start(ap, error);
433 vfprintf(stderr, fmt, ap);
434 va_end(ap);
435 if (error == -1)
436 error = errno;
437 if (error > -1000 && error < 0) {
438 fprintf(stderr, ": dserr = %d\n", error);
439 } else if (error & 0x8000) {
440 fprintf(stderr, ": nwerr = %04x\n", error);
441 } else if (error) {
442 fprintf(stderr, ": syserr = %s\n", strerror(error));
443 } else
444 fprintf(stderr, "\n");
447 char *
448 ncp_printb(char *dest, int flags, const struct ncp_bitname *bnp) {
449 int first = 1;
451 strcpy(dest, "<");
452 for(; bnp->bn_bit; bnp++) {
453 if (flags & bnp->bn_bit) {
454 strcat(dest, bnp->bn_name);
455 first = 0;
457 if (!first && (flags & bnp[1].bn_bit))
458 strcat(dest, "|");
460 strcat(dest, ">");
461 return dest;