Check-in [cc9b79793c]
Overview
Comment:First half of renaming
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: cc9b79793cc29fa3915452e50ab6763fcf1b4e7c
User & Date: rkeene on 2014-10-24 20:12:14
Other Links: manifest | tags
Context
2014-10-24
20:13
Completed rename check-in: 5d8baf9914 user: rkeene tags: trunk
20:12
First half of renaming check-in: cc9b79793c user: rkeene tags: trunk
2012-09-17
13:36
Updated to return correct value from close handler check-in: 6ad41a2c2b user: rkeene tags: trunk
Changes

Added .fossil-settings/ignore-glob version [8823994c8d].











>
>
>
>
>
1
2
3
4
5
tuapi.so
libtuapi.a
tuapi.o
tuapi.tcl.h
pkgIndex.tcl

Modified build-common.sh from [1b93b7f590] to [4e129d0a2f].

1
2
3
4
5
6
7
8
9
10
11
12
13


14
#! /bin/bash

set -e

case "$1" in
	clean|distclean)
		rm -rf out inst
		rm -f libsystem.a system.o system.so
		rm -f system.tcl.h
		exit 0
		;;
esac



./stringify.tcl system.tcl > system.tcl.h







|
|




>
>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#! /bin/bash

set -e

case "$1" in
	clean|distclean)
		rm -rf out inst
		rm -f libtuapi.a tuapi.o tuapi.so
		rm -f tuapi.tcl.h
		exit 0
		;;
esac

tuapi_version="$(grep Tcl_PkgProvide system.c | awk '{ print $3 }' | sed 's@[");]*@@g')"

./stringify.tcl system.tcl > tuapi.tcl.h

Modified build-dyn.sh from [3cc9484186] to [68b9f210b2].

1
2
3
4
5
6
7
8
9
10
11
12


# /bin/bash

# Perform common build options
. build-common.sh

# Compile using the same options as Tcl
TCLCONFIGSH="$(find /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 /lib /lib64 -name tclConfig.sh -print -quit)"

. "${TCLCONFIGSH}"

echo "${TCL_CC} -ggdb3 -fPIC -DPIC -Wall -DUSE_TCL_STUBS=1 ${TCL_DEFS} ${TCL_INCLUDE_SPEC} ${TCL_STUB_LIB_SPEC} -shared -rdynamic -o system.so system.c"
eval ${TCL_CC} -ggdb3 -fPIC -DPIC -Wall -DUSE_TCL_STUBS=1 ${TCL_DEFS} ${TCL_INCLUDE_SPEC} ${TCL_STUB_LIB_SPEC} -shared -rdynamic -o system.so system.c












|
|
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# /bin/bash

# Perform common build options
. build-common.sh

# Compile using the same options as Tcl
TCLCONFIGSH="$(find /usr/lib /usr/lib64 /usr/local/lib /usr/local/lib64 /lib /lib64 -name tclConfig.sh -print -quit)"

. "${TCLCONFIGSH}"

echo "${TCL_CC} -ggdb3 -fPIC -DPIC -Wall -DUSE_TCL_STUBS=1 ${TCL_DEFS} ${TCL_INCLUDE_SPEC} ${TCL_STUB_LIB_SPEC} -shared -rdynamic -o tuapi.so system.c"
eval ${TCL_CC} -ggdb3 -fPIC -DPIC -Wall -DUSE_TCL_STUBS=1 ${TCL_DEFS} ${TCL_INCLUDE_SPEC} ${TCL_STUB_LIB_SPEC} -shared -rdynamic -o tuapi.so system.c

echo 'package ifneeded tuapi '"${tuapi_version}"' [list load [file join $dir tuapi.so]]' > pkgIndex.tcl

Modified build-static.sh from [a001c327e9] to [8d87567e49].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

#! /bin/bash

# Perform common build options
. build-common.sh

# Define variables
KITCREATORROOT="$(readlink -f '..')"

# Compile using the same options as Tcl
TCLCONFIGSH='/usr/lib/tclConfig.sh'

. "${TCLCONFIGSH}"

echo "diet ${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o system.o -c system.c"
eval diet ${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o system.o -c system.c
ar rcu libsystem.a system.o
ranlib libsystem.a










|



|
|
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#! /bin/bash

# Perform common build options
. build-common.sh

# Define variables
KITCREATORROOT="$(readlink -f '..')"

# Compile using the same options as Tcl
TCLCONFIGSH='/usr/lib64/tclConfig.sh'

. "${TCLCONFIGSH}"

echo "${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o tuapi.o -c system.c"
eval ${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o tuapi.o -c system.c
ar rcu libtuapi.a tuapi.o
ranlib libtuapi.a
echo 'package ifneeded tuapi '"${tuapi_version}"' [list load {} tuapi]' > pkgIndex.tcl

Modified build.sh from [ad274edd90] to [a96c51243e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


19
20
21
22
#! /bin/bash

# Perform common build options
. build-common.sh

# Define variables
KITCREATORROOT="$(readlink -f '..')"

# Compile using the same options as Tcl
TCLCONFIGSH="${KITCREATORROOT}/tcl/inst/lib/tclConfig.sh"

. "${TCLCONFIGSH}"

echo "${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o system.o -c system.c"
eval ${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o system.o -c system.c
ar rcu libsystem.a system.o
ranlib libsystem.a



mkdir -p inst/lib/system1.0
mkdir -p out/lib/system1.0
cp libsystem.a inst/lib/system1.0
cp pkgIndex.tcl out/lib/system1.0













|
|
|
|

>
>
|
|
|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#! /bin/bash

# Perform common build options
. build-common.sh

# Define variables
KITCREATORROOT="$(readlink -f '..')"

# Compile using the same options as Tcl
TCLCONFIGSH="${KITCREATORROOT}/tcl/inst/lib/tclConfig.sh"

. "${TCLCONFIGSH}"

echo "${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o tuapi.o -c system.c"
eval ${TCL_CC} ${TCL_DEFS} ${TCL_INCLUDE_SPEC} -o tuapi.o -c system.c
ar rcu libtuapi.a tuapi.o
ranlib libtuapi.a

echo 'package ifneeded tuapi '"${tuapi_version}"' [list load {} tuapi]' > pkgIndex.tcl

mkdir -p inst/lib/tuapi-0.1
mkdir -p out/lib/tuapi-0.1
cp libtuapi.a inst/lib/tuapi-0.1
cp pkgIndex.tcl out/lib/tuapi-0.1

Deleted pkgIndex.tcl version [1495e7ac95].

1
package ifneeded system 0.1 [list load "" system]
<


Modified system.c from [1a6534ed63] to [1dceb1e290].

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
	return(syscall(SYS_pivot_root, new_root, put_old));
}
#endif

/*
 * Simple hash routine to enable switching on a string to be implemented
 */
static unsigned long tclsystem_internal_simplehash(const void *databuf, int datalen) {
	unsigned long retval = 0;
	const unsigned char *data;

	data = databuf;

	for (; datalen > 0; datalen--,data++) {
		retval ^= (retval >> 25) & 0x7F;
		retval <<= 7;
		retval &= (0xFFFFFFFFUL);
		retval ^= *data;
	}

	return(retval);
}

static unsigned long tclsystem_internal_simplehash_obj(Tcl_Obj *tcl_data) {
	unsigned long retval;
	char *data;
	int datalen = -1;

	data = Tcl_GetStringFromObj(tcl_data, &datalen);

	retval = tclsystem_internal_simplehash(data, datalen);

	return(retval);
}

#if 0
/* NOTUSED: Uncomment when needed: */
static unsigned long tclsystem_internal_simplehash_str(const char *data) {
	unsigned long retval;
	int datalen;

	datalen = strlen(data);

	retval = tclsystem_internal_simplehash(data, datalen);

	return(retval);
}
#endif

static int tclsystem_internalproc_simplehash(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	unsigned long hashval;
	Tcl_Obj *hashval_obj;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::internal::hash value\"", -1));

		return(TCL_ERROR);
	}

	hashval = tclsystem_internal_simplehash_obj(objv[1]);

	hashval_obj = Tcl_NewObj();
	Tcl_SetWideIntObj(hashval_obj, hashval);

	Tcl_SetObjResult(interp, hashval_obj);

	return(TCL_OK);
}

static int tclsystem_internal_getsock(int *sock_v4_out, int *sock_v6_out) {
	int sock_v4 = -1, sock_v6 = -1;
	int sock;

	if (sock_v4_out == NULL && sock_v6_out == NULL) {
		return(-1);
	}








|















|






|






|





|





|




|




|









|







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
	return(syscall(SYS_pivot_root, new_root, put_old));
}
#endif

/*
 * Simple hash routine to enable switching on a string to be implemented
 */
static unsigned long tuapi_internal_simplehash(const void *databuf, int datalen) {
	unsigned long retval = 0;
	const unsigned char *data;

	data = databuf;

	for (; datalen > 0; datalen--,data++) {
		retval ^= (retval >> 25) & 0x7F;
		retval <<= 7;
		retval &= (0xFFFFFFFFUL);
		retval ^= *data;
	}

	return(retval);
}

static unsigned long tuapi_internal_simplehash_obj(Tcl_Obj *tcl_data) {
	unsigned long retval;
	char *data;
	int datalen = -1;

	data = Tcl_GetStringFromObj(tcl_data, &datalen);

	retval = tuapi_internal_simplehash(data, datalen);

	return(retval);
}

#if 0
/* NOTUSED: Uncomment when needed: */
static unsigned long tuapi_internal_simplehash_str(const char *data) {
	unsigned long retval;
	int datalen;

	datalen = strlen(data);

	retval = tuapi_internal_simplehash(data, datalen);

	return(retval);
}
#endif

static int tuapi_internalproc_simplehash(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	unsigned long hashval;
	Tcl_Obj *hashval_obj;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::internal::hash value\"", -1));

		return(TCL_ERROR);
	}

	hashval = tuapi_internal_simplehash_obj(objv[1]);

	hashval_obj = Tcl_NewObj();
	Tcl_SetWideIntObj(hashval_obj, hashval);

	Tcl_SetObjResult(interp, hashval_obj);

	return(TCL_OK);
}

static int tuapi_internal_getsock(int *sock_v4_out, int *sock_v6_out) {
	int sock_v4 = -1, sock_v6 = -1;
	int sock;

	if (sock_v4_out == NULL && sock_v6_out == NULL) {
		return(-1);
	}

181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Low-level System Call Wrapper Procedures
 *
 * These procedures should minimally wrap Linux or UNIX system calls to
 * expose to the Tcl-level.  Where possible accept symbolic names rather
 * than numeric values (.e.g, list of values to OR together to get flags).
 */
static int tclsystem_mount(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *mountflags_obj, **mountflags_list, *mountflag;
	int mountflags_list_len;
	char *source, *target, *fstype;
	unsigned long mountflags = 0;
	void *data = NULL;
	int mount_ret, tcl_ret;

	if (objc < 5 || objc > 6) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::mount source target fstype mountflags ?data?\"", -1));

		return(TCL_ERROR);
	}

	source = Tcl_GetString(objv[1]);
	target = Tcl_GetString(objv[2]);
	fstype = Tcl_GetString(objv[3]);







|








|







181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/*
 * Low-level System Call Wrapper Procedures
 *
 * These procedures should minimally wrap Linux or UNIX system calls to
 * expose to the Tcl-level.  Where possible accept symbolic names rather
 * than numeric values (.e.g, list of values to OR together to get flags).
 */
static int tuapi_mount(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *mountflags_obj, **mountflags_list, *mountflag;
	int mountflags_list_len;
	char *source, *target, *fstype;
	unsigned long mountflags = 0;
	void *data = NULL;
	int mount_ret, tcl_ret;

	if (objc < 5 || objc > 6) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::mount source target fstype mountflags ?data?\"", -1));

		return(TCL_ERROR);
	}

	source = Tcl_GetString(objv[1]);
	target = Tcl_GetString(objv[2]);
	fstype = Tcl_GetString(objv[3]);
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
	if (tcl_ret != TCL_OK) {
		return(tcl_ret);
	}

	for (; mountflags_list_len > 0; mountflags_list_len--,mountflags_list++) {
		mountflag = mountflags_list[0];

		switch (tclsystem_internal_simplehash_obj(mountflag)) {
#ifdef MS_BIND
			case 0x8526744: /* BIND */
				mountflags |= MS_BIND;
				break;
#endif
#ifdef MS_DIRSYNC
			case 0x2aff41c3: /* DIRSYNC */







|







212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
	if (tcl_ret != TCL_OK) {
		return(tcl_ret);
	}

	for (; mountflags_list_len > 0; mountflags_list_len--,mountflags_list++) {
		mountflag = mountflags_list[0];

		switch (tuapi_internal_simplehash_obj(mountflag)) {
#ifdef MS_BIND
			case 0x8526744: /* BIND */
				mountflags |= MS_BIND;
				break;
#endif
#ifdef MS_DIRSYNC
			case 0x2aff41c3: /* DIRSYNC */
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj(target, -1));

	return(TCL_OK);
}

static int tclsystem_umount(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj **flags, *flag;
	Tcl_Obj *pathname_obj;
	char *pathname;
	int umount2_flags = 0;
	int flags_cnt;
	int chk_ret, tcl_ret;

	if (objc < 2 || objc > 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"system::syscall::umount dir ?flags?\"", -1));

		return(TCL_ERROR);
	}

	pathname_obj = objv[1];
	pathname = Tcl_GetString(pathname_obj);

	/* Set a default return value */
	Tcl_SetObjResult(interp, pathname_obj);

	if (objc == 3) {
		tcl_ret = Tcl_ListObjGetElements(interp, objv[2], &flags_cnt, &flags);
		if (tcl_ret != TCL_OK) {
			return(tcl_ret);
		}

		for (; flags_cnt > 0; flags_cnt--,flags++) {
			flag = flags[0];

			switch (tclsystem_internal_simplehash_obj(flag)) {
				case 0x69f4a3c5: /* FORCE */
					umount2_flags |= MNT_FORCE;

					break;
				case 0x5a9173c8: /* DETACH */
					umount2_flags |= MNT_DETACH;








|








|



















|







308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj(target, -1));

	return(TCL_OK);
}

static int tuapi_umount(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj **flags, *flag;
	Tcl_Obj *pathname_obj;
	char *pathname;
	int umount2_flags = 0;
	int flags_cnt;
	int chk_ret, tcl_ret;

	if (objc < 2 || objc > 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"tuapi::syscall::umount dir ?flags?\"", -1));

		return(TCL_ERROR);
	}

	pathname_obj = objv[1];
	pathname = Tcl_GetString(pathname_obj);

	/* Set a default return value */
	Tcl_SetObjResult(interp, pathname_obj);

	if (objc == 3) {
		tcl_ret = Tcl_ListObjGetElements(interp, objv[2], &flags_cnt, &flags);
		if (tcl_ret != TCL_OK) {
			return(tcl_ret);
		}

		for (; flags_cnt > 0; flags_cnt--,flags++) {
			flag = flags[0];

			switch (tuapi_internal_simplehash_obj(flag)) {
				case 0x69f4a3c5: /* FORCE */
					umount2_flags |= MNT_FORCE;

					break;
				case 0x5a9173c8: /* DETACH */
					umount2_flags |= MNT_DETACH;

378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_swapon(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"system::syscall::swapon pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = swapon(pathname, 0);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_swapoff(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"system::syscall::swapoff pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = swapoff(pathname);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_insmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Channel fd;
	Tcl_Obj *module_filename, *module_data;
	void *module_data_val;
	int module_data_len;
	int read_ret, chk_ret;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"system::syscall::insmod filename ?args ...?\"", -1));

		return(TCL_ERROR);
	}

	module_filename = objv[1];

	fd = Tcl_FSOpenFileChannel(interp, module_filename, "r", 0600);







|




|
















|




|
















|







|







378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_swapon(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"tuapi::syscall::swapon pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = swapon(pathname, 0);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_swapoff(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"tuapi::syscall::swapoff pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = swapoff(pathname);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_insmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Channel fd;
	Tcl_Obj *module_filename, *module_data;
	void *module_data_val;
	int module_data_len;
	int read_ret, chk_ret;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"tuapi::syscall::insmod filename ?args ...?\"", -1));

		return(TCL_ERROR);
	}

	module_filename = objv[1];

	fd = Tcl_FSOpenFileChannel(interp, module_filename, "r", 0600);
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_rmmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_lsmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_hostname(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char hostname[HOST_NAME_MAX + 1];
	int chk_ret;

	if (objc == 1) {
		/* No arguments given, just return the hostname */
		chk_ret = gethostname(hostname, sizeof(hostname));
		if (chk_ret != 0) {







|





|





|







473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_rmmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_lsmod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_hostname(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char hostname[HOST_NAME_MAX + 1];
	int chk_ret;

	if (objc == 1) {
		/* No arguments given, just return the hostname */
		chk_ret = gethostname(hostname, sizeof(hostname));
		if (chk_ret != 0) {
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"hostname ?hostname?\"", -1));

	return(TCL_ERROR);
}

static int tclsystem_domainname(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_chroot(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall:chroot pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = chroot(pathname);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_pivot_root(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *new_root, *put_old;
	int chk_ret;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::pivot_root new_root put_old\"", -1));

		return(TCL_ERROR);
	}

	new_root = Tcl_GetString(objv[1]);
	put_old = Tcl_GetString(objv[2]);

	chk_ret = pivot_root(new_root, put_old);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_mknod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_getuid(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_kill(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *signal_obj;

	Tcl_WideInt pid_wide, sig_wide;
	pid_t pid;
	int sig;
	int kill_ret, tcl_ret;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::kill pid sig\"", -1));

		return(TCL_ERROR);
	}

	tcl_ret = Tcl_GetWideIntFromObj(interp, objv[1], &pid_wide);
	if (tcl_ret != TCL_OK) {
		return(tcl_ret);
	}
	pid = pid_wide;

	signal_obj = objv[2];

	tcl_ret = Tcl_GetWideIntFromObj(interp, signal_obj, &sig_wide);
	if (tcl_ret != TCL_OK) {
		switch (tclsystem_internal_simplehash_obj(signal_obj)) {
			case 0x122ad0: /* HUP */
			case 0x98f364d0: /* SIGHUP */
				sig = SIGHUP;
				break;
			case 0x126754: /* INT */
			case 0x98f32954: /* SIGINT */
				sig = SIGINT;







|





|




|
















|




|

















|





|





|








|














|







527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"hostname ?hostname?\"", -1));

	return(TCL_ERROR);
}

static int tuapi_domainname(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_chroot(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *pathname;
	int chk_ret;

	if (objc != 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall:chroot pathname\"", -1));

		return(TCL_ERROR);
	}

	pathname = Tcl_GetString(objv[1]);

	chk_ret = chroot(pathname);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_pivot_root(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *new_root, *put_old;
	int chk_ret;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::pivot_root new_root put_old\"", -1));

		return(TCL_ERROR);
	}

	new_root = Tcl_GetString(objv[1]);
	put_old = Tcl_GetString(objv[2]);

	chk_ret = pivot_root(new_root, put_old);
	if (chk_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_mknod(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_getuid(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_kill(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *signal_obj;

	Tcl_WideInt pid_wide, sig_wide;
	pid_t pid;
	int sig;
	int kill_ret, tcl_ret;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::kill pid sig\"", -1));

		return(TCL_ERROR);
	}

	tcl_ret = Tcl_GetWideIntFromObj(interp, objv[1], &pid_wide);
	if (tcl_ret != TCL_OK) {
		return(tcl_ret);
	}
	pid = pid_wide;

	signal_obj = objv[2];

	tcl_ret = Tcl_GetWideIntFromObj(interp, signal_obj, &sig_wide);
	if (tcl_ret != TCL_OK) {
		switch (tuapi_internal_simplehash_obj(signal_obj)) {
			case 0x122ad0: /* HUP */
			case 0x98f364d0: /* SIGHUP */
				sig = SIGHUP;
				break;
			case 0x126754: /* INT */
			case 0x98f32954: /* SIGINT */
				sig = SIGINT;
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_ps(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_execve(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char **argv = NULL;
	char *file;
	int idx;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::execve file ?args ...?\"", -1));

		return(TCL_ERROR);
	}

	/* Find executable */
	file = Tcl_GetString(objv[1]);








|





|





|







762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_ps(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_execve(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char **argv = NULL;
	char *file;
	int idx;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::execve file ?args ...?\"", -1));

		return(TCL_ERROR);
	}

	/* Find executable */
	file = Tcl_GetString(objv[1]);

799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

	/* If the new image could not take over, something went wrong -- report error */
	Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

	return(TCL_ERROR);
}

static int tclsystem_losetup(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *file, *loopdev;
	int chk_ret;
	int loopfd, filefd;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::losetup loopdev file\"", -1));

		return(TCL_ERROR);
	}

	loopdev = Tcl_GetString(objv[1]);
	file = Tcl_GetString(objv[2]);








|





|







799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819

	/* If the new image could not take over, something went wrong -- report error */
	Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

	return(TCL_ERROR);
}

static int tuapi_losetup(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	char *file, *loopdev;
	int chk_ret;
	int loopfd, filefd;

	if (objc != 3) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::losetup loopdev file\"", -1));

		return(TCL_ERROR);
	}

	loopdev = Tcl_GetString(objv[1]);
	file = Tcl_GetString(objv[2]);

848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static void tclsystem_private_append_sockaddr_to_tclobj(Tcl_Interp *interp, Tcl_Obj *list, char *header, struct sockaddr *addr) {
	char addr_buf[INET6_ADDRSTRLEN + INET_ADDRSTRLEN + 1], *chk_inp;

	switch (addr->sa_family) {
		case AF_INET: /* IPv4 */
		case AF_INET6: /* IPv6 */
			switch (addr->sa_family) {
				case AF_INET: /* IPv4 */







|







848
849
850
851
852
853
854
855
856
857
858
859
860
861
862

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static void tuapi_private_append_sockaddr_to_tclobj(Tcl_Interp *interp, Tcl_Obj *list, char *header, struct sockaddr *addr) {
	char addr_buf[INET6_ADDRSTRLEN + INET_ADDRSTRLEN + 1], *chk_inp;

	switch (addr->sa_family) {
		case AF_INET: /* IPv4 */
		case AF_INET6: /* IPv6 */
			switch (addr->sa_family) {
				case AF_INET: /* IPv4 */
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

			break;
	}

	return;
}

static int tclsystem_private_get_sockaddr_from_obj(Tcl_Obj *value, void *target) {
	struct sockaddr_in local_v4;
	struct sockaddr_in6 local_v6;
	const char *addr_str;
	int inetpton_ret;

	addr_str = Tcl_GetString(value);








|







879
880
881
882
883
884
885
886
887
888
889
890
891
892
893

			break;
	}

	return;
}

static int tuapi_private_get_sockaddr_from_obj(Tcl_Obj *value, void *target) {
	struct sockaddr_in local_v4;
	struct sockaddr_in6 local_v6;
	const char *addr_str;
	int inetpton_ret;

	addr_str = Tcl_GetString(value);

910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

		return(0);
	}

	return(-1);
}

static int tclsystem_ifconfig_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_Obj *tcl_iface_list;
	struct ifconf ifaces_cfg;
	struct ifreq *iface_req = NULL;
	int iface_req_cnt = 224, iface_req_len;
	int idx, iface_cnt;
	int ioctl_ret, tcl_ret;








|







910
911
912
913
914
915
916
917
918
919
920
921
922
923
924

		return(0);
	}

	return(-1);
}

static int tuapi_ifconfig_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_Obj *tcl_iface_list;
	struct ifconf ifaces_cfg;
	struct ifreq *iface_req = NULL;
	int iface_req_cnt = 224, iface_req_len;
	int idx, iface_cnt;
	int ioctl_ret, tcl_ret;

960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
	free(iface_req);

	Tcl_SetObjResult(interp, tcl_iface_list);

	return(TCL_OK);
}

static int tclsystem_ifconfig_info(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock, int sock_v4, int sock_v6) {
	Tcl_Obj *retlist, *flags;
	struct ifreq iface_req;
	unsigned char *addr_data;
	const char *link_encap;
	const char *iface;
	int flags_bitmask, flag_broadcast = 0, flag_pointopoint = 0;
	int ioctl_ret;







|







960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
	free(iface_req);

	Tcl_SetObjResult(interp, tcl_iface_list);

	return(TCL_OK);
}

static int tuapi_ifconfig_info(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock, int sock_v4, int sock_v6) {
	Tcl_Obj *retlist, *flags;
	struct ifreq iface_req;
	unsigned char *addr_data;
	const char *link_encap;
	const char *iface;
	int flags_bitmask, flag_broadcast = 0, flag_pointopoint = 0;
	int ioctl_ret;
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
		Tcl_ListObjAppendElement(interp, retlist, Tcl_NewStringObj("index", -1));
		Tcl_ListObjAppendElement(interp, retlist, Tcl_NewWideIntObj(iface_req.ifr_ifindex));
	}

	if (sock_v4 != -1) {
		ioctl_ret = ioctl(sock_v4, SIOCGIFADDR, &iface_req);
		if (ioctl_ret == 0) {
			tclsystem_private_append_sockaddr_to_tclobj(interp, retlist, "address", &iface_req.ifr_addr);
		}

		if (flag_pointopoint) {
			/* Point-to-Point interfaces */
			ioctl_ret = ioctl(sock_v4, SIOCGIFDSTADDR, &iface_req);
			if (ioctl_ret == 0) {
				tclsystem_private_append_sockaddr_to_tclobj(interp, retlist, "destination", &iface_req.ifr_addr);
			}
		}

		if (flag_broadcast) {
			/* Broadcast interfaces */
			ioctl_ret = ioctl(sock_v4, SIOCGIFBRDADDR, &iface_req);
			if (ioctl_ret == 0) {
				tclsystem_private_append_sockaddr_to_tclobj(interp, retlist, "broadcast", &iface_req.ifr_addr);
			}
		}

		ioctl_ret = ioctl(sock_v4, SIOCGIFNETMASK, &iface_req);
		if (ioctl_ret == 0) {
			tclsystem_private_append_sockaddr_to_tclobj(interp, retlist, "netmask", &iface_req.ifr_addr);
		}
	}

	Tcl_SetObjResult(interp, retlist);

	return(TCL_OK);
}

static int tclsystem_ifconfig_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock, int sock_v4, int sock_v6) {
	Tcl_Obj *option_name_obj, *option_val_obj;
	Tcl_Obj **flags_objv;
	struct ifreq iface_req;
	struct sockaddr *tmp_ioctl_addr;
	const char *iface;
	short flags;
	int flags_objc;







|






|







|





|








|







1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
		Tcl_ListObjAppendElement(interp, retlist, Tcl_NewStringObj("index", -1));
		Tcl_ListObjAppendElement(interp, retlist, Tcl_NewWideIntObj(iface_req.ifr_ifindex));
	}

	if (sock_v4 != -1) {
		ioctl_ret = ioctl(sock_v4, SIOCGIFADDR, &iface_req);
		if (ioctl_ret == 0) {
			tuapi_private_append_sockaddr_to_tclobj(interp, retlist, "address", &iface_req.ifr_addr);
		}

		if (flag_pointopoint) {
			/* Point-to-Point interfaces */
			ioctl_ret = ioctl(sock_v4, SIOCGIFDSTADDR, &iface_req);
			if (ioctl_ret == 0) {
				tuapi_private_append_sockaddr_to_tclobj(interp, retlist, "destination", &iface_req.ifr_addr);
			}
		}

		if (flag_broadcast) {
			/* Broadcast interfaces */
			ioctl_ret = ioctl(sock_v4, SIOCGIFBRDADDR, &iface_req);
			if (ioctl_ret == 0) {
				tuapi_private_append_sockaddr_to_tclobj(interp, retlist, "broadcast", &iface_req.ifr_addr);
			}
		}

		ioctl_ret = ioctl(sock_v4, SIOCGIFNETMASK, &iface_req);
		if (ioctl_ret == 0) {
			tuapi_private_append_sockaddr_to_tclobj(interp, retlist, "netmask", &iface_req.ifr_addr);
		}
	}

	Tcl_SetObjResult(interp, retlist);

	return(TCL_OK);
}

static int tuapi_ifconfig_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock, int sock_v4, int sock_v6) {
	Tcl_Obj *option_name_obj, *option_val_obj;
	Tcl_Obj **flags_objv;
	struct ifreq iface_req;
	struct sockaddr *tmp_ioctl_addr;
	const char *iface;
	short flags;
	int flags_objc;
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
		}

		objc--;
		objv++;

		option_val_obj = objv[0];

		switch (tclsystem_internal_simplehash_obj(option_name_obj)) {
			case 0x6d9870f3: /* flags */
				flags = 0;

				tcl_ret = Tcl_ListObjGetElements(interp, option_val_obj, &flags_objc, &flags_objv);
				if (tcl_ret != TCL_OK) {
					return(tcl_ret);
				}

				for (; flags_objc > 0; flags_objc--,flags_objv++) {
					switch (tclsystem_internal_simplehash_obj(flags_objv[0])) {
						case 0x2ad0: /* UP */
							flags |= IFF_UP;
							break;
						case 0x1aef7f54: /* BROADCAST */
							flags |= IFF_BROADCAST;
							break;
						case 0xc252abd4: /* POINTOPOINT */







|









|







1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
		}

		objc--;
		objv++;

		option_val_obj = objv[0];

		switch (tuapi_internal_simplehash_obj(option_name_obj)) {
			case 0x6d9870f3: /* flags */
				flags = 0;

				tcl_ret = Tcl_ListObjGetElements(interp, option_val_obj, &flags_objc, &flags_objv);
				if (tcl_ret != TCL_OK) {
					return(tcl_ret);
				}

				for (; flags_objc > 0; flags_objc--,flags_objv++) {
					switch (tuapi_internal_simplehash_obj(flags_objv[0])) {
						case 0x2ad0: /* UP */
							flags |= IFF_UP;
							break;
						case 0x1aef7f54: /* BROADCAST */
							flags |= IFF_BROADCAST;
							break;
						case 0xc252abd4: /* POINTOPOINT */
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

			case 0x4d65ee6b: /* netmask */
				if (tmp_ioctl == -1) {
					tmp_ioctl = SIOCSIFNETMASK;
					tmp_ioctl_addr = &iface_req.ifr_netmask;
				}

				parse_ret = tclsystem_private_get_sockaddr_from_obj(option_val_obj, tmp_ioctl_addr);
				if (parse_ret != 0) {
					Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(option_val_obj)));

					return(TCL_ERROR);
				}

				switch (tmp_ioctl_addr->sa_family) {







|







1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441

			case 0x4d65ee6b: /* netmask */
				if (tmp_ioctl == -1) {
					tmp_ioctl = SIOCSIFNETMASK;
					tmp_ioctl_addr = &iface_req.ifr_netmask;
				}

				parse_ret = tuapi_private_get_sockaddr_from_obj(option_val_obj, tmp_ioctl_addr);
				if (parse_ret != 0) {
					Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(option_val_obj)));

					return(TCL_ERROR);
				}

				switch (tmp_ioctl_addr->sa_family) {
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
				return(TCL_ERROR);
		}
	}

	return(TCL_OK);
}

static int tclsystem_ifconfig(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tclsystem_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all interfaces */
			retval = tclsystem_ifconfig_list(cd, interp, objc, objv, sock);

			break;
		case 2: /* One argument, give information about the interface */
			retval = tclsystem_ifconfig_info(cd, interp, objc, objv, sock, sock_v4, sock_v6);

			break;
		default:
			/* Otherwise, configure the interace */
			retval = tclsystem_ifconfig_conf(cd, interp, objc, objv, sock, sock_v4, sock_v6);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tclsystem_route_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock_v4, int sock_v6) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_route_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock_v4, int sock_v6) {
	Tcl_WideInt option_val_wide; 
	Tcl_Obj *operation_obj, *dest_obj, *destmask_obj;
	Tcl_Obj *option_name_obj, *option_val_obj;
	struct rtentry route;
	int sock;
	int ioctl_id;
	int tcl_ret, ioctl_ret, parse_ret;

	if (objc < 4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::route operation destination destination_mask ?options?\"", -1));

		return(TCL_ERROR);
	}

	/* Clear object values */
	memset(&route, 0, sizeof(route));

	/* Determine operation */
	operation_obj = objv[1];
	switch (tclsystem_internal_simplehash_obj(operation_obj)) {
		case 0x187264: /* add */
			ioctl_id = SIOCADDRT;
			break;
		case 0x1932ec: /* del */
		case 0x5d98e965: /* delete */
			ioctl_id = SIOCDELRT;
			break;
		default:
			Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad option \"%s\": must be add, or delete", Tcl_GetString(operation_obj)));

			return(TCL_ERROR);
	}

	/* Set default flags */
	route.rt_flags = RTF_UP;

	/* Parse destination address */
	dest_obj = objv[2];
	parse_ret = tclsystem_private_get_sockaddr_from_obj(dest_obj, &route.rt_dst);
	if (parse_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(dest_obj)));

		return(TCL_ERROR);
	}

	/* Parse destination netmask */
	destmask_obj = objv[3];
	parse_ret = tclsystem_private_get_sockaddr_from_obj(destmask_obj, &route.rt_genmask);
	if (parse_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(destmask_obj)));

		return(TCL_ERROR);
	}

	if (route.rt_dst.sa_family != route.rt_genmask.sa_family) {







|



|









|



|




|
















|





|









|









|


















|








|







1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
				return(TCL_ERROR);
		}
	}

	return(TCL_OK);
}

static int tuapi_ifconfig(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tuapi_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all interfaces */
			retval = tuapi_ifconfig_list(cd, interp, objc, objv, sock);

			break;
		case 2: /* One argument, give information about the interface */
			retval = tuapi_ifconfig_info(cd, interp, objc, objv, sock, sock_v4, sock_v6);

			break;
		default:
			/* Otherwise, configure the interace */
			retval = tuapi_ifconfig_conf(cd, interp, objc, objv, sock, sock_v4, sock_v6);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tuapi_route_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock_v4, int sock_v6) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_route_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock_v4, int sock_v6) {
	Tcl_WideInt option_val_wide; 
	Tcl_Obj *operation_obj, *dest_obj, *destmask_obj;
	Tcl_Obj *option_name_obj, *option_val_obj;
	struct rtentry route;
	int sock;
	int ioctl_id;
	int tcl_ret, ioctl_ret, parse_ret;

	if (objc < 4) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::route operation destination destination_mask ?options?\"", -1));

		return(TCL_ERROR);
	}

	/* Clear object values */
	memset(&route, 0, sizeof(route));

	/* Determine operation */
	operation_obj = objv[1];
	switch (tuapi_internal_simplehash_obj(operation_obj)) {
		case 0x187264: /* add */
			ioctl_id = SIOCADDRT;
			break;
		case 0x1932ec: /* del */
		case 0x5d98e965: /* delete */
			ioctl_id = SIOCDELRT;
			break;
		default:
			Tcl_SetObjResult(interp, Tcl_ObjPrintf("bad option \"%s\": must be add, or delete", Tcl_GetString(operation_obj)));

			return(TCL_ERROR);
	}

	/* Set default flags */
	route.rt_flags = RTF_UP;

	/* Parse destination address */
	dest_obj = objv[2];
	parse_ret = tuapi_private_get_sockaddr_from_obj(dest_obj, &route.rt_dst);
	if (parse_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(dest_obj)));

		return(TCL_ERROR);
	}

	/* Parse destination netmask */
	destmask_obj = objv[3];
	parse_ret = tuapi_private_get_sockaddr_from_obj(destmask_obj, &route.rt_genmask);
	if (parse_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(destmask_obj)));

		return(TCL_ERROR);
	}

	if (route.rt_dst.sa_family != route.rt_genmask.sa_family) {
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
		}

		objc--;
		objv++;

		option_val_obj = objv[0];

		switch (tclsystem_internal_simplehash_obj(option_name_obj)) {
			case 0x4c727779: /* gateway */
				parse_ret = tclsystem_private_get_sockaddr_from_obj(option_val_obj, &route.rt_gateway);
				if (parse_ret != 0) {
					Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(option_val_obj)));

					return(TCL_ERROR);
				}

				route.rt_flags &= (~RTF_HOST);







|

|







1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
		}

		objc--;
		objv++;

		option_val_obj = objv[0];

		switch (tuapi_internal_simplehash_obj(option_name_obj)) {
			case 0x4c727779: /* gateway */
				parse_ret = tuapi_private_get_sockaddr_from_obj(option_val_obj, &route.rt_gateway);
				if (parse_ret != 0) {
					Tcl_SetObjResult(interp, Tcl_ObjPrintf("unable to parse \"%s\" as an address", Tcl_GetString(option_val_obj)));

					return(TCL_ERROR);
				}

				route.rt_flags &= (~RTF_HOST);
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_route(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tclsystem_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all interfaces */
			retval = tclsystem_route_list(cd, interp, objc, objv, sock_v4, sock_v6);

			break;
		default:
			/* Otherwise, modify routes */
			retval = tclsystem_route_conf(cd, interp, objc, objv, sock_v4, sock_v6);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tclsystem_brctl_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tclsystem_brctl_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_Obj *operation_obj, *bridge_name_obj, *interface_name_obj;
	unsigned long arg[4];
	struct ifreq ifr;
	int ioctl_ret, ioctl_id;
	int add = 0;

	/* Determine operation */
	operation_obj = objv[1];
	switch (tclsystem_internal_simplehash_obj(operation_obj)) {
		case 0x1c993272: /* addbr */
			add = 1;
		case 0x4cbb3272: /* delbr */
			if (objc != 3) {
				if (add) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::brctl addbr bridge\"", -1));
				} else {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::brctl delbr bridge\"", -1));
				}

				return(TCL_ERROR);
			}

			bridge_name_obj = objv[2];








|



|









|




|
















|





|








|





|

|







1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_route(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tuapi_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all interfaces */
			retval = tuapi_route_list(cd, interp, objc, objv, sock_v4, sock_v6);

			break;
		default:
			/* Otherwise, modify routes */
			retval = tuapi_route_conf(cd, interp, objc, objv, sock_v4, sock_v6);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tuapi_brctl_list(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));

	return(TCL_ERROR);
}

static int tuapi_brctl_conf(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[], int sock) {
	Tcl_Obj *operation_obj, *bridge_name_obj, *interface_name_obj;
	unsigned long arg[4];
	struct ifreq ifr;
	int ioctl_ret, ioctl_id;
	int add = 0;

	/* Determine operation */
	operation_obj = objv[1];
	switch (tuapi_internal_simplehash_obj(operation_obj)) {
		case 0x1c993272: /* addbr */
			add = 1;
		case 0x4cbb3272: /* delbr */
			if (objc != 3) {
				if (add) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::brctl addbr bridge\"", -1));
				} else {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::brctl delbr bridge\"", -1));
				}

				return(TCL_ERROR);
			}

			bridge_name_obj = objv[2];

1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792

			break;
		case 0x1C9937E6: /* addif */
			add = 1;
		case 0x4cbb37e6: /* delif */
			if (objc != 4) {
				if (add) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::brctl addif bridge interface\"", -1));
				} else {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::brctl delif bridge interface\"", -1));
				}

				return(TCL_ERROR);
			}

			if (add) {
				ioctl_id = SIOCBRADDIF;







|

|







1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792

			break;
		case 0x1C9937E6: /* addif */
			add = 1;
		case 0x4cbb37e6: /* delif */
			if (objc != 4) {
				if (add) {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::brctl addif bridge interface\"", -1));
				} else {
					Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::brctl delif bridge interface\"", -1));
				}

				return(TCL_ERROR);
			}

			if (add) {
				ioctl_id = SIOCBRADDIF;
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tclsystem_brctl(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tclsystem_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all bridges */
			retval = tclsystem_brctl_list(cd, interp, objc, objv, sock);

			break;
		default:
			/* Otherwise, modify routes */
			retval = tclsystem_brctl_conf(cd, interp, objc, objv, sock);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tclsystem_vconfig(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tclsystem_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));







|



|









|




|
















|



|







1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
1838
1839
1840
1841
1842
1843
1844
1845
1846
1847
1848
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868

		return(TCL_ERROR);
	}

	return(TCL_OK);
}

static int tuapi_brctl(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tuapi_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	switch (objc) {
		case 0:
		case 1: /* No arguments, list all bridges */
			retval = tuapi_brctl_list(cd, interp, objc, objv, sock);

			break;
		default:
			/* Otherwise, modify routes */
			retval = tuapi_brctl_conf(cd, interp, objc, objv, sock);

			break;
	}

	/* Cleanup */
	if (sock_v4 != -1) {
		close(sock_v4);
	}

	if (sock_v6 != -1) {
		close(sock_v6);
	}

	return(retval);
}

static int tuapi_vconfig(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	int sock_v4, sock_v6, sock;
	int retval = TCL_ERROR;

	sock = tuapi_internal_getsock(&sock_v4, &sock_v6);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create socket", -1));

		return(TCL_ERROR);
	}

	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
		close(sock_v6);
	}

	return(retval);
}

#ifndef DISABLE_UNIX_SOCKETS
struct tclsystem_socket_unix__chan_id {
	int fd;
	Tcl_Channel chan;
};

static int tclsystem_socket_unix__chan_close(ClientData id_p, Tcl_Interp *interp) {
	struct tclsystem_socket_unix__chan_id *id;
	int fd;

	id = id_p;

	fd = id->fd;

	close(fd);

	free(id);

	return(0);
}

static int tclsystem_socket_unix__chan_read(ClientData id_p, char *buf, int bufsize, int *errorCodePtr) {
	struct tclsystem_socket_unix__chan_id *id;
	ssize_t read_ret;
	int fd;
	int retval;

	id = id_p;

	fd = id->fd;

	read_ret = read(fd, buf, bufsize);
	if (read_ret < 0) {
		*errorCodePtr = errno;

		return(-1);
	}

	retval = read_ret;

	return(retval);
}

static int tclsystem_socket_unix__chan_write(ClientData id_p, const char *buf, int toWrite, int *errorCodePtr) {
	struct tclsystem_socket_unix__chan_id *id;
	ssize_t write_ret;
	int fd;
	int bytesWritten;

	id = id_p;

	fd = id->fd;







|




|
|













|
|




















|
|







1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
		close(sock_v6);
	}

	return(retval);
}

#ifndef DISABLE_UNIX_SOCKETS
struct tuapi_socket_unix__chan_id {
	int fd;
	Tcl_Channel chan;
};

static int tuapi_socket_unix__chan_close(ClientData id_p, Tcl_Interp *interp) {
	struct tuapi_socket_unix__chan_id *id;
	int fd;

	id = id_p;

	fd = id->fd;

	close(fd);

	free(id);

	return(0);
}

static int tuapi_socket_unix__chan_read(ClientData id_p, char *buf, int bufsize, int *errorCodePtr) {
	struct tuapi_socket_unix__chan_id *id;
	ssize_t read_ret;
	int fd;
	int retval;

	id = id_p;

	fd = id->fd;

	read_ret = read(fd, buf, bufsize);
	if (read_ret < 0) {
		*errorCodePtr = errno;

		return(-1);
	}

	retval = read_ret;

	return(retval);
}

static int tuapi_socket_unix__chan_write(ClientData id_p, const char *buf, int toWrite, int *errorCodePtr) {
	struct tuapi_socket_unix__chan_id *id;
	ssize_t write_ret;
	int fd;
	int bytesWritten;

	id = id_p;

	fd = id->fd;
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

		return(-1);
	}

	return(bytesWritten);
}

static void tclsystem_socket_unix__chan_eventhandler(ClientData id_p, int mask) {
	struct tclsystem_socket_unix__chan_id *id;
	Tcl_Channel chan;

	id = id_p;

	chan = id->chan;

	if (!chan) {
		return;
	}

	Tcl_NotifyChannel(chan, mask);
}

static void tclsystem_socket_unix__chan_watch(ClientData id_p, int mask) {
	struct tclsystem_socket_unix__chan_id *id;
	int fd;

	id = id_p;

	fd = id->fd;

	Tcl_CreateFileHandler(fd, mask, tclsystem_socket_unix__chan_eventhandler, id);

	return;
}

static int tclsystem_socket_unix__chan_gethandle(ClientData id_p, int direction, ClientData *handlePtr) {
	struct tclsystem_socket_unix__chan_id *id;
	int fd;
	ClientData fd_cd;

	id = id_p;

	fd = id->fd;

	memcpy(&fd_cd, &fd, sizeof(fd));

	*handlePtr = fd_cd;

	return(TCL_OK);
}

static Tcl_Channel tclsystem_socket_unix_sock2tclchan(int sock) {
	struct tclsystem_socket_unix__chan_id *id;
	static Tcl_ChannelType tcl_chan_type;
	static int tcl_chan_type_init = 0;
	Tcl_Channel tcl_chan;
	char chan_name[32];
	int sock_flags;

	if (!tcl_chan_type_init) {
		tcl_chan_type.typeName = "socket";
		tcl_chan_type.version = TCL_CHANNEL_VERSION_2;
		tcl_chan_type.closeProc = tclsystem_socket_unix__chan_close;
		tcl_chan_type.inputProc = tclsystem_socket_unix__chan_read;
		tcl_chan_type.outputProc = tclsystem_socket_unix__chan_write;
		tcl_chan_type.watchProc = tclsystem_socket_unix__chan_watch;
		tcl_chan_type.getHandleProc = tclsystem_socket_unix__chan_gethandle;
		tcl_chan_type.seekProc = NULL;
		tcl_chan_type.setOptionProc = NULL;
		tcl_chan_type.getOptionProc = NULL;
		tcl_chan_type.close2Proc = NULL;
		tcl_chan_type.blockModeProc = NULL;
		tcl_chan_type.flushProc = NULL;
		tcl_chan_type.handlerProc = NULL;







|
|













|
|






|




|
|














|
|









|
|
|
|
|







1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028

		return(-1);
	}

	return(bytesWritten);
}

static void tuapi_socket_unix__chan_eventhandler(ClientData id_p, int mask) {
	struct tuapi_socket_unix__chan_id *id;
	Tcl_Channel chan;

	id = id_p;

	chan = id->chan;

	if (!chan) {
		return;
	}

	Tcl_NotifyChannel(chan, mask);
}

static void tuapi_socket_unix__chan_watch(ClientData id_p, int mask) {
	struct tuapi_socket_unix__chan_id *id;
	int fd;

	id = id_p;

	fd = id->fd;

	Tcl_CreateFileHandler(fd, mask, tuapi_socket_unix__chan_eventhandler, id);

	return;
}

static int tuapi_socket_unix__chan_gethandle(ClientData id_p, int direction, ClientData *handlePtr) {
	struct tuapi_socket_unix__chan_id *id;
	int fd;
	ClientData fd_cd;

	id = id_p;

	fd = id->fd;

	memcpy(&fd_cd, &fd, sizeof(fd));

	*handlePtr = fd_cd;

	return(TCL_OK);
}

static Tcl_Channel tuapi_socket_unix_sock2tclchan(int sock) {
	struct tuapi_socket_unix__chan_id *id;
	static Tcl_ChannelType tcl_chan_type;
	static int tcl_chan_type_init = 0;
	Tcl_Channel tcl_chan;
	char chan_name[32];
	int sock_flags;

	if (!tcl_chan_type_init) {
		tcl_chan_type.typeName = "socket";
		tcl_chan_type.version = TCL_CHANNEL_VERSION_2;
		tcl_chan_type.closeProc = tuapi_socket_unix__chan_close;
		tcl_chan_type.inputProc = tuapi_socket_unix__chan_read;
		tcl_chan_type.outputProc = tuapi_socket_unix__chan_write;
		tcl_chan_type.watchProc = tuapi_socket_unix__chan_watch;
		tcl_chan_type.getHandleProc = tuapi_socket_unix__chan_gethandle;
		tcl_chan_type.seekProc = NULL;
		tcl_chan_type.setOptionProc = NULL;
		tcl_chan_type.getOptionProc = NULL;
		tcl_chan_type.close2Proc = NULL;
		tcl_chan_type.blockModeProc = NULL;
		tcl_chan_type.flushProc = NULL;
		tcl_chan_type.handlerProc = NULL;
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078

	/* Update the structure passed to each function to include the channel name */
	id->chan = tcl_chan;

	return(tcl_chan);
}

struct tclsystem_socket_unix__chan_accept_cd {
	int fd;
	Tcl_Interp *interp;
	Tcl_Obj *command;
};

static void tclsystem_socket_unix__chan_accept(ClientData cd_p, int mask) {
	struct tclsystem_socket_unix__chan_accept_cd *cd;
	Tcl_Interp *interp;
	Tcl_Channel chan;
	Tcl_Obj *command, *command_to_run_objs[5], *command_to_run;
	int setsockopt_ret;
	int pass_creds_true = 1;
	int fd;
	int sock;







|





|
|







2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078

	/* Update the structure passed to each function to include the channel name */
	id->chan = tcl_chan;

	return(tcl_chan);
}

struct tuapi_socket_unix__chan_accept_cd {
	int fd;
	Tcl_Interp *interp;
	Tcl_Obj *command;
};

static void tuapi_socket_unix__chan_accept(ClientData cd_p, int mask) {
	struct tuapi_socket_unix__chan_accept_cd *cd;
	Tcl_Interp *interp;
	Tcl_Channel chan;
	Tcl_Obj *command, *command_to_run_objs[5], *command_to_run;
	int setsockopt_ret;
	int pass_creds_true = 1;
	int fd;
	int sock;
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
	command = cd->command;

	sock = accept(fd, NULL, NULL);
	if (sock < 0) {
		return;
	}

	chan = tclsystem_socket_unix_sock2tclchan(sock);
	if (chan == NULL) {
		close(sock);

		return;
	}

	setsockopt_ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &pass_creds_true, sizeof(pass_creds_true));







|







2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
	command = cd->command;

	sock = accept(fd, NULL, NULL);
	if (sock < 0) {
		return;
	}

	chan = tuapi_socket_unix_sock2tclchan(sock);
	if (chan == NULL) {
		close(sock);

		return;
	}

	setsockopt_ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &pass_creds_true, sizeof(pass_creds_true));
2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
	command_to_run = Tcl_ConcatObj(sizeof(command_to_run_objs) / sizeof(command_to_run_objs[0]), command_to_run_objs);

	Tcl_EvalObjEx(interp, command_to_run, TCL_EVAL_GLOBAL);

	return;
}

static int tclsystem_socket_unix_server(ClientData cd, Tcl_Interp *interp, int sock, const char *path, Tcl_Obj *command) {
	struct tclsystem_socket_unix__chan_accept_cd *accept_cd;
	struct sockaddr_un dest;
	ssize_t pathlen;
	int bind_ret, listen_ret;

	pathlen = strlen(path) + 1;
	if (pathlen <= 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("path too short", -1));







|
|







2116
2117
2118
2119
2120
2121
2122
2123
2124
2125
2126
2127
2128
2129
2130
2131
	command_to_run = Tcl_ConcatObj(sizeof(command_to_run_objs) / sizeof(command_to_run_objs[0]), command_to_run_objs);

	Tcl_EvalObjEx(interp, command_to_run, TCL_EVAL_GLOBAL);

	return;
}

static int tuapi_socket_unix_server(ClientData cd, Tcl_Interp *interp, int sock, const char *path, Tcl_Obj *command) {
	struct tuapi_socket_unix__chan_accept_cd *accept_cd;
	struct sockaddr_un dest;
	ssize_t pathlen;
	int bind_ret, listen_ret;

	pathlen = strlen(path) + 1;
	if (pathlen <= 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("path too short", -1));
2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184

	accept_cd->fd = sock;
	accept_cd->interp = interp;
	accept_cd->command = command;

	Tcl_IncrRefCount(command);

	Tcl_CreateFileHandler(sock, TCL_READABLE, tclsystem_socket_unix__chan_accept, accept_cd);

	return(TCL_OK);
}

static int tclsystem_socket_unix_client(ClientData cd, Tcl_Interp *interp, int sock, const char *path) {
	Tcl_Channel chan;
	struct sockaddr_un dest;
	ssize_t pathlen;
	int connect_ret, setsockopt_ret;
	int pass_creds_true = 1;

	pathlen = strlen(path) + 1;







|




|







2165
2166
2167
2168
2169
2170
2171
2172
2173
2174
2175
2176
2177
2178
2179
2180
2181
2182
2183
2184

	accept_cd->fd = sock;
	accept_cd->interp = interp;
	accept_cd->command = command;

	Tcl_IncrRefCount(command);

	Tcl_CreateFileHandler(sock, TCL_READABLE, tuapi_socket_unix__chan_accept, accept_cd);

	return(TCL_OK);
}

static int tuapi_socket_unix_client(ClientData cd, Tcl_Interp *interp, int sock, const char *path) {
	Tcl_Channel chan;
	struct sockaddr_un dest;
	ssize_t pathlen;
	int connect_ret, setsockopt_ret;
	int pass_creds_true = 1;

	pathlen = strlen(path) + 1;
2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
	setsockopt_ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &pass_creds_true, sizeof(pass_creds_true));
	if (setsockopt_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	chan = tclsystem_socket_unix_sock2tclchan(sock);
	if (chan == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create Tcl channel", -1));

		return(TCL_ERROR);
	}

	Tcl_RegisterChannel(interp, chan);

	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1));

	return(TCL_OK);
}

static int tclsystem_socket_unix(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *path_obj, *command_obj;
	char *path;
	int retval;
	int sock;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::socket_unix path\" or \"::system::syscall::socket_unix -server command path\"", -1));

		return(TCL_ERROR);
	}

	path_obj = objv[1];
	path = Tcl_GetString(path_obj);

	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	if (strcmp(path, "-server") == 0) {
		if (objc != 4) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::socket_unix -server command path\"", -1));

			close(sock);

			return(TCL_ERROR);
		}

		command_obj = objv[2];
		path_obj = objv[3];

		path = Tcl_GetString(path_obj);

		retval = tclsystem_socket_unix_server(cd, interp, sock, path, command_obj);
	} else {
		if (objc != 2) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::socket_unix path\"", -1));

			close(sock);

			return(TCL_ERROR);
		}

		retval = tclsystem_socket_unix_client(cd, interp, sock, path);
	}

	if (retval != TCL_OK) {
		close(sock);
	}

	return(retval);
}
#else
static int tclsystem_socket_unix(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));
	return(TCL_ERROR)
}
#endif

static int tclsystem_tsmf_start_svc(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	struct timeval select_timeout;
	Tcl_WideInt umask_val, timeout_val, uid_val, gid_val;
	Tcl_Obj *filename_obj, *env_obj, *logfile_obj, **env_entry_objv, *cwd_obj, *umask_obj, *uid_obj, *gid_obj;
	Tcl_Obj *sri_obj, *timeout_obj;
	pid_t child, child_pgid = -1, waitpid_ret;
	ssize_t read_ret;
	time_t currtime;







|













|






|
















|











|


|






|









|





|







2207
2208
2209
2210
2211
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
2295
2296
2297
	setsockopt_ret = setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &pass_creds_true, sizeof(pass_creds_true));
	if (setsockopt_ret != 0) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	chan = tuapi_socket_unix_sock2tclchan(sock);
	if (chan == NULL) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("unable to create Tcl channel", -1));

		return(TCL_ERROR);
	}

	Tcl_RegisterChannel(interp, chan);

	Tcl_SetObjResult(interp, Tcl_NewStringObj(Tcl_GetChannelName(chan), -1));

	return(TCL_OK);
}

static int tuapi_socket_unix(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_Obj *path_obj, *command_obj;
	char *path;
	int retval;
	int sock;

	if (objc < 2) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::socket_unix path\" or \"::tuapi::syscall::socket_unix -server command path\"", -1));

		return(TCL_ERROR);
	}

	path_obj = objv[1];
	path = Tcl_GetString(path_obj);

	sock = socket(AF_UNIX, SOCK_STREAM, 0);
	if (sock == -1) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(strerror(errno), -1));

		return(TCL_ERROR);
	}

	if (strcmp(path, "-server") == 0) {
		if (objc != 4) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::socket_unix -server command path\"", -1));

			close(sock);

			return(TCL_ERROR);
		}

		command_obj = objv[2];
		path_obj = objv[3];

		path = Tcl_GetString(path_obj);

		retval = tuapi_socket_unix_server(cd, interp, sock, path, command_obj);
	} else {
		if (objc != 2) {
			Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::socket_unix path\"", -1));

			close(sock);

			return(TCL_ERROR);
		}

		retval = tuapi_socket_unix_client(cd, interp, sock, path);
	}

	if (retval != TCL_OK) {
		close(sock);
	}

	return(retval);
}
#else
static int tuapi_socket_unix(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	Tcl_SetObjResult(interp, Tcl_NewStringObj("not implemented", -1));
	return(TCL_ERROR)
}
#endif

static int tuapi_tsmf_start_svc(ClientData cd, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
	struct timeval select_timeout;
	Tcl_WideInt umask_val, timeout_val, uid_val, gid_val;
	Tcl_Obj *filename_obj, *env_obj, *logfile_obj, **env_entry_objv, *cwd_obj, *umask_obj, *uid_obj, *gid_obj;
	Tcl_Obj *sri_obj, *timeout_obj;
	pid_t child, child_pgid = -1, waitpid_ret;
	ssize_t read_ret;
	time_t currtime;
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
	int fds[2], fd;
	int status;
	int idx;

	/* 1. Parse arguments */
	/* 1.a. Ensure the correct number of arguments were passed */
	if (objc != 10) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::system::syscall::tsmf_start_svc sri filename logfile env cwd umask uid gid timeout\"", -1));

		return(TCL_ERROR);
	}

	/* 1.b. Identify Tcl_Objs to use for each argument */
	sri_obj = objv[1];
	filename_obj = objv[2];







|







2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
	int fds[2], fd;
	int status;
	int idx;

	/* 1. Parse arguments */
	/* 1.a. Ensure the correct number of arguments were passed */
	if (objc != 10) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj("wrong # args: should be \"::tuapi::syscall::tsmf_start_svc sri filename logfile env cwd umask uid gid timeout\"", -1));

		return(TCL_ERROR);
	}

	/* 1.b. Identify Tcl_Objs to use for each argument */
	sri_obj = objv[1];
	filename_obj = objv[2];
2545
2546
2547
2548
2549
2550
2551
2552



2553

2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
	argv[0] = filename;
	argv[1] = "start";
	argv[2] = NULL;
	execve_ret = execve(filename, argv, envv);

	/* 10. Abort if something has gone wrong */
	_exit(execve_ret);
}





int System_Init(Tcl_Interp *interp) {
#ifdef USE_TCL_STUBS
	const char *tclInitStubs_ret;

	/* Initialize Stubs */
	tclInitStubs_ret = Tcl_InitStubs(interp, "8.4", 0);
	if (!tclInitStubs_ret) {
		return(TCL_ERROR);
	}
#endif

	/* Kernel maintenance related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::insmod", tclsystem_insmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::rmmod", tclsystem_rmmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::lsmod", tclsystem_lsmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::hostname", tclsystem_hostname, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::domainname", tclsystem_domainname, NULL, NULL);

	/* Block or char device related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::losetup", tclsystem_losetup, NULL, NULL);

	/* Filesystem related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::mount", tclsystem_mount, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::umount", tclsystem_umount, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::swapon", tclsystem_swapon, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::swapoff", tclsystem_swapoff, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::mknod", tclsystem_mknod, NULL, NULL);

	/* Process related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::getuid", tclsystem_getuid, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::chroot", tclsystem_chroot, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::pivot_root", tclsystem_pivot_root, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::kill", tclsystem_kill, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::ps", tclsystem_ps, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::execve", tclsystem_execve, NULL, NULL);

	/* Network related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::ifconfig", tclsystem_ifconfig, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::route", tclsystem_route, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::brctl", tclsystem_brctl, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::system::syscall::vconfig", tclsystem_vconfig, NULL, NULL);

	/* Needed commands for basic services Tcl lacks */
	Tcl_CreateObjCommand(interp, "::system::syscall::socket_unix", tclsystem_socket_unix, NULL, NULL);

	/* Service (TSMF) related commands */
	Tcl_CreateObjCommand(interp, "::system::syscall::tsmf_start_svc", tclsystem_tsmf_start_svc, NULL, NULL);

	/* Internal functions */
	Tcl_CreateObjCommand(interp, "::system::internal::hash", tclsystem_internalproc_simplehash, NULL, NULL);

	/* Define constants */
	/** Create parent namespace **/
	Tcl_CreateNamespace(interp, "::system::const", NULL, NULL);

	/** Define constants, for real **/
	Tcl_ObjSetVar2(interp, Tcl_NewStringObj("::system::const::HOST_NAME_MAX", -1), NULL, Tcl_NewWideIntObj(HOST_NAME_MAX), TCL_GLOBAL_ONLY);

	/* Create high-level user functions */
	Tcl_Eval(interp,
#include "system.tcl.h" 
	);

	Tcl_PkgProvide(interp, "system", "0.1");

	return(TCL_OK);
}







|
>
>
>
|
>
|











|
|
|
|
|


|


|
|
|
|
|


|
|
|
|
|
|


|
|
|
|


|


|


|



|


|



|


|



2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
2575
2576
2577
2578
2579
2580
2581
2582
2583
2584
2585
2586
2587
2588
2589
2590
2591
2592
2593
2594
2595
2596
2597
2598
2599
2600
2601
2602
2603
2604
2605
2606
2607
2608
2609
2610
2611
2612
2613
2614
2615
2616
2617
2618
2619
2620
2621
2622
2623
2624
	argv[0] = filename;
	argv[1] = "start";
	argv[2] = NULL;
	execve_ret = execve(filename, argv, envv);

	/* 10. Abort if something has gone wrong */
	_exit(execve_ret);

	/* Handle lint-ness */
	return(TCL_ERROR);
	sri_obj = sri_obj;
}

int Tuapi_Init(Tcl_Interp *interp) {
#ifdef USE_TCL_STUBS
	const char *tclInitStubs_ret;

	/* Initialize Stubs */
	tclInitStubs_ret = Tcl_InitStubs(interp, "8.4", 0);
	if (!tclInitStubs_ret) {
		return(TCL_ERROR);
	}
#endif

	/* Kernel maintenance related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::insmod", tuapi_insmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::rmmod", tuapi_rmmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::lsmod", tuapi_lsmod, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::hostname", tuapi_hostname, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::domainname", tuapi_domainname, NULL, NULL);

	/* Block or char device related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::losetup", tuapi_losetup, NULL, NULL);

	/* Filesystem related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::mount", tuapi_mount, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::umount", tuapi_umount, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::swapon", tuapi_swapon, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::swapoff", tuapi_swapoff, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::mknod", tuapi_mknod, NULL, NULL);

	/* Process related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::getuid", tuapi_getuid, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::chroot", tuapi_chroot, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::pivot_root", tuapi_pivot_root, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::kill", tuapi_kill, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::ps", tuapi_ps, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::execve", tuapi_execve, NULL, NULL);

	/* Network related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::ifconfig", tuapi_ifconfig, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::route", tuapi_route, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::brctl", tuapi_brctl, NULL, NULL);
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::vconfig", tuapi_vconfig, NULL, NULL);

	/* Needed commands for basic services Tcl lacks */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::socket_unix", tuapi_socket_unix, NULL, NULL);

	/* Service (TSMF) related commands */
	Tcl_CreateObjCommand(interp, "::tuapi::syscall::tsmf_start_svc", tuapi_tsmf_start_svc, NULL, NULL);

	/* Internal functions */
	Tcl_CreateObjCommand(interp, "::tuapi::internal::hash", tuapi_internalproc_simplehash, NULL, NULL);

	/* Define constants */
	/** Create parent namespace **/
	Tcl_CreateNamespace(interp, "::tuapi::const", NULL, NULL);

	/** Define constants, for real **/
	Tcl_ObjSetVar2(interp, Tcl_NewStringObj("::tuapi::const::HOST_NAME_MAX", -1), NULL, Tcl_NewWideIntObj(HOST_NAME_MAX), TCL_GLOBAL_ONLY);

	/* Create high-level user functions */
	Tcl_Eval(interp,
#include "tuapi.tcl.h" 
	);

	Tcl_PkgProvide(interp, "tuapi", "0.1");

	return(TCL_OK);
}

Modified system.tcl from [69a9dbf05c] to [dc4245bc68].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#! /usr/bin/env tclsh

namespace eval ::system {}
namespace eval ::system::helper {}

set ::system::_mount_flags(bind) BIND
set ::system::_mount_flags(move) MOVE
set ::system::_mount_flags(remount) REMOUNT
set ::system::_mount_flags(mandlock) MANDLOCK
set ::system::_mount_flags(dirsync) DIRSYNC
set ::system::_mount_flags(noatime) NOATIME
set ::system::_mount_flags(nodiratime) NODIRATIME
set ::system::_mount_flags(relatime) RELATIME
set ::system::_mount_flags(strictatime) STRICTATIME
set ::system::_mount_flags(nodev) NODEV
set ::system::_mount_flags(noexec) NOEXEC
set ::system::_mount_flags(nosuid) NOSUID
set ::system::_mount_flags(ro) RDONLY
set ::system::_mount_flags(silent) SILENT
set ::system::_mount_flags(synchronous) SYNCHRONOUS
set ::system::_mount_flags(sync) SYNCHRONOUS


# Determine where to mount a given device (usually by checking "/etc/fstab")
proc ::system::helper::find_mountpoint {device} {
	set data ""
	catch {
		set fd [open "/etc/fstab"]
		set data [read -nonewline $fd]
		close $fd
	}



|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|



|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#! /usr/bin/env tclsh

namespace eval ::tuapi {}
namespace eval ::tuapi::helper {}

set ::tuapi::_mount_flags(bind) BIND
set ::tuapi::_mount_flags(move) MOVE
set ::tuapi::_mount_flags(remount) REMOUNT
set ::tuapi::_mount_flags(mandlock) MANDLOCK
set ::tuapi::_mount_flags(dirsync) DIRSYNC
set ::tuapi::_mount_flags(noatime) NOATIME
set ::tuapi::_mount_flags(nodiratime) NODIRATIME
set ::tuapi::_mount_flags(relatime) RELATIME
set ::tuapi::_mount_flags(strictatime) STRICTATIME
set ::tuapi::_mount_flags(nodev) NODEV
set ::tuapi::_mount_flags(noexec) NOEXEC
set ::tuapi::_mount_flags(nosuid) NOSUID
set ::tuapi::_mount_flags(ro) RDONLY
set ::tuapi::_mount_flags(silent) SILENT
set ::tuapi::_mount_flags(synchronous) SYNCHRONOUS
set ::tuapi::_mount_flags(sync) SYNCHRONOUS


# Determine where to mount a given device (usually by checking "/etc/fstab")
proc ::tuapi::helper::find_mountpoint {device} {
	set data ""
	catch {
		set fd [open "/etc/fstab"]
		set data [read -nonewline $fd]
		close $fd
	}

48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
			return [list source $curr_device target $curr_mountpoint fstype $curr_fstype options $curr_opts dumpfreq $curr_dumpfreq fsckpass $curr_fsckpass]
		}
	}

	return -code error "no entry found in \"/etc/fstab\" for \"$device\""
}

proc ::system::mount args {
	set options_list [list]

	for {set idx 0} {$idx < [llength $args]} {incr idx} {
		set curr_arg [lindex $args $idx]

		switch -glob -- $curr_arg {
			"-t" {







|







48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
			return [list source $curr_device target $curr_mountpoint fstype $curr_fstype options $curr_opts dumpfreq $curr_dumpfreq fsckpass $curr_fsckpass]
		}
	}

	return -code error "no entry found in \"/etc/fstab\" for \"$device\""
}

proc ::tuapi::mount args {
	set options_list [list]

	for {set idx 0} {$idx < [llength $args]} {incr idx} {
		set curr_arg [lindex $args $idx]

		switch -glob -- $curr_arg {
			"-t" {
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
			}
		}
	}

	set args [lrange $args $idx end]

	if {[llength $args] < 1 || [llength $args] > 2} {
		return -code error "wrong # args: should be \"::system::mount ?options? source ?target?\""
	}

	set source [lindex $args 0]

	if {[llength $args] == 2} {
		set target [lindex $args 1]
	} else {
		array set mountinfo [::system::helper::find_mountpoint $source]
		set source $mountinfo(source)
		set target $mountinfo(target)

		if {![info exists fstype]} {
			set fstype $mountinfo(fstype)
		}








|







|







89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
			}
		}
	}

	set args [lrange $args $idx end]

	if {[llength $args] < 1 || [llength $args] > 2} {
		return -code error "wrong # args: should be \"::tuapi::mount ?options? source ?target?\""
	}

	set source [lindex $args 0]

	if {[llength $args] == 2} {
		set target [lindex $args 1]
	} else {
		array set mountinfo [::tuapi::helper::find_mountpoint $source]
		set source $mountinfo(source)
		set target $mountinfo(target)

		if {![info exists fstype]} {
			set fstype $mountinfo(fstype)
		}

140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
			}
			"norw" {
				set option_lc "ro"
			}
		}

		# Example: noatime
		if {[info exists ::system::_mount_flags($option_lc)]} {
			lappend options_list $::system::_mount_flags($option_lc)

			continue
		}

		# Example: atime
		if {[info exists ::system::_mount_flags(no$option_lc)]} {
			set idx [lsearch -exact $options_list $::system::_mount_flags(no$option_lc)]
			if {$idx != -1} {
				set options_list [lreplace $options_list $idx $idx]
			}

			continue
		}

		# Example: norelatime
		if {[string match "no*" $option_lc]} {
			set neg_option_lc [string range $option_lc 2 end]

			if {[info exists ::system::_mount_flags($neg_option_lc)]} {
				set idx [lsearch -exact $options_list $::system::_mount_flags($neg_option_lc)]
				if {$idx != -1} {
					set options_list [lreplace $options_list $idx $idx]
				}

				continue
			}
		}

		# Accumulate unknown options
		lappend unknown_options $option
	}

	# Use "swapon" if this is swap
	if {$fstype == "swap"} {
		return [::system::syscall::swapon $source]
	}

	# Otherwise, call "mount" system call
	## If we have accumulated any unknown options, pass them as a
	## comma-seperated value string
	if {[info exists unknown_options]} {
		set data [join $unknown_options ","]

		return [::system::syscall::mount $source $target $fstype $options_list $data]
	}

	return [::system::syscall::mount $source $target $fstype $options_list]
}

proc ::system::umount {dir {flags ""}} {
	return [::system::syscall::umount $dir [string toupper $flags]]
}

proc ::system::kill {pid sig} {
	return [::system::syscall::kill $pid [string toupper $sig]]
}

proc ::system::killpg {pgroup sig} {
	if {$pgroup <= 1} {
		return -code error "invalid process group specified (must be greater than 1)"
	}

	return [::system::syscall::kill -$pgroup [string toupper $sig]]
}

proc ::system::ifconfig args {
	if {[llength $args] == 0} {
		# Return information on all interfaces
		set retlist [list]
		foreach interface [::system::syscall::ifconfig] {
			lappend retlist $interface [::system::syscall::ifconfig $interface]
		}

		return $retlist
	}

	set interface [lindex $args 0]
	set args [lrange $args 1 end]

	array set ifaceinfo [::system::syscall::ifconfig $interface]

	if {[llength $args] == 0} {
		return [array get ifaceinfo]
	}

	for {set idx 0} {$idx < [llength $args]} {incr idx} {
		set opt [lindex $args $idx]







|
|





|
|











|
|














|








|


|


|
|


|
|


|




|


|



|
|








|







140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
			}
			"norw" {
				set option_lc "ro"
			}
		}

		# Example: noatime
		if {[info exists ::tuapi::_mount_flags($option_lc)]} {
			lappend options_list $::tuapi::_mount_flags($option_lc)

			continue
		}

		# Example: atime
		if {[info exists ::tuapi::_mount_flags(no$option_lc)]} {
			set idx [lsearch -exact $options_list $::tuapi::_mount_flags(no$option_lc)]
			if {$idx != -1} {
				set options_list [lreplace $options_list $idx $idx]
			}

			continue
		}

		# Example: norelatime
		if {[string match "no*" $option_lc]} {
			set neg_option_lc [string range $option_lc 2 end]

			if {[info exists ::tuapi::_mount_flags($neg_option_lc)]} {
				set idx [lsearch -exact $options_list $::tuapi::_mount_flags($neg_option_lc)]
				if {$idx != -1} {
					set options_list [lreplace $options_list $idx $idx]
				}

				continue
			}
		}

		# Accumulate unknown options
		lappend unknown_options $option
	}

	# Use "swapon" if this is swap
	if {$fstype == "swap"} {
		return [::tuapi::syscall::swapon $source]
	}

	# Otherwise, call "mount" system call
	## If we have accumulated any unknown options, pass them as a
	## comma-seperated value string
	if {[info exists unknown_options]} {
		set data [join $unknown_options ","]

		return [::tuapi::syscall::mount $source $target $fstype $options_list $data]
	}

	return [::tuapi::syscall::mount $source $target $fstype $options_list]
}

proc ::tuapi::umount {dir {flags ""}} {
	return [::tuapi::syscall::umount $dir [string toupper $flags]]
}

proc ::tuapi::kill {pid sig} {
	return [::tuapi::syscall::kill $pid [string toupper $sig]]
}

proc ::tuapi::killpg {pgroup sig} {
	if {$pgroup <= 1} {
		return -code error "invalid process group specified (must be greater than 1)"
	}

	return [::tuapi::syscall::kill -$pgroup [string toupper $sig]]
}

proc ::tuapi::ifconfig args {
	if {[llength $args] == 0} {
		# Return information on all interfaces
		set retlist [list]
		foreach interface [::tuapi::syscall::ifconfig] {
			lappend retlist $interface [::tuapi::syscall::ifconfig $interface]
		}

		return $retlist
	}

	set interface [lindex $args 0]
	set args [lrange $args 1 end]

	array set ifaceinfo [::tuapi::syscall::ifconfig $interface]

	if {[llength $args] == 0} {
		return [array get ifaceinfo]
	}

	for {set idx 0} {$idx < [llength $args]} {incr idx} {
		set opt [lindex $args $idx]
244
245
246
247
248
249
250
251
252
253
254
255
256

				foreach newflag [list UP RUNNING] {
					if {[lsearch -exact $flags $newflag] == -1} {
						lappend flags $newflag
					}
				}

				::system::syscall::ifconfig $interface flags $flags
			}

		}
	}
}







|





244
245
246
247
248
249
250
251
252
253
254
255
256

				foreach newflag [list UP RUNNING] {
					if {[lsearch -exact $flags $newflag] == -1} {
						lappend flags $newflag
					}
				}

				::tuapi::syscall::ifconfig $interface flags $flags
			}

		}
	}
}

Modified test.tcl from [7fb0b14e6d] to [550d4882f7].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#! /usr/bin/env tclsh

puts [exec ./build-dyn.sh]

load ./system.so

::system::syscall::tsmf_start_svc blah /bin/true /tmp/logfile [list PATH=/bin] / 022 root root 10

foreach iface [system::syscall::ifconfig] {
#lo0:2: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
#        inet 127.0.0.1 netmask ff000000 
#aggr100003:1: flags=201000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4,CoS> mtu 1500 index 2
#        inet 140.194.100.149 netmask ffffff00 broadcast 140.194.100.255

	unset -nocomplain ifaceinfo
	array set ifaceinfo [system::syscall::ifconfig $iface]

	set secondline ""
	foreach {label entry} [list inet address netmask netmask broadcast broadcast] {
		if {![info exists ifaceinfo($entry)]} {
			continue
		}

		append secondline " $label $ifaceinfo($entry)"
	}

	puts "$iface: flags=<[join $ifaceinfo(flags) ,]> mtu $ifaceinfo(mtu) index $ifaceinfo(index)"
	puts "\t[string trim $secondline]"
	if {[info exists ifaceinfo(hwaddr)]} {
		puts "\tether $ifaceinfo(hwaddr)"
	}
}

#system::syscall::route add 1.2.3.4 255.255.255.255
system::syscall::ifconfig dummy0 address 1.2.3.4 netmask 255.255.255.0 flags [list UP RUNNING BROADCAST MULTICAST]




|

|

|






|

















|
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#! /usr/bin/env tclsh

puts [exec ./build-dyn.sh]

load ./tuapi.so

::tuapi::syscall::tsmf_start_svc blah /bin/true /tmp/logfile [list PATH=/bin] / 022 0 0 10

foreach iface [tuapi::syscall::ifconfig] {
#lo0:2: flags=2001000849<UP,LOOPBACK,RUNNING,MULTICAST,IPv4,VIRTUAL> mtu 8232 index 1
#        inet 127.0.0.1 netmask ff000000 
#aggr100003:1: flags=201000843<UP,BROADCAST,RUNNING,MULTICAST,IPv4,CoS> mtu 1500 index 2
#        inet 140.194.100.149 netmask ffffff00 broadcast 140.194.100.255

	unset -nocomplain ifaceinfo
	array set ifaceinfo [tuapi::syscall::ifconfig $iface]

	set secondline ""
	foreach {label entry} [list inet address netmask netmask broadcast broadcast] {
		if {![info exists ifaceinfo($entry)]} {
			continue
		}

		append secondline " $label $ifaceinfo($entry)"
	}

	puts "$iface: flags=<[join $ifaceinfo(flags) ,]> mtu $ifaceinfo(mtu) index $ifaceinfo(index)"
	puts "\t[string trim $secondline]"
	if {[info exists ifaceinfo(hwaddr)]} {
		puts "\tether $ifaceinfo(hwaddr)"
	}
}

#tuapi::syscall::route add 1.2.3.4 255.255.255.255
tuapi::syscall::ifconfig dummy0 address 1.2.3.4 netmask 255.255.255.0 flags [list UP RUNNING BROADCAST MULTICAST]