2 * Copyright (c) 1999, Boris Popov
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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
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.4 2005/02/17 13:59:35 joerg 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>
48 #include <netncp/ncp_lib.h>
49 #include <netncp/ncp_rcfile.h>
50 #include <netncp/ncp_nls.h>
51 /*#include <netncp/ncp_cfg.h>*/
54 extern char *__progname
;
59 ncp_add_word_lh(struct ncp_buf
*conn
, u_int16_t x
) {
60 setwle(conn
->packet
, conn
->rqsize
, x
);
66 ncp_add_dword_lh(struct ncp_buf
*conn
, u_int32_t x
) {
67 setdle(conn
->packet
, conn
->rqsize
, x
);
73 ncp_add_word_hl(struct ncp_buf
*conn
, u_int16_t x
){
74 setwbe(conn
->packet
, conn
->rqsize
, x
);
80 ncp_add_dword_hl(struct ncp_buf
*conn
, u_int32_t x
) {
81 setdbe(conn
->packet
, conn
->rqsize
, x
);
87 ncp_add_mem(struct ncp_buf
*conn
, const void *source
, int size
) {
88 memcpy(conn
->packet
+conn
->rqsize
, source
, size
);
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
);
101 ncp_add_pstring(struct ncp_buf
*conn
, const char *s
) {
104 ncp_printf("ncp_add_pstring: string too long: %s\n", s
);
107 ncp_add_byte(conn
, len
);
108 ncp_add_mem(conn
, s
, len
);
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
);
120 ncp_add_byte(conn
, 1); /* 1 component */
121 ncp_add_pstring(conn
, path
);
123 ncp_add_byte(conn
, 0);
128 ncp_init_request(struct ncp_buf
*conn
) {
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
);
141 ncp_reply_word_hl(struct ncp_buf
*conn
, int offset
) {
142 return getwbe(ncp_reply_data(conn
, offset
), 0);
146 ncp_reply_word_lh(struct ncp_buf
*conn
, int offset
) {
147 return getwle(ncp_reply_data(conn
, offset
), 0);
151 ncp_reply_dword_hl(struct ncp_buf
*conn
, int offset
) {
152 return getdbe(ncp_reply_data(conn
, offset
), 0);
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
) {
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
);
192 NWRequest(NWCONN_HANDLE cH
, nuint16 fn
,
193 nuint16 nrq
, NW_FRAGMENT
* rq
,
194 nuint16 nrp
, NW_FRAGMENT
* rp
)
197 struct ncp_conn_frag nf
;
200 ncp_init_request(conn
);
201 ncp_add_byte(conn
, NCP_CONN_FRAG
);
207 ncp_add_mem(conn
, &nf
, sizeof(nf
));
208 error
= ncp_conn_request(cH
, conn
);
216 int len
= sizeof(sysentoffset
);
217 int kv
, kvlen
= sizeof(kv
);
218 static int ncp_initialized
;
222 error
= sysctlbyname("net.ncp.sysent", &sysentoffset
, &len
, NULL
, 0);
224 fprintf(stderr
, "%s: can't find kernel module\n", __func__
);
227 error
= sysctlbyname("net.ncp.version", &kv
, &kvlen
, NULL
, 0);
229 fprintf(stderr
, "%s: kernel module is old, please recompile it.\n", __func__
);
232 if (NCP_VERSION
!= kv
) {
233 fprintf(stderr
, "%s: kernel module version(%d) don't match library(%d).\n", __func__
, kv
, NCP_VERSION
);
236 if ((error
= ncp_nls_setrecode(0)) != 0) {
237 fprintf(stderr
, "%s: can't initialise recode\n", __func__
);
240 if ((error
= ncp_nls_setlocale("")) != 0) {
241 fprintf(stderr
, "%s: can't initialise locale\n", __func__
);
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)':'
262 ncp_getopt(nargc
, nargv
, ostr
)
267 static char *place
= EMSG
; /* option letter processing */
268 char *oli
; /* option letter list index */
271 if (ncp_optreset
|| !*place
) { /* update scanning pointer */
275 if (tmpind
>= nargc
) {
279 if (*(place
= nargv
[tmpind
]) != '-') {
281 continue; /* lookup next option */
283 if (place
[1] && *++place
== '-') { /* found "--" */
284 ncp_optind
= ++tmpind
;
291 } /* option letter okay? */
292 if ((ncp_optopt
= (int)*place
++) == (int)':' ||
293 !(oli
= strchr(ostr
, ncp_optopt
))) {
295 * if the user didn't specify '-' as an option,
296 * assume it means -1.
298 if (ncp_optopt
== (int)'-')
302 if (ncp_opterr
&& *ostr
!= ':')
303 (void)fprintf(stderr
,
304 "%s: illegal option -- %c\n", __progname
, ncp_optopt
);
307 if (*++oli
!= ':') { /* don't need argument */
312 else { /* need an argument */
313 if (*place
) /* no white space */
315 else if (nargc
<= ++ncp_optind
) { /* no arg */
320 (void)fprintf(stderr
,
321 "%s: option requires an argument -- %c\n",
322 __progname
, ncp_optopt
);
325 else /* white space */
326 ncp_optarg
= nargv
[ncp_optind
];
330 return (ncp_optopt
); /* dump back option letter */
333 * misc options parsing routines
336 ncp_args_parserc(struct ncp_args
*na
, char *sect
, ncp_setopt_t
*set_callback
) {
339 for (; na
->opt
; na
++) {
342 if (rc_getstringptr(ncp_rc
,sect
,na
->name
,&na
->str
) == 0) {
343 len
= strlen(na
->str
);
344 if (len
> na
->ival
) {
345 fprintf(stderr
,"rc: Argument for option '%c' (%s) too long\n",na
->opt
,na
->name
);
352 error
= rc_getbool(ncp_rc
,sect
,na
->name
,&na
->ival
);
353 if (error
== ENOENT
) break;
354 if (error
) return EINVAL
;
358 if (rc_getint(ncp_rc
,sect
,na
->name
,&na
->ival
) == 0) {
359 if (((na
->flag
& NAFL_HAVEMIN
) &&
360 (na
->ival
< na
->min
)) ||
361 ((na
->flag
& NAFL_HAVEMAX
) &&
362 (na
->ival
> na
->max
))) {
363 fprintf(stderr
,"rc: Argument for option '%c' (%s) should be in [%d-%d] range\n",na
->opt
,na
->name
,na
->min
,na
->max
);
377 ncp_args_parseopt(struct ncp_args
*na
, int opt
, char *optarg
, ncp_setopt_t
*set_callback
) {
380 for (; na
->opt
; na
++) {
381 if (na
->opt
!= opt
) continue;
386 len
= strlen(na
->str
);
387 if (len
> na
->ival
) {
388 fprintf(stderr
,"opt: Argument for option '%c' (%s) too long\n",na
->opt
,na
->name
);
400 na
->ival
= strtol(optarg
, NULL
, 0);
402 fprintf(stderr
,"opt: Invalid integer value for option '%c' (%s).\n",na
->opt
,na
->name
);
405 if (((na
->flag
& NAFL_HAVEMIN
) &&
406 (na
->ival
< na
->min
)) ||
407 ((na
->flag
& NAFL_HAVEMAX
) &&
408 (na
->ival
> na
->max
))) {
409 fprintf(stderr
,"opt: Argument for option '%c' (%s) should be in [%d-%d] range\n",na
->opt
,na
->name
,na
->min
,na
->max
);
423 * Print a (descriptive) error message
425 * 0 - no specific error code available;
426 * -999..-1 - NDS error
427 * 1..32767 - system error
428 * the rest - requester error;
431 ncp_error(char *fmt
, int error
,...) {
434 fprintf(stderr
, "%s: ", __progname
);
436 vfprintf(stderr
, fmt
, ap
);
440 if (error
> -1000 && error
< 0) {
441 fprintf(stderr
, ": dserr = %d\n", error
);
442 } else if (error
& 0x8000) {
443 fprintf(stderr
, ": nwerr = %04x\n", error
);
445 fprintf(stderr
, ": syserr = %s\n", strerror(error
));
447 fprintf(stderr
, "\n");
451 ncp_printb(char *dest
, int flags
, const struct ncp_bitname
*bnp
) {
455 for(; bnp
->bn_bit
; bnp
++) {
456 if (flags
& bnp
->bn_bit
) {
457 strcat(dest
, bnp
->bn_name
);
460 if (!first
&& (flags
& bnp
[1].bn_bit
))