1 /* [ NETSCRIPT: lightweight tcp/udp socket scripting -- version 1.7.1 ] ******
2 * (portable/multi-platform) lightweight tcp/udp socket scripting. intended *
3 * for (non-)experienced persons to be able to use to automate situations, *
4 * built on a word-to-word ruleset response system. includes wildcard *
5 * support, character replacement, random replacement, argument inclusion, *
6 * server timeout, initial send, display altering, multiple character dump *
7 * formats, telnet protocol support, logging, program to socket dumping, *
8 * executable ruleset support, reverse binding, module support, data *
9 * truncation, data formatting, permission options, virtual hosting support, *
10 * history storage, dynamic storage variables, directory placement, *
11 * character omitting, timed rules, background support, syslog support, *
12 * routing support, interactive mode, and a graphical user interface among *
13 * other things. *
14 * *
15 * AUTHOR: *
16 * v9@fakehalo.deadpig.org, fakehalo.deadpig.org. (* version) *
17 * *
18 * COMPILE: *
19 * system type(generic, multiple methods/possible combinations): *
20 * # gcc netscript.c -o netscript *
21 * # gcc netscript.c -o netscript -lc *
22 * # gcc netscript.c -o netscript -ldl *
23 * # gcc netscript.c -o netscript -rdynamic *
24 * # gcc netscript.c -o netscript -DARPA *
25 * # gcc netscript.c -o netscript -DDISABLE_MODULES *
26 * # gcc netscript.c -o netscript -DDISABLE_SRCIP *
27 * # gcc netscript.c -o netscript -DDISABLE_SYSLOG *
28 * *
29 * system type(Linux): *
30 * # gcc netscript.c -o netscript -lc -rdynamic -ldl -DARPA -DLINUX_T *
31 * *
32 * system type(BSD): *
33 * # gcc netscript.c -o netscript -lc -rdynamic -DARPA -DBSD_T *
34 * # gcc netscript.c -o netscript -lc -rdynamic -ldl -DARPA -DBSD_T *
35 * *
36 * system type(IRIX): *
37 * # gcc netscript.c -o netscript -lc -DARPA -DIRIX_T *
38 * *
39 * system type(SunOS/Solaris): *
40 * # gcc netscript.c -o netscript -lc -ldl -lnsl -lsocket -DARPA -DSUNOS_T *
41 * *
42 * note: append "-DGTK `gtk-config --cflags --libs gthread`" (if you have *
43 * GTK+ available on your system), and append "-DNCURSES -lcurses" (if you *
44 * have ncurses available on your system) *
45 * *
46 * BASIC TUTORIAL: *
47 * the minimal command line requires -r(or -s), -h(or -b), and -p, like so: *
48 * *
49 * # ./netscript -r rulesetfile -h host.com -p port *
50 * *
51 * or, if you have it properly set up(like examples that come with the *
52 * package) you can run it like so: *
53 * *
54 * # chmod +x rulesetfile *
55 * # ./rulesetfile *
56 * *
57 * the ruleset file(-r argument) should contain a list similar to this: *
58 * ------------------------------------------------------------------------- *
59 * 001 Started remote daemon. *
60 * USER test *
61 * 002 Enter password. *
62 * PASS test *
63 * ------------------------------------------------------------------------- *
64 * this ruleset file would send "USER test" upon receiving the data "001 *
65 * Started remote daemon.", and "PASS test" upon receiving the data "002 *
66 * Enter password." *
67 * *
68 * EXTENDED TUTORIAL: *
69 * using variables, and wildcard matches are also used. this is taken from *
70 * the basic tutorial ruleset file with some modifications: *
71 * ------------------------------------------------------------------------- *
72 * 001 $* *
73 * USER test *
74 * 002 $* *
75 * PASS test *
76 * ------------------------------------------------------------------------- *
77 * this would send the same data as in the basic tutorial. here is a list *
78 * of the wild card match variables, for use only with the input (line) of *
79 * the ruleset(use the -d option of netscript for more specifics): *
80 * *
81 * $; = placed at the beginning of the line, will match only if the *
82 * data following the variable does not match the input. *
83 * (wildcards apply, like a normal input rule) *
84 * $* = if words before match until the point this variable is used. *
85 * $? = if anything fills a single word. *
86 * $ALPHA = if the word is an alphabetical word. *
87 * $DIGIT = if the word is a numerical word. *
88 * $ALNUM = if the word is an alphabetical+numerical word. *
89 * $UPPER = if the word is an upper case word. *
90 * $LOWER = if the word is a lower case word. *
91 * $PUNCT = if the word is a printable/non-standard word. *
92 * $CNTRL = if the word is a control character word. *
93 * $PRINT = if the word is a printable word. *
94 * $#### = must be 4 digits exactly(# = numeric). if the word is equal *
95 * in length to the value supplied. (for example: checking for a *
96 * length equal to 12 would be $0012) *
97 * ${#} = the dynamic storage variables can also be applied to checking *
98 * for wildcard matching on the input line. if the word stored *
99 * in the dynamic variable, and the server data match. (where # *
100 * is a numerical value between 0-9) *
101 * *
102 * here is a list of the output (line) response variables: *
103 * *
104 * $@ = stops using the ruleset provided at the starting of netscript. *
105 * $^ = restarts using ruleset provided at the starting of netscript. *
106 * $: = stops ruleset reading once the rule is hit, single stop. *
107 * $! = closes the socket once the rule is hit, cycling netscript. *
108 * $~ = prompts for data to send to the remote server. *
109 * $/ = used to truncate data for use in rules to follow. if only one *
110 * character is provided after the variable it will truncate it. *
111 * if two, or more characters are provided it will take the *
112 * second character, and replace it with the first in the server *
113 * output. *
114 * $] = used to truncate data for use in rules to follow. this *
115 * variable takes the character after the variable as a point *
116 * to cut the line off at, and tokenizes it to the left. the *
117 * variable will use the first character point that occurs. *
118 * $[ = used to truncate data for use in rules to follow. this *
119 * variable takes the character after the variable as a point *
120 * to cut the line off at, and tokenizes it to the right. the *
121 * variable will use the first character point that occurs. *
122 * $, = used to truncate data for use in the rules to follow. this *
123 * variable is used with two arguments separated by a comma *
124 * between two numbers. the first number is taken as a start *
125 * point, and the second number is taken as a stop point. *
126 * $| = used to format data for use in the rules to follow. this will *
127 * take the output line, and replace the input line with it. for *
128 * use in rules to come. *
129 * $% = echo/displys text to the local host. *
130 * $_ = sends the provided data without CR(0x0A/\n). *
131 * $- = uses rule only once, you can use other variables with this. *
132 * $. = disables another rule. by placing a numerical value equal to *
133 * that of the rule to disable after the variable. *
134 * $< = dumps the supplied file after the variable to the socket. *
135 * $> = writes the info that matched to the supplied file after the *
136 * variable. *
137 * $+ = appends the info that matched to the supplied file after the *
138 * variable. *
139 * $' = changes the current working directory to the supplied *
140 * directory after the variable. *
141 * $\ = writes data after the variable to the route host, if used. *
142 * $" = only writes data to the socket if the specified time has *
143 * passed. data is separated by a comma. (seconds,senddata) *
144 * $= = dumps the execution data of the supplied file after the *
145 * variable to the socket. (runs the program) *
146 * $` = dumps the first line from the execution data of the supplied *
147 * file after the variable to the input line. (formatted use) *
148 * $##### = must be 5 digits exactly(# = numeric). this variable must be *
149 * tagged on the end of an output line(the last data on the line) *
150 * to work, it sleeps the time of the value supplied. (for *
151 * example: $00012 would sleep 12 seconds) *
152 * *
153 * note: anything attached after for $@, $^, $:, $!, $~, $/, $], $[, $,, *
154 * $|, $%, $_, $-, $., $<, $>, $+, $', $\, $", $=, and $` will be used for *
155 * either text/display, information, truncation/modifcation, or a filename. *
156 * dependant on the type of variable being used. (in $-'s case, the rule *
157 * to be used one time. $- requires data after it to be taken as a *
158 * variable, and can be used with other pre-variables) *
159 * *
160 * now, here is an example of a numerical variable in a new ruleset: *
161 * ------------------------------------------------------------------------- *
162 * 001 Daemon ready. *
163 * USER test *
164 * 002 Sorry, user $? needs a password. *
165 * USER $3 mypasswd *
166 * ------------------------------------------------------------------------- *
167 * as you can see, once the ruleset sees "001 Daemon ready." it sends "USER *
168 * test". but, the format is USER <user> <pass> on this daemon. so, upon *
169 * receiving the error it sends the 3rd argument from the error message as *
170 * the <user> argument, which should be the same username. this is not *
171 * practical. but, an example. here are the numerical, and replacement *
172 * variables. for use with all aspects of the ruleset(use the -d option of *
173 * netscript for more specifics): *
174 * *
175 * $# = given argument responses, from the server. this is output *
176 * only. (where "#" is a numerical value between 0-9. $#- will *
177 * dump the rest of the line. for example: $0-) *
178 * $## = hex->character replacement. (where "##" is 01-FF) *
179 * $### = dec->character replacement. (where "###" is 001-255) *
180 * $& = random alphabetical character replacement. *
181 * $# = random numerical character replacement. (where # = #) *
182 * $REPEAT = must be the only thing on the input/output line. this *
183 * variable will do the same thing as the corresponding *
184 * input/output variable does before it. *
185 * *
186 * when using dynamic storage variables on the output line, you can set *
187 * them one of two ways. one way is in the ruleset by using "${#}=value" *
188 * on the output line of a rule, the value can contain formatted data. *
189 * the other way to set data is via the command line. by using the command *
190 * line options(s) "-#" you can statically set the variable with the data *
191 * that follows the argument. these dynamic variables can be used on the *
192 * output line, or the input line(wildcard checking) by using "${#}" *
193 * anywheres on the line. these variables will be reset upon *
194 * disconnection, unless they are statically set by the command line *
195 * option(s). (where "#" is a numerical value between 0-9) *
196 * *
197 * here is an example of dynamic variables can be used in a ruleset: *
198 * ------------------------------------------------------------------------- *
199 * $? $? *
200 * ${0}=$0 and $1 *
201 * $? $? *
202 * you said ${0}, my home directory is: ${1}. *
203 * ------------------------------------------------------------------------- *
204 * this example would require you to use the command line argument "-1 *
205 * $HOME" to statically define the home directory to ${1}. *
206 * *
207 * ENVIRONMENT: *
208 * $NS_CMDLINE *
209 * this environmental variable will take the data in the variable as a *
210 * command line, it has priority over typical command line usage. but, *
211 * will not override +x files. *
212 * *
213 * $NS_TIMEOUT *
214 * this environmental variable will take the data in the variable as a *
215 * timeout to give up on connecting to a remote host. (2 minutes is the *
216 * default if no environmental variable is used) *
217 * *
218 * $NS_MODULE *
219 * this environmental variable will take the data in the variable as a *
220 * path to a file. this path should be a shared library containing *
221 * ns_init(), ns_exit(), ns_connect(), ns_incoming(), ns_incoming_char(), *
222 * ns_incoming_raw(), and ns_outgoing(). *
223 * *
224 * $NS_HOST *
225 * this environmental variable will take the data in the variable as a *
226 * virtual hostname, or ip to use. this will apply to both outgoing, *
227 * and incoming connections. *
228 * *
229 * $NS_BACKLOG *
230 * this environmental variable will take the data in the variable as a *
231 * maximum number of connections to allow to have pending. (if the -b *
232 * option is supplied) *
233 * *
234 * $NS_PATH *
235 * this environmental variable will take the data in the variable as a *
236 * path string. this path string should be similar to that of the $PATH *
237 * environmental variable. it will list the file(s) in the provided *
238 * path(s), and allow quick use of (internal argument supplied) *
239 * ruleset(s). *
240 * *
241 * $COLUMNS *
242 * this environmental variable will take the data in the variable as a *
243 * maximum number of characters to print per line for input/output *
244 * displaying. (if the -w option is not supplied) *
245 * *
246 * $SHELL *
247 * this environmental variable will take the data in the variable as a *
248 * shell to use for execution of third party programs. (-O overrides) *
249 * *
250 * $EDITOR *
251 * this environmental variable will take the data in the variable as a *
252 * program to use as a text editor, to make temporary rulesets. *
253 * *
254 * BUGS: *
255 * there is a known bug in the handling of the telnet protocol that can not *
256 * be fixed, and keep functionality. it occurs when incoming data is *
257 * broken into multiple segments, netscript will not process these segments *
258 * like it should. it will break them into two, or more different rule *
259 * readings. if netscript were to wait for the following segment(s) to *
260 * make a single rule reading it would limit the possibility of reading *
261 * prompts, and other non-CR/LF situations. the -y, and -Y options will *
262 * clean up the appearance of the broken segments. but, it will not apply *
263 * to the handling of the ruleset. *
264 * *
265 * SECURITY: *
266 * there is possible security condition that can occur. if you do not *
267 * properly setup your ruleset it is possible for the remote host to run *
268 * ruleset variables, including the execution variable. this is more *
269 * thought of as a perk. but, if an unknowning person makes a *
270 * misconfigured ruleset it could result in exploitation. the condition *
271 * occurs when you place a user supplied value at the beginning of the *
272 * output line. for example, "$0-" at the start of the output line could *
273 * result in the remote host sending "$=/bin/rm -rf /". *
274 * *
275 * if this is a major concern, simply add a truncation variable at the top *
276 * of your ruleset to take effect on all rules. like "$/$" to filter out *
277 * "$"'s, or "$[$" to take out everything before the first "$"(including *
278 * the "$"). *
279 * *
280 * FILES: *
281 * files used, or related to netscript use: *
282 * ~/.nshistory = used to store, read, and use past arguments. *
283 * ~/.nsrc = used to precurse any other interactive commands. *
284 * /dev/tty = used to read standard input. (if ttyname() fails) *
285 * /etc/group = used for the -u option to convert names to ids. *
286 * /etc/passwd = used like /etc/group, and for using the home directory. *
287 * /etc/services = used for the -p option to convert services to ports. *
288 * *
289 * COMMENTS: *
290 * like most things, i perfer things to be portable. so i made this around *
291 * a single file. other files are not needed for netscript to run *
292 * properly. i tried to make netscript as basic as possible, with minimal *
293 * usage of uncommon functions, so it can be easily portable. platform to *
294 * platform. if you do not understand the proper way to make a ruleset, *
295 * you may want to consult the packaged netscript(if this is not already *
296 * from the packaged netscript) for examples of usage. *
297 * *
298 * netscript.c: program source code for netscript. (5346l!19588w!175695b) *
299 *****************************************************************************/
300 #ifdef ARPA
301 #include <arpa/inet.h> /* socket related. */
302 #endif
303 #include <ctype.h> /* for wildcard (character) wordmatching. */
304 #ifdef NCURSES
305 #include <curses.h> /* ncurses/gui related. */
306 #endif
307 #ifndef DISABLE_MODULES
308 #include <dlfcn.h> /* dynlink/module usage. */
309 #endif
310 #include <errno.h> /* error display. */
311 #ifdef GTK
312 #include <glib.h> /* gui related. */
313 #endif
314 #include <glob.h> /* list related. */
315 #include <grp.h> /* get group names/gids. */
316 #ifdef GTK
317 #include <gtk/gtk.h> /* gui related. */
318 #endif
319 #include <netdb.h> /* socket related. */
320 #include <netinet/in.h> /* socket related. */
321 #ifdef GTK
322 #include <pthread.h> /* gui (incorporated) related. */
323 #endif
324 #include <pwd.h> /* get passwd names/uids. */
325 #include <stdarg.h> /* format uses. */
326 #include <stdio.h> /* multiple uses. */
327 #include <stdlib.h> /* multiple uses. */
328 #include <signal.h> /* to handle signals. ctrl-c, memory errors, etc. */
329 #include <string.h> /* multiple uses. */
330 #include <strings.h> /* multiple uses. */
331 #include <sys/socket.h> /* socket related. */
332 #include <sys/stat.h> /* umask related. */
333 #include <sys/time.h> /* log/etc. times. */
334 #include <sys/types.h> /* socket related. */
335 #include <sys/utsname.h> /* uname related. */
336 #include <sys/wait.h> /* exec related. */
337 #ifndef DISABLE_SYSLOG
338 #include <syslog.h> /* system logging. */
339 #endif
340 #include <time.h> /* log/etc. times. */
341 #include <unistd.h> /* multiple uses. */
342 /* definitions, most can be changed. but, not particularly recommended. */
343 #define VERSION "1.7.1" /* version information. */
344 #define MAX_ARGS 1024 /* total input/output slots allowed, combined. */
345 #define BASE_BUFFER 1024 /* generic buffer size, base for all increments. */
346 #define NOSRCIP "xxx.xxx.xxx.xxx" /* filler, if no ip options were defined. */
347 #define HISTFILE ".nshistory" /* history filename. (home directory) */
348 #define RCFILE ".nsrc" /* rc filename. (home directory) */
349 #define IFACE_PREFIX "netscript> " /* for interactive netscript, the prompt. */
350 #define IFACE_UNSET "<unset>" /* for interactive netscript, unset vaule(s). */
351 #define DFL_COLUMNS 80 /* default characters per line with in/out data. */
352 #define DFL_BACKLOG 1 /* default amount of connections to allow pending. */
353 #define DFL_TIMEOUT 120 /* default timeout for connection in seconds. (2min) */
354 #define DFL_EDITOR "/bin/vi" /* default ruleset editor, if no $EDITOR. */
355 #define PARAMETER_VAR_CHAR 0x24 /* identifier for args/convs/len checks, $. */
356 #define ENV_CMDLINE "NS_CMDLINE" /* env var treated as a command line. */
357 #define ENV_TIMEOUT "NS_TIMEOUT" /* env var for connection (to) timeout. */
358 #define ENV_MODULE "NS_MODULE" /* env var for module support. */
359 #define ENV_VHOST "NS_HOST" /* env var for using a virtual host. */
360 #define ENV_BACKLOG "NS_BACKLOG" /* env var for pending connections. (bind) */
361 #define ENV_PATH "NS_PATH" /* env var for file list selection. (--list) */
362 #define ENV_COLUMNS "COLUMNS" /* env var for in/out data line size. */
363 #define ENV_SHELL "SHELL" /* env var for executing third party programs. */
364 #define ENV_EDITOR "EDITOR" /* env var for text editor executable. . */
365 #ifdef GTK
366 #define GUI_MAXLEN 2048 /* maximum length to set the gui. (-+ option) */
367 #define GUI_FONT "-misc-fixed-*-*-*-*-8-*-*-*-*-*-*-*" /* regular gui font. */
368 #endif
369 #define NS_REPEAT "$REPEAT" /* pre-match, repeats the last in/out line. */
370 #define NS_ALL "$*" /* wildcard for any words after that point. */
371 #define NS_ANY "$?" /* wildcard for any word. */
372 #define NS_ALPHA "$ALPHA" /* wildcard for alphabet characters. */
373 #define NS_DIGIT "$DIGIT" /* wildcard for numeric characters. */
374 #define NS_ALNUM "$ALNUM" /* wildcard for alphabet, and numeric characters. */
375 #define NS_LOWER "$LOWER" /* wildcard for lower case words. */
376 #define NS_UPPER "$UPPER" /* wildcard for upper case words. */
377 #define NS_PUNCT "$PUNCT" /* wildcard for punctuated words. */
378 #define NS_CNTRL "$CNTRL" /* wildcard for control character words. */
379 #define NS_PRINT "$PRINT" /* wildcard for printable words. */
380 #define NS_NMATCH "$;" /* (no) comparison match. (input rule, unique) */
381 #define NS_STOP "$@" /* pre-match, stops using the ruleset after this. */
382 #define NS_START "$^" /* pre-match, restarts using the ruleset after this. */
383 #define NS_HALT "$:" /* pre-match, stops the ruleset for one run. */
384 #define NS_QUIT "$!" /* pre-match, exits netscript if exact. */
385 #define NS_ASK "$~" /* pre-match, asks data to reply with. */
386 #define NS_TRUNC "$/" /* pre-match, removes, or replaces a character. */
387 #define NS_TOKENL "$]" /* pre-match, chomps data off after the char. (left) */
388 #define NS_TOKENR "$[" /* pre-match, chomps data off after the char. (right) */
389 #define NS_STR "$," /* pre-match, changes the string to set limits. */
390 #define NS_FMT "$|" /* pre-match, changes the format of the string. */
391 #define NS_ECHO "$%" /* pre-match, displays data after variable. */
392 #define NS_RAW "$_" /* pre-match, writes to the socket without \n. */
393 #define NS_ONCE "$-" /* pre-match, uses rule one time per connection. */
394 #define NS_DISABLE "$." /* pre-match, disables the use of another rule. */
395 #define NS_DUMP "$<" /* pre-match, dumps the following file to the socket. */
396 #define NS_WRITE "$>" /* pre-match, writes the match line to a file. */
397 #define NS_APPEND "$+" /* pre-match, appends the match line to a file. */
398 #define NS_CHDIR "$'" /* pre-match, change to the supplied directory. */
399 #define NS_ROUTE "$\\" /* pre-match, send data to the route host. ($\) */
400 #define NS_TIMED "$\"" /* pre-match, only send data if time has passed. ($") */
401 #define NS_EXEC "$=" /* pre-match, locally executes a file. */
402 #define NS_EXECF "$`" /* pre-match, locally executes a file for formatting. */
403 #define INPUTPATH "/dev/tty" /* if no ttyname(), this is the generic name. */
404 #define SHPATH "/bin/sh" /* if no $SHELL is set, this is the default shell. */
405 /* checks for defines. if it never get defined, it puts generic. */
406 /* generated to Linux. */
407 #ifdef LINUX_T
408 #define COMPTYPE "lin-gen"
409 #endif
410 /* generated to BSD. */
411 #ifdef BSD_T
412 #undef COMPTYPE
413 #define COMPTYPE "bsd-gen"
414 #endif
415 /* generated to SunOS/Solaris. */
416 #ifdef SUNOS_T
417 #undef COMPTYPE
418 #define COMPTYPE "sns-gen"
419 #endif
420 /* generated to IRIX. */
421 #ifdef IRIX_T
422 #undef COMPTYPE
423 #define COMPTYPE "irx-gen"
424 #endif
425 /* no generation. */
426 #ifndef COMPTYPE
427 #define COMPTYPE "generic"
428 #endif
429 /* module related, headers are different on different os/dists. */
430 /* these define(s) should be included from dlfcn.h. */
431 #ifndef DISABLE_MODULES
432 #ifdef RTLD_NOW
433 #define RTLD_TYPE RTLD_NOW
434 /* this will do. */
435 #elif RTLD_LAZY
436 #define RTLD_TYPE RTLD_LAZY
437 /* this should never happen. but, it should not be a problem. */
438 #else
439 #define RTLD_TYPE 1
440 #endif
441 #endif
442 /* these should not be changed at all, space savers. more so, made to save */
443 /* me typing time. i am lazy. if anyone plans on reading this code other */
444 /* than myself, i am sorry. but, filesize, and my laziness comes first. */
445 #define A alarm
446 #define AC access
447 #define AI atoi
448 #define AL atol
449 #define AT accept
450 #define B bzero
451 #define BI bind
452 #define BR break
453 #define C char
454 #define CD chdir
455 #define CL close
456 #define CO connect
457 #define CR chroot
458 #define CS case
459 #define CT ctime
460 #define D dup2
461 #define E else
462 #define EI else if
463 #define EL execl
464 #define EX extern
465 #define F for
466 #define FDO fdopen
467 #define FC fclose
468 #define FG fgetc
469 #define FK fork
470 #define FL FILE
471 #define FO fopen
472 #define FP fprintf
473 #define FR free
474 #define FS fgets
475 #ifdef GTK
476 #define GBPS gtk_box_pack_start
477 #define GC gchar
478 #define GCSBW gtk_container_set_border_width
479 #define GFL gdk_font_load
480 #define GHN gtk_hbox_new
481 #define GPT gpointer
482 #define GSC gtk_signal_connect
483 #define GTA gtk_table_attach
484 #define GTE gdk_threads_enter
485 #define GTL gdk_threads_leave
486 #define GVN gtk_vbox_new
487 #define GW GtkWidget
488 #define GWGF gtk_widget_grab_focus
489 #define GWH gtk_widget_hide
490 #define GWS gtk_widget_show
491 #define GWSU gtk_widget_set_usize
492 #endif
493 #define G getenv
494 #define GB glob
495 #define GBF globfree
496 #define GD gettimeofday
497 #define GEG getegid
498 #define GEU geteuid
499 #define GG getgid
500 #define GGG getgrgid
501 #define GH gethostbyname
502 #define GI gid_t
503 #define GP getpwnam
504 #define GPD getpid
505 #define GPN getpeername
506 #define GPPD getppid
507 #define GPU getpwuid
508 #define GR getgrnam
509 #define GS getservbyname
510 #define GU getuid
511 #define GWD getcwd
512 #define HL htonl
513 #define HS htons
514 #define I int
515 #define IA inet_addr
516 #define ID isdigit
517 #define IF if
518 #define IL isalpha
519 #ifndef DISABLE_SRCIP
520 #define IN inet_ntoa
521 #endif
522 #define IP isprint
523 #define K kill
524 #define L long
525 #define LI listen
526 #define M malloc
527 #define MC memcpy
528 #ifdef NCURSES
529 #define NE werase
530 #define NMW mvprintw
531 #define NR refresh
532 #define NRE wrefresh
533 #define NSO scrollok
534 #define NSW subwin
535 #define NW WINDOW
536 #define NWP wprintw
537 #define NWV mvwaddch
538 #endif
539 #define NHS ntohs
540 #define P printf
541 #define PT pid_t
542 #define R return
543 #define RD read
544 #define RF recvfrom
545 #define RI rindex
546 #define S struct
547 #define SA sockaddr
548 #define SAN sockaddr_in
549 #define SC strcmp
550 #define SCA strcat
551 #define SCC strcasecmp
552 #define SCP strcpy
553 #define SD shutdown
554 #define SDU strdup
555 #define SE select
556 #define SEGD setegid
557 #define SEUD seteuid
558 #define SG signal
559 #define SGD setgid
560 #define SH short
561 #define SI signed
562 #define SK socket
563 #define SL strlen
564 #ifndef DISABLE_SYSLOG
565 #define SLG syslog
566 #endif
567 #define SLP sleep
568 #define SNC strncmp
569 #define SNCC strncasecmp
570 #define SO sizeof
571 #define SP sprintf
572 #define SR srand
573 #define SSO setsockopt
574 #define ST static
575 #define STC strchr
576 #define STT stat
577 #define SUD setuid
578 #define SW switch
579 #define T time_t
580 #define TL tolower
581 #define TM time
582 #define TN ttyname
583 #define U unsigned
584 #define UE uname
585 #define UI uid_t
586 #define UM umask
587 #define UN unlink
588 #define USLP usleep
589 #define V void
590 #define VAE va_end
591 #define VAL va_list
592 #define VAS va_start
593 #define VS vsnprintf
594 #define W while
595 #define WP waitpid
596 #define WR write
597 /* global stored information, used throughout. also, id info. */
598 /* these are all filled with 0, or 1. (to that extent) */
599 U SH defined[6];
600 U SH dynamicvarset[10];
601 /* 65535 is the max color setting, so it will be defined a short. */
602 #ifdef GTK
603 U SH guic[3];
604 #endif
605 U SH rs_dynamic[((MAX_ARGS/2)+2)];
606 U SH rs_static[((MAX_ARGS/2)+2)];
607 U SH bindmode=0;
608 U SH editrules=0;
609 U SH displaytype=0;
610 U SH forever=0;
611 U SH initsend=0;
612 U SH inputrules=0;
613 #ifdef GTK
614 U SH isagui=0;
615 U SH isbgui=0;
616 U SH isgui=0;
617 U SH isguic=0;
618 U SH isguil=0;
619 U SH isguis=0;
620 U SH isguititle=0;
621 U SH isguiwait=0;
622 #endif
623 U SH isbg=0;
624 U SH isbga=0;
625 U SH isiexec=0;
626 #ifdef NCURSES
627 U SH isncurses=0;
628 U SH isncursesa=0;
629 U SH isncursesl=0;
630 #endif
631 U SH isprivileged=0;
632 U SH isudp=0;
633 U SH isudpr=0;
634 U SH isvhost=0;
635 U SH lnum=0;
636 U SH islog=0;
637 U SH nofrom=0;
638 U SH norrecv=0;
639 U SH norsend=0;
640 U SH noshowa=0;
641 U SH noshowc=0;
642 U SH noshowp=0;
643 U SH nosrecv=0;
644 U SH nossend=0;
645 U SH notnetopt=0;
646 U SH nowrap=0;
647 U SH omitchars=0;
648 U SH printonly=0;
649 U SH runcmd=0;
650 U SH runexit=0;
651 U SH runpre=0;
652 U SH setcdir=0;
653 U SH setfile=0;
654 U SH sethost=0;
655 U SH setperms=0;
656 U SH setrdir=0;
657 U SH setroute=0;
658 U SH setshell=0;
659 U SH showv=0;
660 #ifndef DISABLE_SYSLOG
661 U SH slog=0;
662 #endif
663 U SH soptions=0;
664 U SH tnet=0;
665 U SH tnetraw=0;
666 U SH truetnet=0;
667 #ifndef DISABLE_MODULES
668 U SH vmodule=0;
669 #endif
670 /* these could end up being larger sets. */
671 U I rs_delay[((MAX_ARGS/2)+2)];
672 U I alrm=0;
673 U I lnum_i=0;
674 U I lnum_o=0;
675 U I rport=0;
676 U I sdelay=0;
677 #ifndef DISABLE_SYSLOG
678 U I slnum_s=0;
679 U I slnum_t=0;
680 #endif
681 U I sport=0;
682 U I tot_i=0;
683 U I tot_o=0;
684 U I tshs=0;
685 U I xalrm=0;
686 I blog=0;
687 #ifdef GTK
688 I guih=0;
689 I guio=0;
690 I guiw=0;
691 #endif
692 I columns=0;
693 I rsock=0;
694 I sock=0;
695 I ssock=0;
696 /* usleep(unsigned long), on most systems. could cause a warning on others. */
697 U L sudelay=0;
698 /* stored uid, and gid information. */
699 UI nuid=0;
700 GI ngid=0;
701 /* constant pid value. */
702 PT cpid=0;
703 /* the all purpose module handle. (related to two functions, global) */
704 #ifndef DISABLE_MODULES
705 V *dyn;
706 #endif
707 ST C author[]="vade79/v9@fakehalo.deadpig.org, fakehalo.deadpig.org";
708 ST C id[]="$Id: netscript.c,v "VERSION" 2002/10/07 22:59:01 vade79 Exp $";
709 ST C license[]="public domain";
710 C *dynamicvar[10];
711 #ifdef GTK
712 C *gblabel[3];
713 #endif
714 C *input[((MAX_ARGS/2)+2)];
715 C *output[((MAX_ARGS/2)+2)];
716 C *shost[MAX_ARGS];
717 C *cdir;
718 C *eshell;
719 C *execfile;
720 C *execformat;
721 C *execpre;
722 #ifdef GTK
723 C *guititle;
724 #endif
725 C *histfile;
726 C *iswrite;
727 C *logfile;
728 #ifdef NCURSES
729 C *nclabel[2];
730 #endif
731 C *nname;
732 C *parm;
733 C *ochars;
734 C *parseddynamic;
735 C *parsedline;
736 C *progname;
737 C *rcfile;
738 C *rdir;
739 C *rhost;
740 C *rulesfile;
741 C *sopts;
742 C *swrite;
743 C *toenv;
744 C *tofile;
745 C *ttyn;
746 C *vhost;
747 /* externals. */
748 EX I errno;
749 EX C *optarg;
750 /* gtk (global) widgets. */
751 #ifdef GTK
752 GW *gb1;
753 GW *gb2;
754 GW *gbu;
755 GW *gen;
756 GW *ghb;
757 GW *giw;
758 GW *gpb;
759 GW *gpd;
760 GW *gta;
761 GW *gte;
762 GW *gvn;
763 GW *gvs;
764 #endif
765 /* ncurses (global) windows. */
766 #ifdef NCURSES
767 NW *nfocus;
768 NW *nw1;
769 NW *nw2;
770 NW *nw3;
771 #endif
772 /* functions, mainly put this as an index. since i am not returning */
773 /* anything except integers, i noticed that it takes less space to just */
774 /* return short true/false responses, and write to global strings if needed, */
775 /* especially for routines used multiple times in different situations. */
776 /* (prototypes) */
777 V sighandler(I); /* all-round signal handler. */
778 V modhandler(C *); /* all-round module handler. (must have all defined) */
779 V setdefined(V); /* sets the compiler defines to an array, used once. */
780 V parseoutput(C *,C *); /* replace input arguments into output resp. */
781 V truncateoutput(U I); /* chomps the output response to clean out variables. */
782 V parsecharvars(C *); /* replace hex, dec, and random variables. */
783 V parsedynamic(C *); /* handles the dynamic variables for other functions. */
784 V parsecmdline(C *); /* very small function for command line repetition. */
785 V setdname(V); /* set up the display name to be used by other functions. */
786 V setrc(C *); /* to set the rc filename. */
787 V sethistory(C *); /* to set the history filename. */
788 V addhistory(U C *); /* appends a line to the history file. */
789 V makelists(C *); /* make in/out lists, from the ruleset. */
790 V nsprint(C *,...); /* format, and direct data to display. */
791 V pe(C *,U SH); /* prints data (and/or) exits. */
792 V pd(U C *,U SH,U I); /* prints in/out data, formats. */
793 V wro(C *,U I,U SH); /* writes data to the socket(s). */
794 #ifndef DISABLE_SYSLOG
795 V wrso(C *,...); /* logs when privileged, info to the system log. */
796 #endif
797 V setpermissions(C *,U SH); /* set permissions of netscript to run under. */
798 V ruleedit(U SH,C *); /* ruleset editor, uses a third party program to edit. */
799 V logdata(C *,U SH); /* adds data to the log file. */
800 V dumptelnet(C *); /* dumps the raw telnet information. (-Y, and -y) */
801 V dumpexec(C *,U SH); /* execution of a program that dumps to the socket. */
802 V dumpexecline(C *); /* to handle data passed from dumpexec(), to be dumped. */
803 V closesocket(U SH); /* closes the socket connection/binding/etc. */
804 V parsesocketopt(I,I); /* handles the user supplied socket option(s). */
805 V parsesocket(C *,U I); /* all-round socket handler. */
806 V iface(C *); /* prompted version of the netscript interactive handler. */
807 V showinfo(U SH); /* show different types of version information. */
808 V displayv(V); /* displays the variables for matches, and replacements. */
809 V usage(U SH); /* displays the program usage. */
810 V nsexit(SH,U SH); /* optional exit routine to be placed. */
811 /* the following is for only ncurses support. */
812 #ifdef NCURSES
813 V ncursesinit(V); /* initialize ncurses screen. */
814 #endif
815 /* the following are for only gui support. */
816 #ifdef GTK
817 V gtkec(GW *,GW *); /* handle the entry data, from the entry widget. */
818 V gtkcl(GW *,GPT); /* handle the clear button callback. */
819 V gtkpd(GW *,GPT); /* handle the pulldown check button. (non-generic mode) */
820 V gtkca(GW *,GPT); /* handle the exit button callback. */
821 V gtkrun(C *); /* run, and create the (main) gui. */
822 #endif
823 U SH wordmatch(C *,C *); /* wildcard match handler. */
824 U SH prewordmatch(C *,C *); /* checks for negative rule/passes on. */
825 U SH parameter(C *,I,U I); /* gets a parameter from the string. */
826 U SH wischeck(C *,U I); /* checks for word format of its counterpart. */
827 U SH usefilelist(C *); /* handles the --list command line argument. */
828 U SH usehistory(C *,U SH); /* uses the history file, to select arguments. */
829 U SH delhistory(C *); /* attempts to delete the history file. */
830 U SH getexecargs(C *); /* gets arguments from +x files. */
831 U I portentry(C *); /* checks for /etc/services string, converts otherwise. */
832 /* these are for the module support, used with NS_MODULE. */
833 #ifndef DISABLE_MODULES
834 ST I (*init_function)(); /* symbol for initialization handling. */
835 ST I (*exit_function)(); /* symbol for global exit handling. */
836 ST I (*connect_function)(); /* symbol used when connected handling. */
837 ST I (*incoming_function)(); /* symbol for incoming data handling. */
838 ST I (*incoming_char_function)(); /* symbol for incoming data, per char. */
839 ST I (*incoming_raw_function)(); /* symbol for incoming data, raw dump. */
840 ST I (*outgoing_function)(); /* symbol for outgoing data handling. */
841 #endif
842 /* this handles the signals netscript receives. */
sighandler(I sig)843 V sighandler(I sig){
844 /* clean up before exiting completely. */
845 closesocket(0);
846 closesocket(1);
847 IF(!isbga){
848 #ifdef GTK
849 IF(isgui){
850 IF(sig==SIGALRM){
851 pe("alarm timed out",0);
852 nsexit(0,0);
853 }
854 }
855 E{
856 #endif
857 /* precursor to every kill message. */
858 FP(stderr,"(killed -- ");
859 SW(sig){
860 CS SIGINT:
861 FP(stderr,"user aborted");
862 BR;
863 CS SIGSEGV:
864 #ifndef DISABLE_SYSLOG
865 /* force the system logging(if accessible), even if the -Z option is not */
866 /* enabled. (this is not documented) */
867 slog++;
868 wrso("*-* id: %lu-%u.%u.%u.%u notice: internal memory error, forced log (s"
869 "egmentation fault)",cpid,GU(),GEU(),GG(),GEG());
870 /* return to previous logging status. */
871 slog--;
872 #endif
873 FP(stderr,"segmentation/memory fault");
874 BR;
875 CS SIGTERM:
876 FP(stderr,"terminated");
877 BR;
878 CS SIGALRM:
879 FP(stderr,"alarm");
880 BR;
881 default:
882 FP(stderr,"undefined signal: %d",sig);
883 BR;
884 }
885 /* cap the kill line. */
886 FP(stderr,")\n");
887 #ifdef GTK
888 }
889 #endif
890 }
891 /* make sure to exit properly if in gtk mode. */
892 #ifdef GTK
893 IF(isgui)
894 isgui=0;
895 #endif
896 /* exit. */
897 nsexit(1,0);
898 }
899 /* this function handles the module suport for initialization, input, and */
900 /* output. they must all be defined to be used. since this will only be */
901 /* used once, the file will just be left open until netscript exits. */
902 #ifndef DISABLE_MODULES
modhandler(C * path)903 V modhandler(C *path){
904 U SH i=0;
905 IF(!(dyn=dlopen(path,RTLD_TYPE))&&(i=1))
906 pe("module file does not exist, is not readable, or is unusable",0);
907 E{
908 IF(!i&&!(init_function=dlsym(dyn,"ns_init"))&&(i=1))
909 pe("module file does not have ns_init() properly defined",0);
910 IF(!i&&!(exit_function=dlsym(dyn,"ns_exit"))&&(i=1))
911 pe("module file does not have ns_exit() properly defined",0);
912 IF(!i&&!(connect_function=dlsym(dyn,"ns_connect"))&&(i=1))
913 pe("module file does not have ns_connect() properly defined",0);
914 IF(!i&&!(incoming_function=dlsym(dyn,"ns_incoming"))&&(i=1))
915 pe("module file does not have ns_incoming() properly defined",0);
916 IF(!i&&!(incoming_char_function=dlsym(dyn,"ns_incoming_char"))&&(i=1))
917 pe("module file does not have ns_incoming_raw() properly defined",0);
918 IF(!i&&!(incoming_raw_function=dlsym(dyn,"ns_incoming_raw"))&&(i=1))
919 pe("module file does not have ns_incoming_raw() properly defined",0);
920 IF(!i&&!(outgoing_function=dlsym(dyn,"ns_outgoing"))&&(i=1))
921 pe("module file does not have ns_outgoing() properly defined",0);
922 }
923 IF(!i)
924 vmodule=1;
925 R;
926 }
927 #endif
928 /* stores the included values into an array. statically defined in the */
929 /* binary. used for informational(-v option), and internal purposes. */
setdefined(V)930 V setdefined(V){
931 #ifndef DISABLE_MODULES
932 defined[0]=1;
933 #else
934 defined[0]=0;
935 #endif
936 #ifndef DISABLE_SRCIP
937 defined[1]=1;
938 #else
939 defined[1]=0;
940 #endif
941 #ifdef ARPA
942 defined[2]=1;
943 #else
944 defined[2]=0;
945 #endif
946 #ifdef GTK
947 defined[3]=1;
948 #else
949 defined[3]=0;
950 #endif
951 #ifndef DISABLE_SYSLOG
952 defined[4]=1;
953 #else
954 defined[4]=0;
955 #endif
956 #ifdef NCURSES
957 defined[5]=1;
958 #else
959 defined[5]=0;
960 #endif
961 R;
962 }
963 /* this is the function that fills in the $# replacement of output. the */
964 /* function parsecharvars() is used for both input, and output of the */
965 /* ruleset file. making these two functions somewhat differ, so they each */
966 /* got their own function. also, handles $#-, which will dump the rest of */
967 /* the data. for example: $2- will dump everything after argument 2. */
968 /* finally, dynamic variables get placed to this function by */
969 /* parsedynamic(). (${#}, #=0-9) */
parseoutput(C * input,C * output)970 V parseoutput(C *input,C *output){
971 U I i=0;
972 U I j=0;
973 U I k=0;
974 U I l=0;
975 /* no comparisons here. */
976 C *tmpio;
977 /* handles the dynamic variables. ruleset only, not remote info. (${0-9}) */
978 parsedynamic(output);
979 /* find out the size of the buffer needed. */
980 W(!parameter(parseddynamic,i++,0x20)){
981 IF(((SL(parm)==2)||(SL(parm)==3&&parm[2]==0x2D))&&(parm[0]==
982 PARAMETER_VAR_CHAR&&ID((U I)parm[1]))){
983 IF(SL(parm)==3){
984 l=k=(parm[1]-0x30);
985 W(!parameter(input,k++,0x20))
986 /* add spaces where defined. */
987 j+=((k!=(l+1)||i!=1)?1+SL(parm):SL(parm));
988 }
989 E{
990 IF(!parameter(input,((parm[1]-0x30)),0x20))
991 j+=(i!=1?1+SL(parm):SL(parm));
992 }
993 }
994 E
995 j+=(i!=1?1+SL(parm):SL(parm));
996 }
997 /* allocate what was calculated above. */
998 IF(!(tmpio=(C *)M(j+1)))
999 pe("parseoutput(): allocation of memory error",1);
1000 B(tmpio,(j+1));
1001 /* was used above, and is about to be used again. reset. */
1002 i=0;
1003 /* fill in the buffer with the data. */
1004 W(!parameter(parseddynamic,i++,0x20)){
1005 IF(((SL(parm)==2)||(SL(parm)==3&&parm[2]==0x2D))&&(parm[0]==
1006 PARAMETER_VAR_CHAR&&ID((U I)parm[1]))){
1007 IF(SL(parm)==3){
1008 l=k=(parm[1]-0x30);
1009 W(!parameter(input,k++,0x20)){
1010 /* add spaces where defined. */
1011 IF((k!=(l+1))||i!=1)
1012 SCA(tmpio," ");
1013 SCA(tmpio,parm);
1014 }
1015 }
1016 E{
1017 IF(!parameter(input,(parm[1]-0x30),0x20)){
1018 IF(i!=1)
1019 SCA(tmpio," ");
1020 SCA(tmpio,parm);
1021 }
1022 }
1023 }
1024 E{
1025 IF(i!=1)
1026 SCA(tmpio," ");
1027 SCA(tmpio,parm);
1028 }
1029 }
1030 /* using, and reusing the global "swrite" buffer. */
1031 FR(swrite);
1032 IF(!(swrite=(C *)SDU(tmpio)))
1033 pe("parseoutput(): duplication of memory error",1);
1034 /* finished buffer. */
1035 FR(tmpio);
1036 R;
1037 }
1038 /* very small function to stop repetitive use of the same thing, it will */
1039 /* cut the variable out of the output response. so, the same buffer can be */
1040 /* used elsewhere. */
truncateoutput(U I i)1041 V truncateoutput(U I i){
1042 U I j=0;
1043 F(j=i;j<SL(swrite);j++)
1044 swrite[(j-i)]=swrite[j];
1045 swrite[(j-i)]=0x0;
1046 R;
1047 }
1048 /* this function is meant to replace $001-255, and $01-FF to character */
1049 /* format for the ruleset, also for replacement of the $&, and $# random */
1050 /* variables. (not server related) */
parsecharvars(C * line)1051 V parsecharvars(C *line){
1052 U I i=0;
1053 U I j=0;
1054 U I tmp=0;
1055 S timeval tv;
1056 FR(parsedline);
1057 IF(!(parsedline=(C *)M(SL(line)+1)))
1058 pe("parsecharvars(): allocation of memory error",1);
1059 F(i=0;i<SL(line);i++){
1060 IF(PARAMETER_VAR_CHAR==line[i]){
1061 /* handle decimal truncation. */
1062 IF(line[i+3]&&ID((U I)line[i+1])&&ID((U I)line[i+2])&&ID((U I)line[i+3])){
1063 /* to not get confused with the length check wildcard. */
1064 IF(!(line[i+4]&&ID((U I)line[i+4]))){
1065 tmp=(((line[i+1]-0x30)*100)+((line[i+2]-0x30)*10)+(line[i+3]-0x30));
1066 IF(tmp>0&&tmp<256){
1067 parsedline[j++]=tmp;
1068 i+=3;
1069 }
1070 E
1071 parsedline[j++]=line[i];
1072 }
1073 E
1074 parsedline[j++]=line[i];
1075 }
1076 /* handle hex truncation. */
1077 EI(line[i+2]&&isxdigit((U I)line[i+1])&&isxdigit((U I)line[i+2])){
1078 /* to not get confused with the length check wildcard. */
1079 IF(!(line[i+3]&&line[i+4]&&ID((U I)line[i+3])&&ID((U I)line[i+4]))){
1080 IF(IL((U I)line[i+1]))
1081 tmp=(TL(line[i+1])-0x56);
1082 E
1083 tmp=(line[i+1]-0x2F);
1084 tmp*=16;
1085 IF(IL((U I)line[i+2]))
1086 tmp+=(TL(line[i+2])-0x56);
1087 E
1088 tmp+=(line[i+2]-0x2F);
1089 tmp-=17;
1090 IF(tmp>0&&tmp<256){
1091 parsedline[j++]=tmp;
1092 i+=2;
1093 }
1094 E
1095 parsedline[j++]=line[i];
1096 }
1097 E
1098 parsedline[j++]=line[i];
1099 }
1100 /* handle random(alpha) truncation. */
1101 EI(line[i+1]==0x26){
1102 GD(&tv,(S timezone *)0);
1103 SR(tv.tv_usec);
1104 IF((2.0*rand()/(RAND_MAX+1.0))>1)
1105 parsedline[j++]=(0x41+(26.0*rand()/(RAND_MAX+1.0)));
1106 E
1107 parsedline[j++]=(0x61+(26.0*rand()/(RAND_MAX+1.0)));
1108 i++;
1109 }
1110 /* handle random(numeric) truncation. */
1111 EI(line[i+1]==0x23){
1112 GD(&tv,(S timezone *)0);
1113 SR(tv.tv_usec);
1114 parsedline[j++]=(0x30+(10.0*rand()/(RAND_MAX+1.0)));
1115 i++;
1116 }
1117 E
1118 parsedline[j++]=line[i];
1119 }
1120 E
1121 parsedline[j++]=line[i];
1122 }
1123 parsedline[j]=0x0;
1124 R;
1125 }
1126 /* parsing for ${0-9} dynamic user storage variables, makes the */
1127 /* "parseddynamic" buffer. */
parsedynamic(C * in)1128 V parsedynamic(C *in){
1129 U I i=0;
1130 U I j=0;
1131 F(j=i=0;i<SL(in);i++){
1132 IF(in[(i+3)]&&in[i]==PARAMETER_VAR_CHAR&&in[(i+1)]==0x7B&&ID((U I)in[(i+2)])
1133 &&in[(i+3)]==0x7D&&!(i==0&&in[(i+4)]&&in[(i+4)]==0x3D)){
1134 IF(dynamicvarset[(in[(i+2)]-0x30)])
1135 j+=SL(dynamicvar[(in[(i+2)]-0x30)]);
1136 i+=3;
1137 }
1138 E
1139 j++;
1140 }
1141 FR(parseddynamic);
1142 IF(!(parseddynamic=(C *)M(j+1)))
1143 pe("parsedynamic(): allocation of memory error",1);
1144 B(parseddynamic,(j+1));
1145 F(i=0;i<SL(in);i++){
1146 IF(in[(i+3)]&&in[i]==PARAMETER_VAR_CHAR&&in[(i+1)]==0x7B&&ID((U I)in[(i+2)])
1147 &&in[(i+3)]==0x7D&&!(i==0&&in[(i+4)]&&in[(i+4)]==0x3D)){
1148 /* only if the variable has been set, use it. */
1149 IF(dynamicvarset[(in[(i+2)]-0x30)])
1150 SCA(parseddynamic,dynamicvar[(in[(i+2)]-0x30)]);
1151 i+=3;
1152 }
1153 E
1154 parseddynamic[SL(parseddynamic)]=in[i];
1155 }
1156 R;
1157 }
1158 /* this function was made because these two functions are often with */
1159 /* eachother. saves repetition space. */
parsecmdline(C * in)1160 V parsecmdline(C *in){
1161 parsedynamic(in);
1162 parsecharvars(parseddynamic);
1163 R;
1164 }
1165 /* this function will set up the display name to be used by other functions. */
setdname(V)1166 V setdname(V){
1167 S utsname un;
1168 /* get the display infromation. must check for equal or greater than zero. */
1169 /* due to the fact different platforms handle this differently. but, */
1170 /* errors being a negative number is an apparent constant. */
1171 IF(UE(&un)>-1){
1172 IF(!(nname=(C *)M(SL(un.nodename)+SL(un.machine)+2)))
1173 pe("setdname(): allocation of memory error",1);
1174 B(nname,(SL(un.nodename)+SL(un.machine)+2));
1175 SP(nname,"%s-%s",un.nodename,un.machine);
1176 }
1177 E{
1178 IF(!(nname=(C *)SDU("unknown")))
1179 pe("setdname(): duplication of memory error",1);
1180 }
1181 R;
1182 }
1183 /* function to set the rc filename. */
setrc(C * file)1184 V setrc(C *file){
1185 S passwd *pent;
1186 IF(!(pent=GPU(GU())))
1187 R;
1188 IF(!(rcfile=(C *)M(SL(pent->pw_dir)+SL(file)+2)))
1189 pe("setrc(): allocation of memory error",1);
1190 B(rcfile,(SL(pent->pw_dir)+SL(file)+2)) ;
1191 SP(rcfile,"%s/%s",pent->pw_dir,file);
1192 R;
1193 }
1194 /* function to set the history filename. */
sethistory(C * file)1195 V sethistory(C *file){
1196 S passwd *pent;
1197 IF(!(pent=GPU(GU())))
1198 R;
1199 IF(!(histfile=(C *)M(SL(pent->pw_dir)+SL(file)+2)))
1200 pe("sethistory(): allocation of memory error",1);
1201 B(histfile,(SL(pent->pw_dir)+SL(file)+2)) ;
1202 SP(histfile,"%s/%s",pent->pw_dir,file);
1203 R;
1204 }
1205 /* funcation to append a line to the history file. */
addhistory(U C * data)1206 V addhistory(U C *data){
1207 U I i=0;
1208 U C hread[(BASE_BUFFER*4+1)];
1209 FL *hfd;
1210 /* no verbose error warnings in this function, quiet. */
1211 IF((hfd=FO(histfile,"r"))){
1212 W(FS(hread,(SO(hread)-1),hfd)){
1213 F(i=0;i<SL(hread);i++)
1214 IF(hread[i]==0x0A||hread[i]==0x0D)
1215 hread[i]=0x0;
1216 /* abort it already exists. */
1217 IF(!SC(hread,data)){
1218 FC(hfd);
1219 R;
1220 }
1221 /* clean out. */
1222 B(hread,(BASE_BUFFER*4+1));
1223 }
1224 FC(hfd);
1225 }
1226 IF((hfd=FO(histfile,"a"))){
1227 FP(hfd,"%s\n",data);
1228 FC(hfd);
1229 }
1230 R;
1231 }
1232 /* this is supposed to get the input, and output from the ruleset file. */
1233 /* the file format is per line stacked, must have both. like so: */
1234 /* input given. (wildcards apply here) */
1235 /* output to responed. (pre-data/actions apply here) */
1236 /* input given. (wildcards apply here) */
1237 /* output to responed. (pre-data/actions apply here, and so on..) */
1238 /* also partly handles the "one time" variable. */
makelists(C * path)1239 V makelists(C *path){
1240 /* yes, i could have reused some. but, i like to be able to keep track. */
1241 /* loop ints. */
1242 U I i=0;
1243 U I j=0;
1244 U I k=0;
1245 U I l=0;
1246 /* for the last input/output line. */
1247 U C *lasti;
1248 U C *lasto;
1249 /* rather large size for possible long requests. */
1250 U C rread[(BASE_BUFFER*16+1)];
1251 FL *fd;
1252 /* this switches to standard input if the argument is provided. */
1253 IF(inputrules){
1254 IF(!(fd=FO(ttyn,"r")))
1255 pe("standard input does not appear to exist, or is not readable",1);
1256 pe("awaiting ruleset from standard input, followed by ^D",0);
1257 }
1258 E{
1259 IF(!(fd=FO(path,"r")))
1260 pe("ruleset file does not appear to exist, or is not readable",1);
1261 }
1262 B(rread,(BASE_BUFFER*16+1));
1263 W(FS(rread,(SO(rread)-1),fd)){
1264 /* maximum input/output storage met. exits when it occurs. */
1265 IF(j>=MAX_ARGS)
1266 pe("too many slots to store in memory",1);
1267 IF(rread[0]!=0x23){
1268 F(i=0;i<SL(rread);i++)
1269 IF(rread[i]==0x0A||rread[i]==0x0D)
1270 rread[i]=0x0;
1271 IF(rread[0]!=0x0A&&rread[0]!=0x0D&&rread[0]!=0x0){
1272 /* simple on/off int to write line of input then line of output, then */
1273 /* checking at the end to make sure the input, and output lines are */
1274 /* even. (at the end of the function) */
1275 IF(k)
1276 k=0;
1277 E
1278 k=1;
1279 IF(k){
1280 /* replaces the hex, dec, and random variables. */
1281 parsecharvars(rread);
1282 IF(!(input[tot_i]=(SCC(rread,NS_REPEAT)||!tot_i?(C *)SDU(parsedline):(C *)
1283 SDU(lasti))))
1284 pe("makelists(): duplication of memory error",1);
1285 /* store last input. */
1286 IF(tot_i)
1287 FR(lasti);
1288 IF(!(lasti=(C *)SDU(input[tot_i++])))
1289 pe("makelists(): duplication of memory error",1);
1290 }
1291 E{
1292 /* decided not to allow an only function sleep, so data is required. */
1293 /* virtually makes sure its exactly five numerics, like it must be. */
1294 IF(SL(rread)>6&&ID((U I)rread[(SL(rread)-1)])&&ID((U I)rread[
1295 (SL(rread)-2)])&&ID((U I)rread[(SL(rread)-3)])&&ID((U I)rread[
1296 (SL(rread)-4)])&&ID((U I)rread[(SL(rread)-5)])&&rread[(SL(rread)-6)]
1297 ==PARAMETER_VAR_CHAR){
1298 rs_delay[tot_o]=(((rread[(SL(rread)-5)]-0x30)*10000)+((rread[(SL(rread)-
1299 4)]-0x30)*1000)+((rread[(SL(rread)-3)]-0x30)*100)+((rread[(SL(rread)-2)]-
1300 0x30)*10)+(rread[(SL(rread)-1)]-0x30));
1301 rread[(SL(rread)-6)]=0x0;
1302 }
1303 /* this checks for the "one time" variable. then, adds it to the int */
1304 /* buffer, if no data is provided after the variable it will be treated */
1305 /* as normal text. */
1306 IF(SL(rread)>SL(NS_ONCE)&&!SNCC(rread,NS_ONCE,SL(NS_ONCE))){
1307 /* kill the two variable bytes. (output) */
1308 F(l=SL(NS_ONCE);l<SL(rread);l++)
1309 rread[(l-SL(NS_ONCE))]=rread[l];
1310 rread[(l-SL(NS_ONCE))]=0x0;
1311 rs_static[tot_o]=1;
1312 }
1313 E
1314 rs_static[tot_o]=0;
1315 /* replaces the hex, dec, and random variables. */
1316 parsecharvars(rread);
1317 IF(!(output[tot_o]=(SCC(rread,NS_REPEAT)||!tot_o?(C *)SDU(parsedline):
1318 (C *)SDU(lasto))))
1319 pe("makelists(): duplication of memory error",1);
1320 /* store last output. */
1321 IF(tot_o)
1322 FR(lasto);
1323 /* add the effects of the copied output rule. (if copied) */
1324 IF(!SCC(rread,NS_REPEAT)&&tot_o){
1325 rs_static[tot_o]=rs_static[(tot_o-1)];
1326 rs_delay[tot_o]=rs_delay[(tot_o-1)];
1327 }
1328 IF(!(lasto=(C *)SDU(output[tot_o++])))
1329 pe("makelists(): duplication of memory error",1);
1330 }
1331 }
1332 B(rread,(BASE_BUFFER*16+1));
1333 }
1334 j++;
1335 }
1336 FC(fd);
1337 /* check for equal amount of input to outputs, so the ruleset corresponds. */
1338 IF(tot_i!=tot_o)
1339 pe("input/output data from the ruleset does not correspond",1);
1340 /* no rules, no go. (might as well use telnet then) */
1341 IF(!tot_i||!tot_o)
1342 pe("no input/output responses supplied from the ruleset file",1);
1343 /* status showing for stdin ruleset input. */
1344 IF(inputrules)
1345 pe("valid ruleset supplied via input, continuing",0);
1346 /* clear one last time, these buffers would have both been used to make */
1347 /* it this far. */
1348 FR(lasti);
1349 FR(lasto);
1350 R;
1351 }
1352 /* this function is for printing arguments passed to it, mainly for the */
1353 /* purpose of GTK/ncurses support, so it can be directed. */
nsprint(C * format,...)1354 V nsprint(C *format,...){
1355 SI I i=0;
1356 /* nothing should get this big, but its virtually the max used anywheres */
1357 /* in netscript. */
1358 U I j=(BASE_BUFFER*8);
1359 C *display;
1360 VAL ap;
1361 /* small fixed font to use. */
1362 #ifdef GTK
1363 GdkFont *gf;
1364 GdkColormap *gcm;
1365 GdkColor gc;
1366 #endif
1367 /* return if backgrounded or malloc() failed. */
1368 IF(isbga||!(display=(C *)M(j)))
1369 R;
1370 W(1){
1371 VAS(ap,format);
1372 i=VS(display,j,format,ap);
1373 VAE(ap);
1374 IF(i>-1&&i<j){
1375 /* send to gui window instead, if in gui mode. */
1376 #ifdef GTK
1377 IF(isgui&&isagui){
1378 gcm=gdk_colormap_get_system();
1379 gc.red=guic[0];
1380 gc.green=guic[1];
1381 gc.blue=guic[2];
1382 IF(!gdk_color_alloc(gcm,&gc))
1383 pe("could not allocate color for the gui",1);
1384 E{
1385 GTE();
1386 /* nice, and standard font. like fixed. */
1387 IF(!isbgui)
1388 gf=GFL(GUI_FONT);
1389 gtk_text_insert(GTK_TEXT(gte),(isbgui?0:gf),(isguic?&gc:0),0,display,
1390 SL(display));
1391 GTL();
1392 }
1393 }
1394 E
1395 #endif
1396 #ifdef NCURSES
1397 {
1398 IF(isncurses){
1399 NWP(nfocus,"%s",display);
1400 NRE(nfocus);
1401 /* default (back) to main window. */
1402 nfocus=nw3;
1403 }
1404 E
1405 P("%s",display);
1406 }
1407 #else
1408 P("%s",display);
1409 #endif
1410 FR(display);
1411 R;
1412 }
1413 IF(i>-1)
1414 j=(i+1);
1415 E
1416 j*=2;
1417 IF((display=realloc(display,j))==0){
1418 /* size change failed. free anyways, and return. */
1419 FR(display);
1420 R;
1421 }
1422 }
1423 R;
1424 }
1425 /* displays argv[0], the supplied text, and exits if non-zero. */
pe(C * err,U SH quit)1426 V pe(C *err,U SH quit){
1427 /* simple enough handling on this option. */
1428 IF(!noshowa)
1429 nsprint("%s: %s.\n",progname,err);
1430 IF(quit)
1431 nsexit(quit,0);
1432 R;
1433 }
1434 /* displays hex, dec, or regular with the from/to prompt option. */
1435 /* 0 = output, 1 = input, 2 = other. */
pd(U C * in,U SH io,U I size)1436 V pd(U C *in,U SH io,U I size){
1437 U I i=0;
1438 U I j=0;
1439 U I k=0;
1440 /* will be used for hex, or dec (or duplication of the original). */
1441 U C *chrdump;
1442 U C *line;
1443 C prompt[4];
1444 /* columns gets set before pd() is ever ran, in main(). */
1445 IF(!(line=(C *)M(size+1)))
1446 pe("pd(): allocation of memory error",1);
1447 B(line,(size+1));
1448 IF(displaytype){
1449 /* size multiplied four times because every byte in the original */
1450 /* buffer is going to be equal to four in the new buffer. */
1451 IF(!(chrdump=(C *)M((SL(in)*4)+1)))
1452 pe("pd(): allocation of memory error",1);
1453 B(chrdump,((SL(in)*4)+1));
1454 F(i=0;i<SL(in);i++){
1455 /* 0 = character, 1 = hex, 2 = decimal. */
1456 IF(displaytype==1)
1457 SP(&chrdump[k],"\\x%.2x",in[i]);
1458 E
1459 SP(&chrdump[k],"%.3d%c",in[i],((i+1)!=SL(in))?0x20:0x0);
1460 k+=4;
1461 }
1462 }
1463 /* make the chrdump buffer a standard character buffer if no dispalytype to */
1464 /* wordwrap up later. */
1465 IF(!displaytype){
1466 IF(!(chrdump=(C *)SDU(in)))
1467 pe("pd(): duplication of memory error",1);
1468 }
1469 B(prompt,4);
1470 IF(!io&&!nossend)
1471 SP(prompt,"-> ");
1472 EI(io&&!nosrecv)
1473 SP(prompt,"<- ");
1474 IF(!nowrap){
1475 B(line,(size+1));
1476 F(i=0;i<SL(chrdump);i++){
1477 IF(!SL(line))
1478 SP(line,"%s",!nofrom?prompt:"");
1479 /* next two checks are impossible to effect hex, or dec dumps. */
1480 /* makes sure tabs do not screw up the wordwrap. */
1481 IF(chrdump[i]==0x09)
1482 /* 7 spaces = 1 tab(sort of, at a tab max), if it is beyond the buffer */
1483 /* size the tab will get cut off. does not handle like a tab does. */
1484 F(j=0;(j<7&&!(SL(line)>=size));j++)
1485 line[SL(line)]=0x20;
1486 /* do not want a screwed up wordwrap, just slap a linefeed there instead. */
1487 EI(chrdump[i]==0x0A)
1488 line[SL(line)]=0x0D;
1489 E
1490 line[SL(line)]=chrdump[i];
1491 IF(SL(line)>=size){
1492 #ifdef NCURSES
1493 nfocus=(io?nw1:nw2);
1494 #endif
1495 nsprint("%s\n",line);
1496 B(line,(size+1));
1497 }
1498 }
1499 IF(SL(line)){
1500 #ifdef NCURSES
1501 nfocus=(io?nw1:nw2);
1502 #endif
1503 nsprint("%s\n",line);
1504 }
1505 }
1506 /* for disabled wordwrap, which also includes th -L option. (-w option) */
1507 EI(SL(chrdump)){
1508 /* precurse with number of lines. */
1509 IF(lnum){
1510 #ifdef NCURSES
1511 nfocus=(io?nw1:nw2);
1512 #endif
1513 nsprint("(%.4d) ",(!io?(lnum_o++):(lnum_i++)));
1514 /* restart it to zero. */
1515 IF(lnum_o>=10000)
1516 lnum_o=1;
1517 IF(lnum_i>=10000)
1518 lnum_i=1;
1519 }
1520 #ifdef NCURSES
1521 nfocus=(io?nw1:nw2);
1522 #endif
1523 nsprint("%s%s\n",!nofrom?prompt:"",chrdump);
1524 }
1525 FR(chrdump);
1526 FR(line);
1527 R;
1528 }
1529 /* writes data to the socket, and handles the ns_outgoing() module. also, */
1530 /* handles the telnet dump for outgoing. (-y, and -Y options) */
wro(C * output,U I size,U SH io)1531 V wro(C *output,U I size,U SH io){
1532 U SH s=0;
1533 fd_set cfd;
1534 fd_set crfd;
1535 S timeval tv;
1536 /* check, and use the ns_outgoing() symbol, it passes the output to be */
1537 /* wrote to the socket, the amount that will be wrote, the actual size of */
1538 /* the data, and the socket value. (char *, int, int, int) */
1539 #ifndef DISABLE_MODULES
1540 IF(vmodule&&SL(output)&&size&&!io)
1541 (*outgoing_function)(output,size,SL(output),sock);
1542 #endif
1543 IF(sock!=-1&&!io){
1544 FD_ZERO(&cfd);
1545 FD_SET(sock,&cfd);
1546 /* handle outgoing telnet dumping. (-y, and -Y options) */
1547 dumptelnet(output);
1548 /* no time needed. */
1549 tv.tv_sec=0;
1550 tv.tv_usec=0;
1551 /* make sure the socket is really there. */
1552 IF(SE((sock+1),0,&cfd,0,&tv)>0)
1553 WR(sock,output,size);
1554 IF(islog&&tnetraw)
1555 logdata(output,3);
1556 }
1557 IF(setroute){
1558 /* to still check for activity with select(). */
1559 IF(((norrecv&&io)||(norsend&&!io))&&io!=2)
1560 s=1;
1561 IF(rsock!=-1){
1562 FD_ZERO(&crfd);
1563 FD_SET(rsock,&crfd);
1564 tv.tv_sec=0;
1565 tv.tv_usec=0;
1566 IF(SE((rsock+1),0,&crfd,0,&tv)>0){
1567 IF(!s)
1568 WR(rsock,output,size);
1569 }
1570 /* silent. */
1571 E{
1572 SD(rsock,2);
1573 CL(rsock);
1574 rsock=-1;
1575 setroute=0;
1576 }
1577 }
1578 }
1579 R;
1580 }
1581 /* this function will write the supplied arguments to the system log. it */
1582 /* has a similar usage to nsprint(). (-Z option) */
1583 #ifndef DISABLE_SYSLOG
wrso(C * format,...)1584 V wrso(C *format,...){
1585 SI I i=0;
1586 /* max size. */
1587 U I j=(BASE_BUFFER*8);
1588 C *wlog;
1589 VAL ap;
1590 /* only do if enabled. (-Z option) */
1591 IF(!slog)
1592 R;
1593 /* return if backgrounded or malloc() failed. */
1594 IF(!(wlog=(C *)M(j)))
1595 R;
1596 W(1){
1597 VAS(ap,format);
1598 i=VS(wlog,j,format,ap);
1599 VAE(ap);
1600 IF(i>-1&&i<j){
1601 /* could fail to write. if it does, it probably was not a superuser, */
1602 /* which is all that is desired to be logged anyways. */
1603 SLG(LOG_WARNING,"%s",wlog);
1604 FR(wlog);
1605 R;
1606 }
1607 IF(i>-1)
1608 j=(i+1);
1609 E
1610 j*=2;
1611 IF((wlog=realloc(wlog,j))==0){
1612 /* size change failed. free anyways, and return. */
1613 FR(wlog);
1614 R;
1615 }
1616 }
1617 R;
1618 }
1619 #endif
1620 /* function to set the permissions of netscript to run under. set after */
1621 /* connected. but, set before taking any input, or sending any output. */
setpermissions(C * string,U SH type)1622 V setpermissions(C *string,U SH type){
1623 S passwd *pent;
1624 S group *gent;
1625 /* read the string. */
1626 IF(!type){
1627 /* set them up default. in case no data is provided, it will just reset. */
1628 ngid=GEG();
1629 nuid=GEU();
1630 /* if a "." exists. take the first token as uid, and then second as gid. */
1631 IF(!parameter(string,1,0x2E)){
1632 IF(!(gent=GR(parm)))
1633 ngid=AI(parm);
1634 E
1635 ngid=gent->gr_gid;
1636 parameter(string,0,0x2E);
1637 IF(!(pent=GP(parm)))
1638 nuid=AI(parm);
1639 E
1640 nuid=pent->pw_uid;
1641 }
1642 E{
1643 IF(!(pent=GP(string)))
1644 nuid=AI(string);
1645 /* gid should be defaulted, already. */
1646 E{
1647 nuid=pent->pw_uid;
1648 ngid=pent->pw_gid;
1649 }
1650 /* apply the gid of the user, since no other gid was specified. */
1651 }
1652 }
1653 /* do what setpermissions() said to when called earlier. */
1654 E{
1655 /* note the new id information. to potentially, clarify the discontinue */
1656 /* of logging.*/
1657 #ifndef DISABLE_SYSLOG
1658 wrso("%d-%d id: %lu-%u.%u.%u.%u new: %lu-%u.%u.%u.%u",slnum_t,(slnum_s++),
1659 cpid,GU(),GEU(),GG(),GEG(),cpid,nuid,nuid,ngid,ngid);
1660 #endif
1661 /* set the groups up, to follow. */
1662 IF((pent=GPU(nuid)))
1663 initgroups(pent->pw_name,ngid);
1664 /* setre*id() is not on some systems. virtually the same thing. keeps */
1665 /* the groups. also, no need for setfs*id(), sete*id() will do it. */
1666 /* setfs*id() is not supported everywheres either. */
1667 SGD(ngid);
1668 SEGD(ngid);
1669 SUD(nuid);
1670 SEUD(nuid);
1671 }
1672 R;
1673 }
1674 /* ruleset editor, uses a third party text editor on a file. */
ruleedit(U SH type,C * path)1675 V ruleedit(U SH type,C *path){
1676 C *editor;
1677 C *tmpfile;
1678 PT fp;
1679 T tm;
1680 S stat mod;
1681 IF(isprivileged)
1682 pe("a third party editor can not be executed with privileged access",0);
1683 E{
1684 IF(G(ENV_EDITOR)){
1685 IF(!(editor=(C *)SDU((C *)G(ENV_EDITOR))))
1686 pe("ruleedit(): duplication of memory error",1);
1687 }
1688 E{
1689 IF(!(editor=(C *)SDU(DFL_EDITOR)))
1690 pe("ruleedit(): duplication of memory error",1);
1691 }
1692 IF(!type){
1693 IF(!(tmpfile=(C *)M(5+10+5+10+1)))
1694 pe("ruleedit(): allocation of memory error",1);
1695 B(tmpfile,(5+10+5+10+1));
1696 TM(&tm);
1697 SP(tmpfile,"/tmp/netscript.%.5lu%.10lu",(U L)cpid,(U L)tm);
1698 }
1699 E{
1700 IF(!(tmpfile=(C *)SDU(path)))
1701 pe("ruleedit(): duplication of memory error",1);
1702 }
1703 SW(fp=FK()){
1704 CS -1:
1705 pe("failed forking for the third party text editor",0);
1706 BR;
1707 CS 0:
1708 SG(SIGINT,SIG_DFL);
1709 EL(editor,editor,tmpfile,0);
1710 pe("failed execution of (ruleset) file editor",0);
1711 _exit(1);
1712 BR;
1713 default:
1714 /* wait till finished. */
1715 WP(fp,0,0);
1716 BR;
1717 }
1718 IF(STT(tmpfile,&mod))
1719 pe("could not access the temporary/ruleset file passed to the editor",1);
1720 EI(!setfile){
1721 /* this should never happen. but, just incase. */
1722 IF(mod.st_uid!=GEU()||mod.st_gid!=GEG())
1723 pe("the temporary file has a different owner/group than the current proces"
1724 "s",1);
1725 EI(!setfile){
1726 IF(!(rulesfile=(C *)SDU(tmpfile)))
1727 pe("ruleedit(): duplication of memory error",1);
1728 setfile=1;
1729 }
1730 }
1731 FR(editor);
1732 FR(tmpfile);
1733 }
1734 R;
1735 }
1736 /* this function does the logging. (-l option) */
1737 /* 0 = output, 1 = input, 2 = other, else = raw. */
logdata(C * data,U SH io)1738 V logdata(C *data,U SH io){
1739 /* will be used to hold the ctime data. */
1740 C *timebuf;
1741 C prompt[3];
1742 T tm;
1743 FL *fd;
1744 /* opens, and allows appending to the log file. */
1745 IF(!(fd=FO(logfile,"a")))
1746 pe("log file can not be created, or is not writable",1);
1747 E{
1748 TM(&tm);
1749 IF(!(timebuf=(C *)SDU(CT(&tm))))
1750 pe("logdata(): duplication of memory error",1);
1751 IF(timebuf[(SL(timebuf)-1)]==0x0A)
1752 timebuf[(SL(timebuf)-1)]=0x0;
1753 B(prompt,3);
1754 IF(!io)
1755 SP(prompt,"->");
1756 EI(io==1)
1757 SP(prompt,"<-");
1758 EI(io==2)
1759 SP(prompt,"!!");
1760 IF(SL(data)){
1761 /* raw data write. (-y, and -Y options) */
1762 IF(!SL(prompt))
1763 FP(fd,"%s",data);
1764 E
1765 /* regular data write. */
1766 FP(fd,"%s: %s %s\n",timebuf,prompt,data);
1767 }
1768 FR(timebuf);
1769 FC(fd);
1770 }
1771 R;
1772 }
1773 /* the fixed dumping of information with the telnet option. has */
1774 /* comparisons. (-y, and -Y in conjunction with -T option) */
dumptelnet(C * dump)1775 V dumptelnet(C *dump){
1776 U I i=0;
1777 U I j=0;
1778 U C *tmpdump;
1779 IF(!(tmpdump=(C *)M(SL(dump)+1)))
1780 pe("dumptelnet(): allocation of memory error",1);
1781 IF(tnetraw){
1782 /* 1 = stderr, 2 = stdout(regular). */
1783 IF(tnetraw==1){
1784 /* do not show if backgrounded. */
1785 IF(!isbga)
1786 FP(stderr,"%s",dump);
1787 }
1788 E{
1789 /* mainly did it this way for debug purposes. */
1790 B(tmpdump,(SL(dump)+1));
1791 F(i=j=0;j<SL(dump);j++){
1792 IF(dump[j]==0x0A){
1793 tmpdump[i]=0x0;
1794 nsprint("%s\n",tmpdump);
1795 B(tmpdump,(SL(dump)+1));
1796 i=0;
1797 }
1798 E
1799 tmpdump[i++]=dump[j];
1800 }
1801 IF(SL(tmpdump)){
1802 tmpdump[i]=0x0;
1803 nsprint("%s",tmpdump);
1804 }
1805 /* no need to zero out the buffer since it is going to be free'd next. */
1806 }
1807 }
1808 FR(tmpdump);
1809 R;
1810 }
1811 /* this is for use with dumping a programs output to the socket. also, */
1812 /* used for the $` execution comparison variable. */
dumpexec(C * path,U SH type)1813 V dumpexec(C *path,U SH type){
1814 U SH r=0;
1815 U SH s=0;
1816 U I i=0;
1817 U I j=0;
1818 U I k=0;
1819 /* to be duplicated. */
1820 I fd[2];
1821 PT fp;
1822 /* will wrap if needed to this size. */
1823 U C eread[(BASE_BUFFER*8+1)];
1824 /* temporary buffer must be as big as its counterpart. */
1825 U C ereadl[(BASE_BUFFER*8+1)];
1826 /* timeout of waiting for input. */
1827 S timeval tv;
1828 /* for select(). */
1829 fd_set ffd;
1830 /* set to null, in case anything fails before anything actually happens. */
1831 IF(type){
1832 FR(execformat);
1833 IF(!(execformat=(C *)SDU("(null)")))
1834 pe("dumpexec(): duplication of memory error",1);
1835 }
1836 /* just incase of setuid/setgid. */
1837 #ifdef GTK
1838 IF(isgui){
1839 pe("can not execute third party programs while in gui/gtk mode",0);
1840 R;
1841 }
1842 #endif
1843 #ifndef DISABLE_SYSLOG
1844 wrso("%d-%d id: %lu-%u.%u.%u.%u exec: %s",slnum_t,(slnum_s++),cpid,GU(),GEU(),
1845 GG(),GEG(),path);
1846 #endif
1847 IF(!noshowp&&!type)
1848 pe("entering execution dump, incoming data suspended",0);
1849 IF(isprivileged)
1850 pe("third party programs can not be executed with privileged access",0);
1851 E{
1852 /* pair the two duplicate fd's. */
1853 IF(socketpair(PF_UNIX,SOCK_STREAM,0,fd)==-1){
1854 pe("execution dump failed, incoming data resumed",0);
1855 R;
1856 }
1857 SW(fp=FK()){
1858 CS -1:
1859 pe("execution dump failed, incoming data resumed",0);
1860 CL(fd[0]);
1861 CL(fd[1]);
1862 BR;
1863 CS 0:
1864 /* close, and duplicate the fd's. if netscript is in the background */
1865 /* this will not want to be evaluated. */
1866 IF(!isbga){
1867 CL(0);
1868 CL(1);
1869 CL(2);
1870 }
1871 /* this will allow interaction inside the program, stdin->socket. */
1872 /* if desired. */
1873 IF(isiexec)
1874 D(sock,0);
1875 /* output. */
1876 D(fd[1],1);
1877 D(fd[1],2);
1878 /* better than a raw execution. */
1879 EL(eshell,eshell,"-c",path,0);
1880 /* make sure the handler is still defined, should be anyways. */
1881 SG(SIGINT,sighandler);
1882 /* should never make it here. if it does, since its duplicated, it will */
1883 /* send any output to the socket. so, looks better just to be silent. */
1884 _exit(1);
1885 BR;
1886 default:
1887 /* ignore temporarily to send the signal only to the forked pid. */
1888 SG(SIGINT,SIG_IGN);
1889 FD_ZERO(&ffd);
1890 FD_SET(fd[0],&ffd);
1891 W(!k){
1892 /* defined amount of delay time, 3 seconds by default. (-x option) */
1893 tv.tv_sec=(xalrm?xalrm:3);
1894 /* no need to be so precise. */
1895 tv.tv_usec=0;
1896 IF((s=SE((fd[0]+1),&ffd,0,0,&tv))>0){
1897 B(eread,(BASE_BUFFER*8+1));
1898 IF(RD(fd[0],eread,(BASE_BUFFER*8))){
1899 F(i=0;(s>0&&i<SL(eread));i++){
1900 IF(eread[i]==0x0A||eread[i]==0x0D||j>=(BASE_BUFFER*8)){
1901 /* count back for the missed byte. */
1902 IF(j>=(BASE_BUFFER*8))
1903 i--;
1904 ereadl[j]=0x0;
1905 IF(type&&!r){
1906 /* free the pre-placed "null". */
1907 FR(execformat);
1908 IF(!(execformat=(C *)SDU(ereadl)))
1909 pe("dumpexec(): duplication of memory error",1);
1910 /* let other positions know the buffer is set. */
1911 r=1;
1912 /* can only use one line. so, (fool) exit after one exists. */
1913 s=0;
1914 }
1915 E
1916 dumpexecline(ereadl);
1917 B(ereadl,(BASE_BUFFER*8+1));
1918 /* reset counter. */
1919 j=0;
1920 }
1921 E
1922 ereadl[j++]=eread[i];
1923 }
1924 B(eread,(BASE_BUFFER*8+1));
1925 }
1926 }
1927 /* if statement, and not else. because, of the fool exit possibility. */
1928 IF(s<=0){
1929 /* cap it off, for the next function. */
1930 ereadl[j]=0x0;
1931 IF(type&&!r&&SL(ereadl)){
1932 /* free the pre-placed "null". */
1933 FR(execformat);
1934 IF(!(execformat=(C *)SDU(ereadl)))
1935 pe("dumpexec(): duplication of memory error",1);
1936 /* no need to set short r, to notify, it is never used again. */
1937 }
1938 /* will dump any leftovers, as if there was a CR. */
1939 E
1940 dumpexecline(ereadl);
1941 B(ereadl,(BASE_BUFFER*8+1));
1942 /* force it, incase it timed out. */
1943 K(fp,SIGKILL);
1944 /* wait up, do not want defunctness. */
1945 WP(fp,0,0);
1946 /* bye bye. */
1947 CL(fd[0]);
1948 CL(fd[1]);
1949 /* unignore ctrl-c aborts. */
1950 SG(SIGINT,sighandler);
1951 k=1;
1952 }
1953 }
1954 BR;
1955 }
1956 }
1957 /* it would never make it to this point two times with variable usage. */
1958 /* so, no need to support such an event. required information. */
1959 IF(runexit&&!type)
1960 pe("completed execution dump, exiting netscript",1);
1961 EI(!noshowp&&!type)
1962 pe("completed execution dump, incoming data resumed",0);
1963 R;
1964 }
1965 /* to actually handle the line passed from dumpexec(). */
dumpexecline(C * line)1966 V dumpexecline(C *line){
1967 U C *dump;
1968 IF(SL(line)){
1969 IF(!(dump=(C *)M(SL(line)+(runpre?SL(execpre):0)+1)))
1970 pe("dumpexecline(): allocation of memory error",1);
1971 B(dump,(SL(line)+(runpre?SL(execpre):0)+1));
1972 IF(runpre)
1973 SCA(dump,execpre);
1974 SCA(dump,line);
1975 /* last use of eread for this run. */
1976 IF(!nossend)
1977 pd(dump,0,columns);
1978 wro(dump,SL(dump),0);
1979 wro("\n",1,0);
1980 /* add the output to the log, if enabled. (-l option) */
1981 IF(islog&&!tnetraw)
1982 logdata(dump,0);
1983 /* last use of dump for this run. */
1984 FR(dump);
1985 }
1986 R;
1987 }
1988 /* small function to close sockets. related to connecting, and binding. */
closesocket(U SH type)1989 V closesocket(U SH type){
1990 /* server connection/connected. (and routed along with it) */
1991 IF(!type){
1992 IF(sock>=0){
1993 SD(sock,2);
1994 CL(sock);
1995 sock=-1;
1996 }
1997 IF(setroute&&rsock>=0){
1998 SD(rsock,2);
1999 CL(rsock);
2000 rsock=-1;
2001 }
2002 }
2003 /* server bind socket. */
2004 E{
2005 IF(ssock>=0){
2006 SD(ssock,2);
2007 CL(ssock);
2008 ssock=-1;
2009 }
2010 }
2011 R;
2012 }
2013 /* this function handles the user supplied socket option(s). */
parsesocketopt(I type,I sockv)2014 V parsesocketopt(I type,I sockv){
2015 U I i=0;
2016 I j=0;
2017 I soargs[2];
2018 C *curopt;
2019 /* even if no options are set, set this automatically. (bind socket only) */
2020 IF(type==1){
2021 j=1;
2022 SSO(sockv,SOL_SOCKET,SO_REUSEADDR,(V *)&j,SO(j));
2023 /* was not defined on one of the supported platforms, check to be safe. */
2024 #ifdef SO_REUSEPORT
2025 SSO(sockv,SOL_SOCKET,SO_REUSEPORT,(V *)&j,SO(j));
2026 #endif
2027 }
2028 IF(soptions){
2029 parsedynamic(sopts);
2030 /* find out the size of the buffer needed. */
2031 W(!parameter(parseddynamic,i++,0x3A)){
2032 IF(!(curopt=(C *)SDU(parm)))
2033 pe("parsesocketopt(): duplication of memory error",1);
2034 parameter(curopt,0,0x2C);
2035 /* int->int comparison. */
2036 IF(AI(curopt)==type){
2037 B((V *)soargs,SO(soargs));
2038 IF(!parameter(curopt,1,0x2C)){
2039 soargs[0]=AI(parm);
2040 IF(!parameter(curopt,2,0x2C)){
2041 soargs[1]=AI(parm);
2042 IF(SSO(sockv,SOL_SOCKET,soargs[0],(V *)&soargs[1],SO(soargs[1])))
2043 pe("internal setting of socket option failed",0);
2044 }
2045 }
2046 }
2047 FR(curopt);
2048 }
2049 }
2050 R;
2051 }
2052 /* the socket connection, and line parser. takes the data from the remote */
2053 /* host, and puts it in a per line format, then passes it along to the match */
2054 /* function(s). also includes some specific variable handling. */
parsesocket(C * host,U I port)2055 V parsesocket(C *host,U I port){
2056 /* this is only used in this function. */
2057 U SH stoprules=0;
2058 /* many loop ints used to help keep track of what is what. still re-used */
2059 /* some i knew would never cross paths. */
2060 U I i=0;
2061 U I j=0;
2062 U I k=0;
2063 U I l=0;
2064 U I m=0;
2065 U I n=0;
2066 U I o=0;
2067 U I p=0;
2068 U I q=0;
2069 U I r=0;
2070 U I s=0;
2071 /* for the $, truncation variable. */
2072 SI I left=0;
2073 SI I right=0;
2074 /* socket (size) related. */
2075 SI I salen=0;
2076 /* file dump read buffer. (variable $<) */
2077 U C dread[(BASE_BUFFER*4+1)];
2078 /* special read buffer for initial data. */
2079 U C iread[(BASE_BUFFER*4+1)];
2080 /* initial write buffer. */
2081 U C iwrite[(BASE_BUFFER*4+1)];
2082 /* read buffer for socket data. needs comparisons. */
2083 U C sread[(BASE_BUFFER*4+1)];
2084 /* buffer for data built up till a completed line, otherwise gets cleared. */
2085 /* allowance of large lines. */
2086 U C sreadl[(BASE_BUFFER*16+1)];
2087 /* three byte response buffer, for telnet protocol responses. */
2088 U C telnet[3];
2089 /* single byte, multiple uses. no comparisons. */
2090 C sb[1];
2091 S hostent *he;
2092 /* connect to socket / bind client socket. */
2093 S SAN ns;
2094 /* bind server socket. */
2095 S SAN sns;
2096 /* route client socket. */
2097 S SAN rns;
2098 /* for the $"(time passed) rule. */
2099 T ctm;
2100 T rtm;
2101 FL *dfd;
2102 FL *ifd;
2103 /* reset the line values to one. (-L option) */
2104 IF(lnum)
2105 lnum_i=lnum_o=1;
2106 IF(!noshowc)
2107 /* could have used tot_i, or tot_o for the second argument, i used tot_i. */
2108 nsprint("[%lu@%s] * Session started with %d rule(s) defined.\n",cpid,nname,
2109 tot_i);
2110 /* handling for socket binding. */
2111 IF(bindmode){
2112 /* only happens on the first binding. (for forever mode) */
2113 /* unless udp mode is active, then will rebind. */
2114 IF(bindmode!=2||isudp){
2115 /* main server sockaddr structure. */
2116 if(isudp)
2117 sock=SK(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
2118 else
2119 ssock=SK(AF_INET,SOCK_STREAM,IPPROTO_TCP);
2120 parsesocketopt(1,(isudp?sock:ssock));
2121 B((V *)&sns,SO(sns));
2122 sns.sin_family=AF_INET;
2123 sns.sin_port=HS(port);
2124 IF(isvhost){
2125 /* resolve/set the host. */
2126 IF((sns.sin_addr.s_addr=IA(vhost))){
2127 IF(!(he=GH(vhost))){
2128 IF(!noshowc)
2129 nsprint("[%lu@%s] * Could not resolve the provided virtual host, using "
2130 "any...\n",cpid,nname);
2131 sns.sin_addr.s_addr=HL(INADDR_ANY);
2132 }
2133 E
2134 MC((C *)&sns.sin_addr,(C *)he->h_addr,SO(sns.sin_addr));
2135 }
2136 E
2137 sns.sin_addr.s_addr=HL(INADDR_ANY);
2138 }
2139 /* bind to the ip/port. (-b option) */
2140 IF(BI((isudp?sock:ssock),(S SA *)&sns,SO(sns))<0){
2141 IF(!noshowc)
2142 nsprint("[%lu@%s] * Bind failed: %s.\n",cpid,nname,strerror(errno));
2143 /* yet again. better safe than sorry, do not want fds to fill up. */
2144 closesocket(0);
2145 closesocket(1);
2146 R;
2147 }
2148 /* so it does not re-bind, again. */
2149 bindmode=2;
2150 }
2151 IF(!noshowc)
2152 nsprint("[%lu@%s] * Awaiting incoming connection...\n",cpid,nname);
2153 /* one time connection(per listen), should not need more than one. */
2154 IF(isudp){
2155 i=SO(S SA);
2156 IF(RF(sock,sread,(BASE_BUFFER*4),MSG_PEEK,(S SA *)&sns,&i)<0){
2157 nsprint("[%lu@%s] * Bind failed: recvfrom()\n",cpid,nname);
2158 /* close up shop. */
2159 closesocket(0);
2160 closesocket(1);
2161 R;
2162 }
2163 IF(CO(sock,(S SA *)&sns,SO(sns))){
2164 IF(!noshowc)
2165 nsprint("[%lu@%s] * Connection failed: %s.\n",cpid,nname,strerror(errno));
2166 R;
2167 }
2168 }
2169 E{
2170 IF(LI(ssock,blog)<0){
2171 pe("could not listen on supplied port",0);
2172 R;
2173 }
2174 salen=SO(ns);
2175 IF((sock=AT(ssock,(S SA *)&ns,&salen))<0){
2176 pe("could not accept remote connection",0);
2177 R;
2178 }
2179 parsesocketopt(0,sock);
2180 }
2181 /* close it, if its just one time. (bind) */
2182 IF(!forever)
2183 closesocket(1);
2184 IF(isudp){
2185 i=SO(ns);
2186 /* if fails, doesnt really matter. (hopefully) */
2187 GPN(sock,(S SA *)&ns,&i);
2188 }
2189 IF(!noshowc){
2190 nsprint("[%lu@%s] * Accepted connection from: %s:%d.\n",cpid,nname,
2191 /* since these ips do not really exist, other than in an error */
2192 /* situation. blank out the confusion of an error. */
2193 #ifndef DISABLE_SRCIP
2194 ((!SC(IN(ns.sin_addr),"255.255.255.255")||!SC(IN(ns.sin_addr),"0.0.0.0"))
2195 ?NOSRCIP:IN(ns.sin_addr))
2196 #else
2197 NOSRCIP
2198 #endif
2199 ,port);
2200 }
2201 }
2202 /* handling for socket connection. */
2203 E{
2204 sock=SK(AF_INET,(isudp?SOCK_DGRAM:SOCK_STREAM),(isudp?IPPROTO_UDP:
2205 IPPROTO_TCP));
2206 parsesocketopt(0,sock);
2207 B((V *)&ns,SO(ns));
2208 ns.sin_family=AF_INET;
2209 IF(isvhost){
2210 /* resolve/set the host. */
2211 IF((ns.sin_addr.s_addr=IA(vhost))){
2212 IF(!(he=GH(vhost))){
2213 IF(!noshowc)
2214 nsprint("[%lu@%s] * Could not resolve the provided virtual host, using a"
2215 "ny...\n",cpid,nname);
2216 ns.sin_addr.s_addr=HL(INADDR_ANY);
2217 }
2218 E
2219 MC((C *)&ns.sin_addr,(C *)he->h_addr,SO(ns.sin_addr));
2220 }
2221 IF(BI(sock,(S SA *)&ns,SO(ns))<0){
2222 /* clean up, and use any. */
2223 pe("error binding name to socket, using any",0);
2224 B((V *)&ns,SO(ns));
2225 ns.sin_family=AF_INET;
2226 ns.sin_addr.s_addr=HL(INADDR_ANY);
2227 IF(BI(sock,(S SA *)&ns,SO(ns))<0)
2228 pe("could not bind name properly",0);
2229 }
2230 }
2231 B((V *)&ns,SO(ns));
2232 ns.sin_family=AF_INET;
2233 ns.sin_port=HS(port);
2234 IF(!noshowc)
2235 nsprint("[%lu@%s] * Checking the provided host...\n",cpid,nname);
2236 IF((ns.sin_addr.s_addr=IA(host))){
2237 /* if not valid, attempts to resolve as a host. */
2238 IF(!(he=GH(host))){
2239 /* nothing left to try. */
2240 IF(!noshowc)
2241 nsprint("[%lu@%s] * Could not resolve the provided host.\n",cpid,nname);
2242 R;
2243 }
2244 E
2245 /* successfully resolved. */
2246 MC((C *)&ns.sin_addr,(C *)he->h_addr,SO(ns.sin_addr));
2247 }
2248 IF(!noshowc)
2249 nsprint("[%lu@%s] * Attempting to connect to the provided host...\n",cpid,
2250 nname);
2251 /* if you can not connect to the server the first time might as well kill */
2252 /* the program, same problem would continue infinitely. so, if it times */
2253 /* out after ??(2 minutes by default) seconds it will just exit. */
2254 IF(G(ENV_TIMEOUT)&&AI((C *)G(ENV_TIMEOUT))>0)
2255 A(AI((C *)G(ENV_TIMEOUT)));
2256 E
2257 A(DFL_TIMEOUT);
2258 /* like it looks, attempts to connect to the remote server. */
2259 IF(CO(sock,(S SA *)&ns,SO(ns))){
2260 A(0);
2261 IF(!noshowc)
2262 nsprint("[%lu@%s] * Connection failed: %s.\n",cpid,nname,strerror(errno));
2263 R;
2264 }
2265 E{
2266 A(0);
2267 IF(!noshowc)
2268 nsprint("[%lu@%s] * %s: %s:%d.\n",cpid,nname,(isudp?"Created connection":
2269 "Connected successfully"),
2270 /* since these ips do not really exist, other than in an error */
2271 /* situation. blank out the confusion of an error. */
2272 #ifndef DISABLE_SRCIP
2273 ((!SC(IN(ns.sin_addr),"255.255.255.255")||!SC(IN(ns.sin_addr),"0.0.0.0"))?
2274 NOSRCIP:IN(ns.sin_addr))
2275 #else
2276 NOSRCIP
2277 #endif
2278 ,port);
2279 }
2280 }
2281 /* only do the following if outside GTK+. (changing id levels would make */
2282 /* for display problems) */
2283 #ifdef GTK
2284 IF(!isgui){
2285 #endif
2286 /* set the permissions before taking any input, or sending any output. */
2287 /* only done once. since binding would have occured already. */
2288 IF(setperms){
2289 setpermissions(0,1);
2290 setperms=0;
2291 }
2292 #ifdef GTK
2293 }
2294 #endif
2295 #ifndef DISABLE_SYSLOG
2296 wrso("%d-%d id: %lu-%u.%u.%u.%u remote: %s-%u type: %s",slnum_t,(slnum_s++),
2297 cpid,GU(),GEU(),GG(),GEG(),
2298 #ifndef DISABLE_SRCIP
2299 ((!SC(IN(ns.sin_addr),"255.255.255.255")||!SC(IN(ns.sin_addr),"0.0.0.0"))?
2300 NOSRCIP:IN(ns.sin_addr))
2301 #else
2302 NOSRCIP
2303 #endif
2304 ,port,(bindmode?"incoming":"outgoing"));
2305 #endif
2306 IF(setroute){
2307 rsock=SK(AF_INET,(isudpr?SOCK_DGRAM:SOCK_STREAM),(isudpr?IPPROTO_UDP:
2308 IPPROTO_TCP));
2309 parsesocketopt(2,rsock);
2310 B((V *)&rns,SO(rns));
2311 rns.sin_family=AF_INET;
2312 IF(isvhost){
2313 IF((rns.sin_addr.s_addr=IA(vhost))){
2314 IF(!(he=GH(vhost))){
2315 IF(!noshowc)
2316 nsprint("[%lu@%s] * Could not resolve the provided virtual host, using a"
2317 "ny...\n",cpid,nname);
2318 rns.sin_addr.s_addr=HL(INADDR_ANY);
2319 }
2320 E
2321 MC((C *)&rns.sin_addr,(C *)he->h_addr,SO(rns.sin_addr));
2322 }
2323 IF(BI(rsock,(S SA *)&rns,SO(rns))<0){
2324 /* clean up, and use any. */
2325 pe("error binding name to socket, using any",0);
2326 B((V *)&rns,SO(rns));
2327 rns.sin_family=AF_INET;
2328 rns.sin_addr.s_addr=HL(INADDR_ANY);
2329 IF(BI(rsock,(S SA *)&rns,SO(rns))<0){
2330 pe("could not bind name properly, proceeding anyways",0);
2331 rsock=-1;
2332 }
2333 }
2334 }
2335 IF(rsock!=-1){
2336 B((V *)&rns,SO(rns));
2337 rns.sin_family=AF_INET;
2338 rns.sin_port=HS(rport);
2339 IF(!noshowc)
2340 nsprint("[%lu@%s] * Checking the provided (route) host...\n",cpid,nname);
2341 IF((rns.sin_addr.s_addr=IA(rhost))){
2342 /* if not valid, attempts to resolve as a host. */
2343 IF(!(he=GH(rhost))){
2344 /* nothing left to do. */
2345 IF(!noshowc)
2346 nsprint("[%lu@%s] * Could not resolve the provided host, proceeding anyw"
2347 "ays...\n",cpid,nname);
2348 rsock=-1;
2349 }
2350 E
2351 /* successfully resolved. */
2352 MC((C *)&rns.sin_addr,(C *)he->h_addr,SO(rns.sin_addr));
2353 }
2354 IF(!noshowc&&rsock!=-1)
2355 nsprint("[%lu@%s] * Attempting to connect to the provided (route) host..."
2356 "\n",cpid,nname);
2357 IF(G(ENV_TIMEOUT)&&AI((C *)G(ENV_TIMEOUT))>0)
2358 A(AI((C *)G(ENV_TIMEOUT)));
2359 E
2360 A(DFL_TIMEOUT);
2361 IF(rsock==-1||CO(rsock,(S SA *)&rns,SO(rns))){
2362 A(0);
2363 IF(rsock!=-1&&!noshowc)
2364 nsprint("[%lu@%s] * Route connection failed: %s. (proceeding)\n",cpid,
2365 nname,strerror(errno));
2366 /* ensure the error is known. */
2367 rsock=-1;
2368 }
2369 E{
2370 A(0);
2371 IF(!noshowc)
2372 nsprint("[%lu@%s] * Connected (route) successfully: %s:%d.\n",cpid,nname,
2373 #ifndef DISABLE_SRCIP
2374 ((!SC(IN(rns.sin_addr),"255.255.255.255")||!SC(IN(rns.sin_addr),"0.0.0.0")
2375 )?NOSRCIP:IN(rns.sin_addr))
2376 #else
2377 NOSRCIP
2378 #endif
2379 ,rport);
2380 }
2381 }
2382 }
2383 /* states log start time, and ip that was used. if enabled. (-l option) */
2384 IF(islog&&!tnetraw){
2385 logdata("NEW NETSCRIPT SESSION STARTED.",2);
2386 /* logging of the ip used. */
2387 logdata(
2388 /* since these ips do not really exist, other than in an error situation. */
2389 /* blank out the confusion of an error. */
2390 #ifndef DISABLE_SRCIP
2391 ((!SC(IN(ns.sin_addr),"255.255.255.255")||!SC(IN(ns.sin_addr),"0.0.0.0"))?
2392 NOSRCIP:IN(ns.sin_addr))
2393 #else
2394 NOSRCIP
2395 #endif
2396 ,2);
2397 }
2398 /* check, and use the ns_connect() symbol, it passes the connection type, */
2399 /* ip value, and port. (short, unsigned long int, int) */
2400 #ifndef DISABLE_MODULES
2401 IF(vmodule)
2402 (*connect_function)(bindmode,ns.sin_addr,port);
2403 #endif
2404 /* for the $" rule, will set the time of the connection to be compared to. */
2405 TM(&rtm);
2406 /* cleans out the dynamic (int)buffer for the "one time" variable. */
2407 B((V *)rs_dynamic,SO(rs_dynamic));
2408 /* this is for the "$." variable, it makes it not truely static. resets */
2409 /* every connection if the value is two. (or back to one) */
2410 F(i=0;i<tot_i;i++){
2411 IF(rs_static[i]>1)
2412 rs_static[i]-=2;
2413 }
2414 /* cleans out the dynamic (int)buffer for variable data. (usable) */
2415 /* little more involved than a bzero() for the static vars set by the */
2416 /* command line. */
2417 F(i=0;i<10;i++){
2418 IF(dynamicvarset[i]==1){
2419 FR(dynamicvar[i]);
2420 dynamicvarset[i]=0;
2421 }
2422 }
2423 IF(initsend){
2424 /* handle the unique initial input data. if it is a "?" it will prompt */
2425 /* for input. make sure not to allow if backgrounded. */
2426 IF(!SC(iswrite,"?")&&!isbga){
2427 /* gui version of the request. */
2428 #ifdef GTK
2429 IF(isgui){
2430 IF(isguiwait)
2431 R;
2432 E{
2433 nsprint("input request: enter dynamic initial data to send.\n");
2434 /* only if non-generic. */
2435 IF(!isbgui){
2436 GTE();
2437 /* make sure focus is on the entry box. */
2438 GWGF(gen);
2439 /* show the entry box. */
2440 GWS(gen);
2441 GTL();
2442 }
2443 isguiwait=1;
2444 W(isguiwait)
2445 USLP(250000);
2446 }
2447 }
2448 /* typical version of the request. */
2449 E{
2450 #endif
2451 IF(!(ifd=FO(ttyn,"r")))
2452 pe("could not open standard input for read",0);
2453 E{
2454 /* none of this will work anyways if backgrounded. will close the fd. */
2455 IF(!isbga){
2456 IF(!noshowp)
2457 pe("initial send defined user input, incoming data suspended",0);
2458 /* show default, or reason prompt, if not in raw mode. */
2459 IF(!tnetraw)
2460 nsprint("enter initial data to send: ");
2461 B(iread,(BASE_BUFFER*4+1));
2462 /* truncated for pd(). */
2463 IF(FS(iread,(SO(iread)-1),ifd))
2464 F(o=0;o<SL(iread);o++)
2465 IF(iread[o]==0x0A)
2466 iread[o]=0x0;
2467 IF(!noshowp)
2468 pe("input received, incoming data resumed",0);
2469 IF(!nossend)
2470 pd(iread,0,columns);
2471 wro(iread,SL(iread),0);
2472 wro("\n",1,0);
2473 IF(islog&&!tnetraw)
2474 logdata(iread,0);
2475 }
2476 FC(ifd);
2477 }
2478 #ifdef GTK
2479 }
2480 #endif
2481 }
2482 E{
2483 /* sends the initial data supplied by the argument if supplied. */
2484 IF(!nossend)
2485 pd(iswrite,0,columns);
2486 wro(iswrite,SL(iswrite),0);
2487 wro("\n",1,0);
2488 /* add the initial data to the log, if enabled. (-i, and -l option) */
2489 IF(islog&&!tnetraw)
2490 logdata(iswrite,0);
2491 }
2492 }
2493 IF(runcmd)
2494 dumpexec(execfile,0);
2495 IF(alrm)
2496 A(alrm);
2497 W(1){
2498 B(sread,(BASE_BUFFER*4+1));
2499 IF(!RD(sock,sread,(SO(sread)-1))){
2500 pe("socket reading halted/finished",0);
2501 closesocket(0);
2502 R;
2503 }
2504 /* handle incoming telnet dumping. (-y, and -Y options) */
2505 dumptelnet(sread);
2506 IF(islog&&tnetraw)
2507 logdata(sread,3);
2508 /* check, and use the ns_incoming_raw() symbol. it passes the raw dump of */
2509 /* the socket read buffer, the size of the buffer, and the length of the */
2510 /* buffer. (char *, int, int) */
2511 #ifndef DISABLE_MODULES
2512 IF(vmodule)
2513 (*incoming_raw_function)(sread,SO(sread),SL(sread));
2514 #endif
2515 F(i=0;i<SL(sread);i++){
2516 /* telnet protocol handling, bytes set before handled. */
2517 /* using this method will have socket reading not wait for a \r, or a \n. */
2518 /* (the -T option) */
2519 IF(tnet&&sread[i]==0xFF&&sread[i+1]&&sread[i+2]){
2520 B(telnet,3);
2521 telnet[0]=0xFF;
2522 IF(sread[i+1]==0xFC||sread[i+1]==0xFB)
2523 telnet[1]=0xFE;
2524 EI(sread[i+1]==0xFE||sread[i+1]==0xFD)
2525 telnet[1]=0xFC;
2526 IF(telnet[1]==0xFE||telnet[1]==0xFC){
2527 /* checks to change socket handling for later. */
2528 IF(!truetnet){
2529 pe("received a telnet protocol option, entering telnet reading mode",0);
2530 truetnet=1;
2531 }
2532 /* the option. */
2533 telnet[2]=sread[i+2];
2534 wro(telnet,SO(telnet),0);
2535 IF(!nossend&&!notnetopt)
2536 nsprint("%s(TELNETD-OPT REPLIED: 0x%.2x 0x%.2x 0x%.2x -> 0x%.2x 0x%.2x "
2537 "0x%.2x)\n",!nofrom?"-> ":"",sread[i],sread[i+1],sread[i+2],telnet[0],
2538 telnet[1],telnet[2]);
2539 }
2540 }
2541 /* telnet mode will not wait for a \r, or \n, must get one or more telnet */
2542 /* option before automatically allowed. so, not to create problems with */
2543 /* bad syntax. */
2544 IF(sread[i]==0x0A||sread[i]==0x0D||(tnet&&truetnet&&!sread[i+1])){
2545 /* check where to place the null byte, and make sure byte exists for the */
2546 /* extended null byte. it will not add the last byte if its the last */
2547 /* byte. */
2548 IF(tnet&&truetnet&&!sread[i+1]&&(BASE_BUFFER*16+1)>(j+1)){
2549 /* check, and use the ns_incoming_char() symbol, it passes the byte to */
2550 /* be added to the buffer. (int) */
2551 #ifndef DISABLE_MODULES
2552 IF(vmodule)
2553 (*incoming_char_function)(sread[i]);
2554 #endif
2555 /* append the byte that is usually a \r, or \n. but, for telent */
2556 /* support a non-static character. */
2557 sreadl[j]=sread[i];
2558 sreadl[(j+1)]=0x0;
2559 }
2560 E
2561 sreadl[j]=0x0;
2562 /* handle the -S, and -U command line arguments for delaying. */
2563 IF(sdelay)
2564 SLP(sdelay);
2565 IF(sudelay)
2566 USLP(sudelay);
2567 /* pass to the routed host, if enabled. (-R option) */
2568 IF(setroute){
2569 wro(sreadl,SL(sreadl),1);
2570 IF(SL(sreadl))
2571 wro("\n",1,1);
2572 }
2573 /* check, and use the ns_incoming() symbol, it passes the incoming */
2574 /* string of data, the size of that data, and the socket value. */
2575 /* (char *, int, int) */
2576 #ifndef DISABLE_MODULES
2577 IF(vmodule&&SL(sreadl))
2578 (*incoming_function)(sreadl,SL(sreadl),sock);
2579 #endif
2580 IF(!nosrecv)
2581 pd(sreadl,1,columns);
2582 /* add the output to the log, if enabled. (-l option) */
2583 IF(islog&&!tnetraw)
2584 logdata(sreadl,1);
2585 /* reset the temporary variable. */
2586 IF(stoprules==2)
2587 stoprules=0;
2588 F(k=0;k<tot_i&&SL(sreadl);k++){
2589 /* have not formed the swrite buffer yet, read the output for the */
2590 /* start variable, no need to modify anything yet anyways. */
2591 IF((!stoprules||!SNCC(output[k],NS_START,SL(NS_START)))&&!prewordmatch(
2592 input[k],sreadl)&&!(rs_static[k]&&rs_dynamic[k])){
2593 /* cancel possibility of a repeated rule. */
2594 IF(rs_static[k]){
2595 IF(!noshowp)
2596 pe("ruleset defined this rule to only be used once",0);
2597 rs_dynamic[k]=1;
2598 }
2599 IF(rs_delay[k]){
2600 IF(!noshowp)
2601 pe("ruleset defined a delay before processing of this rule",0);
2602 SLP(rs_delay[k]);
2603 }
2604 /* parse the arguments input->output, $1 $2 $3, makes swrite buf. */
2605 /* rules will redo this for possible skipped arguments in this run. */
2606 /* it will be done when the buffer gets chomped down using a rule. */
2607 parseoutput(sreadl,output[k]);
2608 /* check, and handle the direct stop variable. */
2609 IF(!SNCC(swrite,NS_STOP,SL(NS_STOP))){
2610 /* changes buffer to dump the variable. for later display. */
2611 truncateoutput(SL(NS_STOP));
2612 /* update the new clean buffer. */
2613 parseoutput(sreadl,swrite);
2614 /* no possibility of format bug, pe() handles like text. */
2615 IF(!noshowp)
2616 pe(SL(swrite)?swrite:"ruleset defined ruleset stop",0);
2617 stoprules=1;
2618 }
2619 /* check, and handle the direct restart variable, even without stop. */
2620 EI(!SNCC(swrite,NS_START,SL(NS_START))){
2621 /* changes buffer to dump the variable. for later display. */
2622 truncateoutput(SL(NS_START));
2623 /* update the new clean buffer. */
2624 parseoutput(sreadl,swrite);
2625 /* no possibility of format bug, pe() handles like text. */
2626 IF(!noshowp)
2627 pe(SL(swrite)?swrite:"ruleset defined ruleset start",0);
2628 stoprules=0;
2629 }
2630 /* check, and handle for the direct halt variable. */
2631 EI(!SNCC(swrite,NS_HALT,SL(NS_HALT))){
2632 /* changes buffer to dump the variable. for later display. */
2633 truncateoutput(SL(NS_HALT));
2634 /* update the new clean buffer. */
2635 parseoutput(sreadl,swrite);
2636 /* no possibility of format bug, pe() handles like text. */
2637 IF(!noshowp)
2638 pe(SL(swrite)?swrite:"ruleset defined halt from continuing",0);
2639 stoprules=2;
2640 }
2641 /* check, and handle for the direct quit variable. */
2642 EI(!SNCC(swrite,NS_QUIT,SL(NS_QUIT))){
2643 /* changes buffer to dump the variable. for later display. */
2644 truncateoutput(SL(NS_QUIT));
2645 /* update the new clean buffer. */
2646 parseoutput(sreadl,swrite);
2647 /* no possibility of format bug, pe() handles like text. */
2648 IF(!noshowp)
2649 pe(SL(swrite)?swrite:"ruleset defined socket kill",0);
2650 closesocket(0);
2651 R;
2652 }
2653 /* check, and handle the direct ask variable. */
2654 EI(!SNCC(swrite,NS_ASK,SL(NS_ASK))){
2655 /* can not exactly do this if it is backgrounded. */
2656 IF(isbga)
2657 R;
2658 /* changes buffer to dump the variable. for later display. */
2659 truncateoutput(SL(NS_ASK));
2660 /* update the new clean buffer. */
2661 parseoutput(sreadl,swrite);
2662 /* gui version of the request. */
2663 #ifdef GTK
2664 IF(isgui){
2665 IF(isguiwait)
2666 R;
2667 E{
2668 nsprint("input request: %s.\n",SL(swrite)?swrite:"enter response");
2669 /* only if non-generic. */
2670 IF(!isbgui){
2671 GTE();
2672 /* make sure focus is on the entry box. */
2673 GWGF(gen);
2674 /* show the entry box. */
2675 GWS(gen);
2676 GTL();
2677 }
2678 isguiwait=1;
2679 W(isguiwait)
2680 USLP(250000);
2681 }
2682 }
2683 /* typical version of the request. */
2684 E{
2685 #endif
2686 IF(!(ifd=FO(ttyn,"r")))
2687 pe("could not open standard input for read",0);
2688 E{
2689 IF(!noshowp)
2690 pe("ruleset defined user input, incoming data suspended",0);
2691 /* show default, or reason prompt, if not in raw mode. */
2692 IF(!tnetraw)
2693 nsprint("%s: ",SL(swrite)?swrite:"enter response");
2694 B(iwrite,(BASE_BUFFER*4+1));
2695 #ifdef NCURSES
2696 IF(isncurses)
2697 wgetnstr(nw3,iwrite,(SO(iwrite)-1));
2698 E
2699 #endif
2700 IF(FS(iwrite,(SO(iwrite)-1),ifd))
2701 F(o=0;o<SL(iwrite);o++)
2702 IF(iwrite[o]==0x0A)
2703 iwrite[o]=0x0;
2704 IF(!noshowp)
2705 pe("input received, incoming data resumed",0);
2706 IF(!nossend)
2707 pd(iwrite,0,columns);
2708 wro(iwrite,SL(iwrite),0);
2709 wro("\n",1,0);
2710 IF(islog&&!tnetraw)
2711 logdata(iwrite,0);
2712 FC(ifd);
2713 }
2714 #ifdef GTK
2715 }
2716 #endif
2717 }
2718 /* check, and handle the remove/replace variable. */
2719 EI(!SNCC(swrite,NS_TRUNC,SL(NS_TRUNC))){
2720 /* changes buffer to dump the variable. for later use. */
2721 truncateoutput(SL(NS_TRUNC));
2722 /* update the new clean buffer. */
2723 parseoutput(sreadl,swrite);
2724 /* has to have at least one character to remove. */
2725 IF(SL(swrite)==1){
2726 F(l=0;l<SL(sreadl);l++)
2727 IF(sreadl[l]==swrite[0]){
2728 /* push the rest of the line back. */
2729 F(m=(l+1);m<SL(sreadl);m++){
2730 sreadl[(m-1)]=sreadl[m];
2731 }
2732 /* remove the leftover byte. */
2733 sreadl[(m-1)]=0x0;
2734 /* possibly a new character is here. */
2735 l--;
2736 }
2737 }
2738 /* two, or more replaces. instead of removal. */
2739 EI(SL(swrite)>1)
2740 F(l=0;l<SL(sreadl);l++)
2741 IF(sreadl[l]==swrite[0])
2742 sreadl[l]=swrite[1];
2743 }
2744 EI(!SNCC(swrite,NS_TOKENL,SL(NS_TOKENL))){
2745 /* changes buffer to dump the variable. for later use. */
2746 truncateoutput(SL(NS_TOKENL));
2747 /* update the new clean buffer. */
2748 parseoutput(sreadl,swrite);
2749 IF(SL(swrite)>0)
2750 /* using the int again here. */
2751 F(l=0;l<SL(sreadl);l++)
2752 IF(sreadl[l]==swrite[0])
2753 sreadl[l]=0x0;
2754 }
2755 EI(!SNCC(swrite,NS_TOKENR,SL(NS_TOKENR))){
2756 /* changes buffer to dump the variable. for later use. */
2757 truncateoutput(SL(NS_TOKENR));
2758 /* update the new clean buffer. */
2759 parseoutput(sreadl,swrite);
2760 IF(SL(swrite)>0){
2761 /* using the int(s) again here. */
2762 F(m=l=0;l<SL(sreadl);l++){
2763 IF(m)
2764 sreadl[(l-m)]=sreadl[l];
2765 IF(sreadl[l]==swrite[0]&&!m)
2766 m=(l+1);
2767 }
2768 IF(m)
2769 sreadl[(l-m)]=0x0;
2770 }
2771 }
2772 /* check, and handle the display variable. */
2773 EI(!SNCC(swrite,NS_STR,SL(NS_STR))){
2774 /* changes buffer to dump the variable. for later use. */
2775 truncateoutput(SL(NS_STR));
2776 /* update the new clean buffer. */
2777 parseoutput(sreadl,swrite);
2778 /* check for the comma with data, so atoi() will not fault. */
2779 IF(!parameter(swrite,0,0x2C))
2780 left=AI(parm);
2781 /* only happens if the variable is by itself. */
2782 E
2783 left=0;
2784 IF(!parameter(swrite,1,0x2C))
2785 right=AI(parm);
2786 /* also, only happens if the variable is by itself. */
2787 E
2788 right=-1;
2789 /* can not be less than zero. or, should not be. */
2790 IF(left<0)
2791 left=0;
2792 /* commonly thought that negative values equal to the end of the */
2793 /* line. agree with the standard. */
2794 IF(right<0||right>SL(sreadl))
2795 right=SL(sreadl);
2796 F(r=q=0;q<SL(sreadl);q++){
2797 /* starts at point(left). but, stops before point(right). */
2798 IF(q>=left&&q<right)
2799 sreadl[r++]=sreadl[q];
2800 }
2801 sreadl[r]=0x0;
2802 }
2803 /* check, and handle the format variable. */
2804 EI(!SNCC(swrite,NS_FMT,SL(NS_FMT))){
2805 /* changes buffer to dump the variable. for later formatting. */
2806 truncateoutput(SL(NS_FMT));
2807 /* update the new clean buffer. */
2808 parseoutput(sreadl,swrite);
2809 /* clean it out. */
2810 B(sreadl,(BASE_BUFFER*16+1));
2811 /* byte-by-byte transfer/check. */
2812 F(p=0;((p<(SO(sreadl)-1))&&(p<(SL(swrite))));p++)
2813 sreadl[p]=swrite[p];
2814 sreadl[p]=0x0;
2815 }
2816 /* check, and handle the display variable. */
2817 EI(!SNCC(swrite,NS_ECHO,SL(NS_ECHO))){
2818 /* changes buffer to dump the variable. for later display. */
2819 truncateoutput(SL(NS_ECHO));
2820 /* update the new clean buffer. */
2821 parseoutput(sreadl,swrite);
2822 /* no possibility of format bug, pe() handles like text. */
2823 /* ruleset defined this, so -C will not cut this off. */
2824 pe(SL(swrite)?swrite:"ruleset defined an empty display rule",0);
2825 }
2826 /* check, and handle the no return write (raw) variable. */
2827 /* shows up like a standard write out. */
2828 EI(!SNCC(swrite,NS_RAW,SL(NS_RAW))){
2829 /* changes buffer to dump the variable. for later display. */
2830 truncateoutput(SL(NS_RAW));
2831 /* update the new clean buffer. */
2832 parseoutput(sreadl,swrite);
2833 IF(!nossend)
2834 pd(swrite,0,columns);
2835 wro(swrite,SL(swrite),0);
2836 }
2837 /* check, and handle the disable rule variable. */
2838 EI(!SNCC(swrite,NS_DISABLE,SL(NS_DISABLE))){
2839 /* changes buffer to dump the variable. for later display. */
2840 truncateoutput(SL(NS_DISABLE));
2841 /* update the new clean buffer. */
2842 parseoutput(sreadl,swrite);
2843 IF(SL(swrite)){
2844 l=AI(swrite);
2845 IF(l<tot_i){
2846 IF(!noshowp)
2847 pe("ruleset defined a rule to be disabled",0);
2848 rs_dynamic[l]=1;
2849 /* if the value is two. so, it will get reset every connection. */
2850 /* will be three if its already set to go off. */
2851 IF(rs_static[l]<=1)
2852 rs_static[l]+=2;
2853 }
2854 E
2855 IF(!noshowp)
2856 pe("ruleset defined a non-existent rule to be disabled",0);
2857 }
2858 }
2859 /* check, and handle the file dump variable. */
2860 EI(!SNCC(swrite,NS_DUMP,SL(NS_DUMP))){
2861 IF(isprivileged)
2862 pe("can not read/dump data from a file with privileged access",0);
2863 E{
2864 /* changes buffer to dump the variable. for later display. */
2865 truncateoutput(SL(NS_DUMP));
2866 /* update the new clean buffer. */
2867 parseoutput(sreadl,swrite);
2868 #ifndef DISABLE_SYSLOG
2869 wrso("%d-%d id: %lu-%u.%u.%u.%u read: %s",slnum_t,(slnum_s++),cpid,
2870 GU(),GEU(),GG(),GEG(),swrite);
2871 #endif
2872 IF(AC(swrite,R_OK))
2873 pe("could not access the file requested to dump in the ruleset",0);
2874 E{
2875 IF(!(dfd=FO(swrite,"r")))
2876 pe("file requested by ruleset does not appear to exist, or is not re"
2877 "adable",0);
2878 E{
2879 B(dread,(BASE_BUFFER*4+1));
2880 /* no need to parse the data that comes from this file, instead it */
2881 /* directly dumps the file data. single byte writing for all */
2882 /* character types. */
2883 IF(!noshowp)
2884 pe("ruleset requested a file dump to the remote host",0);
2885 W((n=FG(dfd))!=EOF){
2886 sb[0]=n;
2887 wro(sb,1,0);
2888 }
2889 IF(!noshowp)
2890 pe("ruleset requested file dump was successful",0);
2891 }
2892 FC(dfd);
2893 }
2894 }
2895 }
2896 /* check, and handle the write/append variable. checks for append */
2897 /* first, beacuse if one variable is going to be larger it will be */
2898 /* the apppend variable. */
2899 EI(!SNCC(swrite,NS_WRITE,SL(NS_WRITE))||!SNCC(swrite,NS_APPEND,
2900 SL(NS_APPEND))){
2901 IF(isprivileged)
2902 pe("can not write data to a file with privileged access",0);
2903 E{
2904 /* find out which variable it is, two in one function here. */
2905 IF(!SNCC(swrite,NS_APPEND,SL(NS_APPEND))){
2906 n=SL(NS_APPEND);
2907 /* append type, fopen(). */
2908 sb[0]=0x61;
2909 }
2910 E{
2911 n=SL(NS_WRITE);
2912 /* write type, fopen(). */
2913 sb[0]=0x77;
2914 }
2915 /* changes buffer to dump the variable. for later display. */
2916 truncateoutput(n);
2917 /* update the new clean buffer. */
2918 parseoutput(sreadl,swrite);
2919 #ifndef DISABLE_SYSLOG
2920 wrso("%d-%d id: %lu-%u.%u.%u.%u write: %s",slnum_t,(slnum_s++),cpid,
2921 GU(),GEU(),GG(),GEG(),swrite);
2922 #endif
2923 /* check for existence with non-writability. */
2924 IF(!AC(swrite,F_OK)&&AC(swrite,W_OK))
2925 pe("could not access the file requested to write to in the ruleset",
2926 0);
2927 E{
2928 IF(!(dfd=FO(swrite,sb)))
2929 pe("file requested to write to could not be opened properly",0);
2930 E{
2931 FP(dfd,"%s\n",sreadl);
2932 IF(!noshowp)
2933 pe("ruleset requested write out was successful",0);
2934 }
2935 FC(dfd);
2936 }
2937 }
2938 }
2939 /* check, and handle the chdir variable. */
2940 EI(!SNCC(swrite,NS_CHDIR,SL(NS_CHDIR))){
2941 /* changes buffer to dump the variable. for later display. */
2942 truncateoutput(SL(NS_CHDIR));
2943 /* update the new clean buffer. */
2944 parseoutput(sreadl,swrite);
2945 IF(SL(swrite)){
2946 IF(CD(swrite)){
2947 IF(!noshowp)
2948 pe("ruleset requested directory change failed",0);
2949 }
2950 E{
2951 IF(!noshowp)
2952 pe("ruleset requested directory change was successful",0);
2953 }
2954 }
2955 }
2956 /* check, and handle the (send to) route host variable. */
2957 EI(!SNCC(swrite,NS_ROUTE,SL(NS_ROUTE))){
2958 /* changes buffer to dump the variable. for later display. */
2959 truncateoutput(SL(NS_ROUTE));
2960 /* update the new clean buffer. */
2961 parseoutput(sreadl,swrite);
2962 IF(SL(swrite)){
2963 IF(rsock==-1){
2964 IF(!noshowp)
2965 pe("rulset requested route write failed, no (open) route socket",0);
2966 }
2967 E{
2968 wro(swrite,SL(swrite),2);
2969 wro("\n",1,2);
2970 IF(!noshowp)
2971 pe("ruleset requested route write was successful",0);
2972 }
2973 }
2974 }
2975 /* check, and handle the time passed (send) variable. */
2976 EI(!SNCC(swrite,NS_TIMED,SL(NS_TIMED))){
2977 /* set the current time to check the value, compared to the */
2978 /* connection value. */
2979 TM(&ctm);
2980 /* changes buffer to dump the variable. for later display. */
2981 truncateoutput(SL(NS_TIMED));
2982 /* update the new clean buffer. */
2983 parseoutput(sreadl,swrite);
2984 parameter(swrite,0,0x2C);
2985 IF(wischeck(parm,1)&&(rtm+AI(parm))<ctm){
2986 IF(SL(swrite)>(SL(parm)+1)){
2987 truncateoutput(SL(parm)+1);
2988 IF(!nossend)
2989 pd(swrite,0,columns);
2990 wro(swrite,SL(swrite),0);
2991 wro("\n",1,0);
2992 }
2993 }
2994 }
2995 /* check, and handle the execution dump/formatting variables. */
2996 EI(!SNCC(swrite,NS_EXEC,SL(NS_EXEC))||!SNCC(swrite,NS_EXECF,SL(NS_EXECF))
2997 ){
2998 /* will reuse this int again, and again. */
2999 p=(!SNCC(swrite,NS_EXEC,SL(NS_EXEC))?0:1);
3000 /* changes buffer to dump the variable. for later display. */
3001 truncateoutput(p?SL(NS_EXECF):SL(NS_EXEC));
3002 /* update the new clean buffer. */
3003 parseoutput(sreadl,swrite);
3004 IF(!noshowp&&!p)
3005 pe("ruleset requested a local program execution",0);
3006 /* privileged checking occurs with this function, since its used */
3007 /* elsewhere. */
3008 dumpexec(swrite,p);
3009 IF(p&&SL(execformat)){
3010 /* byte-by-byte transfer/check. (reused int p) */
3011 F(p=0;((p<(SO(sreadl)-1))&&(p<(SL(execformat))));p++)
3012 sreadl[p]=execformat[p];
3013 sreadl[p]=0x0;
3014 }
3015 }
3016 /* not required to check every slot for a byte. but, i do. */
3017 EI(swrite[0]&&swrite[1]&&swrite[2]&&swrite[3]&&swrite[4]&&swrite[0]==
3018 PARAMETER_VAR_CHAR&&swrite[1]==0x7B&&ID((U I)swrite[2])&&swrite[3]==0x7D
3019 &&swrite[4]==0x3D){
3020 /* store the number before chomping it down. */
3021 s=(swrite[2]-0x30);
3022 /* do not overwrite the statically set variables. */
3023 IF(dynamicvarset[s]!=2){
3024 /* changes buffer to dump the variable. for later display. */
3025 truncateoutput(5);
3026 /* update the new clean buffer. */
3027 parseoutput(sreadl,swrite);
3028 IF(dynamicvarset[s]==1)
3029 FR(dynamicvar[s]);
3030 IF(!(dynamicvar[s]=(C *)SDU(swrite)))
3031 pe("parsesocket(): duplication of memory error",1);
3032 dynamicvarset[s]=1;
3033 }
3034 }
3035 E{
3036 IF(!nossend)
3037 pd(swrite,0,columns);
3038 wro(swrite,SL(swrite),0);
3039 wro("\n",1,0);
3040 /* add the input to the log, if enabled. (-l option) */
3041 IF(islog&&!tnetraw)
3042 logdata(swrite,0);
3043 }
3044 }
3045 }
3046 B(sreadl,(BASE_BUFFER*16+1));
3047 j=0;
3048 }
3049 E
3050 /* do not print the telnet options, no one wants to see that. */
3051 IF(tnet&&truetnet&&sread[i]==0xFF&&(sread[i+1]==0xFE||sread[i+1]==0xFD||
3052 sread[i+1]==0xFC||sread[i+1]==0xFB))
3053 i+=2;
3054 /* for reading of printable characters only. meaning non-printable */
3055 /* characters will not make it to ruleset processing. but, the telnet */
3056 /* protocol handling is processed before this point. so, it will not be */
3057 /* effected. (-P option). also, omits defined characters from them -o */
3058 /* option. */
3059 EI((!printonly||IP((U I)sread[i]))&&(!omitchars||!STC(ochars,sread[i]))){
3060 /* check the buffer that is filling until a completed line, making sure */
3061 /* not to exceed bounds. if it does the buffer is cleared. */
3062 IF(j>=SO(sreadl)){
3063 B(sreadl,(BASE_BUFFER*16+1));
3064 j=0;
3065 }
3066 /* write the byte if nothing before this option wanted to stop it. */
3067 E{
3068 /* check, and use the ns_incoming_char() symbol, it passes the byte to */
3069 /* be added to the buffer. (int) */
3070 #ifndef DISABLE_MODULES
3071 IF(vmodule)
3072 (*incoming_char_function)(sread[i]);
3073 #endif
3074 sreadl[j++]=sread[i];
3075 }
3076 }
3077 }
3078 }
3079 /* once more. better safe than sorry, do not want fds to fill up. */
3080 closesocket(0);
3081 R;
3082 }
3083 /* for display types of version information. */
showinfo(U SH type)3084 V showinfo(U SH type){
3085 C *timebuf;
3086 T tm;
3087 IF(type==1){
3088 /* left without uname (verbose display) information. */
3089 nsprint("[%lu] * Version: netscript/v%s!%s. -- License: %s.\n"
3090 "[%lu] * Id data: %s\n"
3091 "[%lu] * Mod: %s -- Src: %s -- Arp: %s -- Gui: %s -- Slg: %s -- Ncr: %s.\n"
3092 "[%lu] * Author: %s.%s\n",cpid,VERSION,COMPTYPE,license,cpid,id,cpid,
3093 (defined[0]?"on":"off"),(defined[1]?"on":"off"),(defined[2]?"on":"off"),
3094 (defined[3]?"on":"off"),(defined[4]?"on":"off"),(defined[5]?"on":"off"),
3095 cpid,author,isprivileged?" (privileged)":"");
3096 }
3097 EI(type==2){
3098 TM(&tm);
3099 IF(!(timebuf=(C *)SDU(CT(&tm))))
3100 pe("showinfo(): duplication of memory error",1);
3101 IF(timebuf[(SL(timebuf)-1)]==0x0A)
3102 timebuf[(SL(timebuf)-1)]=0x0;
3103 nsprint("[ netscript: (version: v%s!%s - launchtime: %s) ]\n",VERSION,
3104 COMPTYPE,timebuf);
3105 FR(timebuf);
3106 }
3107 R;
3108 }
3109 /* this function will handle the prompted version of netscript. */
iface(C * base)3110 V iface(C *base){
3111 U SH r=0;
3112 U SH s=0;
3113 U I i=0;
3114 U I j=0;
3115 U I k=0;
3116 C **tmpname;
3117 C *tmptime;
3118 U C icwd[(BASE_BUFFER*4+1)];
3119 U C iread[(BASE_BUFFER*4+1)];
3120 FL *ifd;
3121 PT fp;
3122 T tm;
3123 S group *gent;
3124 S passwd *pent;
3125 /* no user aborts in this mode, will reset at the end of the function. */
3126 SG(SIGINT,SIG_IGN);
3127 /* no reading of (non-ruleset) files when privileged. this is silent. */
3128 IF(!isprivileged){
3129 IF(!(ifd=FO(rcfile,"r")))
3130 s=0;
3131 E
3132 s=1;
3133 }
3134 W(!r){
3135 IF(!s)
3136 nsprint("%s",base);
3137 IF(!s&&!(ifd=FO(ttyn,"r")))
3138 pe("could not open standard input for read",1);
3139 E{
3140 B(iread,(BASE_BUFFER*4+1));
3141 IF(FS(iread,(SO(iread)-1),ifd)){
3142 F(i=0;i<SL(iread);i++){
3143 IF(iread[i]==0x0A||iread[i]==0x0D)
3144 iread[i]=0x0;
3145 /* apply question marks to unprintable characters. */
3146 IF(iread[i]&&!isprint(iread[i]))
3147 iread[i]=0x3F;
3148 }
3149 }
3150 /* will close the stream below, now that its finished. */
3151 EI(s)
3152 s=0;
3153 }
3154 IF(!s)
3155 FC(ifd);
3156 /* command handling. */
3157 IF(!SNCC(iread,"anotify",7)){
3158 noshowa=(noshowa?0:1);
3159 nsprint("anotify: %sabled\n",(noshowa?"en":"dis"));
3160 }
3161 EI(!SNCC(iread,"background",10)){
3162 isbg=(isbg?0:1);
3163 nsprint("background: %sabled\n",(isbg?"en":"dis"));
3164 }
3165 EI(!SNCC(iread,"bind",4)){
3166 IF(sethost)
3167 nsprint("bind: there are hostname(s) defined to connect to, can not define"
3168 ".\n");
3169 E{
3170 bindmode=(bindmode?0:1);
3171 nsprint("bind: %sabled\n",(bindmode?"en":"dis"));
3172 }
3173 }
3174 EI(!SNCC(iread,"chdir",5)){
3175 IF(!parameter(iread,1,0x20)){
3176 IF(setcdir)
3177 FR(cdir);
3178 parsecmdline(parm);
3179 IF(!(cdir=(C *)SDU(parsedline)))
3180 pe("iface(): duplication of memory error",1);
3181 setcdir=1;
3182 }
3183 nsprint("chdir: %s\n",(setcdir?cdir:IFACE_UNSET));
3184 }
3185 EI(!SNCC(iread,"chroot",6)){
3186 IF(!parameter(iread,1,0x20)){
3187 IF(setrdir)
3188 FR(rdir);
3189 parsecmdline(parm);
3190 IF(!(rdir=(C *)SDU(parsedline)))
3191 pe("iface(): duplication of memory error",1);
3192 setrdir=1;
3193 }
3194 nsprint("chroot: %s\n",(setrdir?rdir:IFACE_UNSET));
3195 }
3196 EI(!SNCC(iread,"cnotify",7)){
3197 noshowc=(noshowc?0:1);
3198 nsprint("cnotify: %sabled\n",(noshowc?"en":"dis"));
3199 }
3200 EI(!SNCC(iread,"disparrows",10)){
3201 nofrom=(nofrom?0:1);
3202 nsprint("disparrows: %sabled\n",(nofrom?"en":"dis"));
3203 }
3204 EI(!SNCC(iread,"dispincoming",12)){
3205 nosrecv=(nosrecv?0:1);
3206 nsprint("dispincoming: %sabled\n",(nosrecv?"en":"dis"));
3207 }
3208 EI(!SNCC(iread,"dispoutgoing",12)){
3209 nossend=(nossend?0:1);
3210 nsprint("dispoutgoing: %sabled\n",(nossend?"en":"dis"));
3211 }
3212 EI(!SNCC(iread,"disptype",8)){
3213 IF(displaytype++>1)
3214 displaytype=0;
3215 nsprint("disptype: %s\n",(!displaytype?"disabled":(displaytype==1?"hex":
3216 "dec")));
3217 }
3218 EI(!SNCC(iread,"execexit",8)){
3219 runexit=(runexit?0:1);
3220 nsprint("execexit: %sabled\n",(runexit?"en":"dis"));
3221 }
3222 EI(!SNCC(iread,"execfile",8)){
3223 IF(isprivileged)
3224 nsprint("execfile: can not log data to a file with privileged access.\n");
3225 E{
3226 IF(!parameter(iread,1,0x20)){
3227 IF(runcmd)
3228 FR(execfile);
3229 parsecmdline(parm);
3230 IF(!(execfile=(C *)SDU(parsedline)))
3231 pe("iface(): duplication of memory error",1);
3232 runcmd=1;
3233 }
3234 nsprint("execfile: %s\n",(runcmd?execfile:IFACE_UNSET));
3235 }
3236 }
3237 EI(!SNCC(iread,"execinteractive",15)){
3238 isiexec=(isiexec?0:1);
3239 nsprint("execinteractive: %sabled\n",(isiexec?"en":"dis"));
3240 }
3241 EI(!SNCC(iread,"execpre",7)){
3242 IF(!parameter(iread,1,0x20)){
3243 IF(runpre)
3244 FR(execpre);
3245 parsecmdline(parm);
3246 IF(!(execpre=(C *)SDU(parsedline)))
3247 pe("iface(): duplication of memory error",1);
3248 runpre=1;
3249 }
3250 nsprint("execpre: %s\n",(runpre?execpre:IFACE_UNSET));
3251 }
3252 EI(!SNCC(iread,"execshell",9)){
3253 IF(!parameter(iread,1,0x20)){
3254 parsecmdline(parm);
3255 IF(AC(parsedline,X_OK))
3256 nsprint("execshell: argument1 is not a valid file, or is not executable."
3257 "\n");
3258 E{
3259 IF(setshell)
3260 FR(eshell);
3261 IF(!(eshell=(C *)SDU(parsedline)))
3262 pe("iface(): duplication of memory error",1);
3263 setshell=1;
3264 }
3265 }
3266 nsprint("execshell: %s\n",(setshell?eshell:IFACE_UNSET));
3267 }
3268 EI(!SNCC(iread,"execwait",8)){
3269 IF(!parameter(iread,1,0x20)){
3270 IF(AI(parm)<0)
3271 nsprint("execwait: argument1 must be a positive integer, can not define."
3272 "\n");
3273 E
3274 xalrm=AI(parm);
3275 }
3276 nsprint("execwait: %d\n",xalrm);
3277 }
3278 EI(!SNCC(iread,"forever",7)){
3279 forever=(forever?0:1);
3280 nsprint("forever: %sabled\n",(forever?"en":"dis"));
3281 }
3282 #ifdef GTK
3283 EI(!SNCC(iread,"guicolor",8)){
3284 IF(!parameter(iread,1,0x20)){
3285 parsecmdline(parm);
3286 IF(SL(parsedline)==6){
3287 B((V *)guic,SO(guic));
3288 F(isguic=i=0;i<6;i+=2){
3289 IF(IL((U I)parsedline[i]))
3290 j=(TL(parsedline[i])-0x56);
3291 E
3292 j=(parsedline[i]-0x2F);
3293 j*=16;
3294 IF(IL((U I)parsedline[i+1]))
3295 j+=(TL(parsedline[i+1])-0x56);
3296 E
3297 j+=(parsedline[i+1]-0x2F);
3298 j-=17;
3299 IF(j>=0&&j<256)
3300 guic[isguic]=(j*257);
3301 isguic++;
3302 }
3303 }
3304 }
3305 nsprint("guicolor: %.2x%.2x%.2x\n",(guic[0]/257),(guic[1]/257),(guic[2]/257)
3306 );
3307 }
3308 EI(!SNCC(iread,"guilabel",8)){
3309 IF(!parameter(iread,1,0x20)){
3310 IF(isguil){
3311 F(k=0;k<isguil;k++)
3312 FR(gblabel[k]);
3313 isguil=0;
3314 }
3315 parsecmdline(parm);
3316 W(!parameter(parsedline,isguil,0x3A)&&isguil<3){
3317 IF(!(gblabel[isguil++]=(C *)SDU(SL(parm)?parm:"nolabel")))
3318 pe("iface(): duplication of memory error",1);
3319 }
3320 }
3321 nsprint("guititle: %s%s\n",(isguil?gblabel[0]:IFACE_UNSET),(isguil>1?
3322 " <...>":""));
3323 }
3324 EI(!SNCC(iread,"guipdlen",8)){
3325 IF(!parameter(iread,1,0x20)){
3326 IF(AI(parm)<0)
3327 nsprint("guipdlen: argument1 must be a positive integer, can not define."
3328 "\n");
3329 E
3330 guio=(AI(parm)>GUI_MAXLEN?GUI_MAXLEN:AI(parm));
3331 }
3332 nsprint("guipdlen: %d\n",guio);
3333 }
3334 EI(!SNCC(iread,"guipd",5)){
3335 isguis=(isguis?0:1);
3336 nsprint("guipd: %sabled\n",(isguis?"en":"dis"));
3337 }
3338 EI(!SNCC(iread,"guititle",8)){
3339 IF(!parameter(iread,1,0x20)){
3340 IF(isguititle)
3341 FR(guititle);
3342 parsecmdline(parm);
3343 IF(!(guititle=(C *)SDU(parsedline)))
3344 pe("iface(): duplication of memory error",1);
3345 isguititle=1;
3346 }
3347 nsprint("guititle: %s\n",(isguititle?guititle:IFACE_UNSET));
3348 }
3349 EI(!SNCC(iread,"gui",3)){
3350 IF(isprivileged)
3351 nsprint("gui: the gui frontend can not be used when netscript is privilege"
3352 "d.\n");
3353 E{
3354 IF(isgui){
3355 IF(isbgui)
3356 isbgui=isgui=0;
3357 E
3358 isbgui=1;
3359 }
3360 E
3361 isgui=1;
3362 nsprint("gui: %s\n",(!isgui?"disabled":(isbgui==1?"generic":"normal")));
3363 }
3364 }
3365 #endif
3366 EI(!SNCC(iread,"host",4)){
3367 IF(bindmode)
3368 nsprint("host: bind mode is already defined, can not define.\n");
3369 E{
3370 IF(!parameter(iread,1,0x20)){
3371 IF(sethost){
3372 F(k=0;k<tshs;k++)
3373 FR(shost[k]);
3374 tshs=0;
3375 }
3376 parsecmdline(parm);
3377 W(!parameter(parsedline,tshs,0x2C)){
3378 IF(!(shost[tshs++]=(C *)SDU(SL(parm)?parm:"0")))
3379 pe("iface(): duplication of memory error",1);
3380 IF(tshs>=MAX_ARGS)
3381 pe("too many slots to store in memory",1);
3382 }
3383 sethost=1;
3384 }
3385 nsprint("host: %s%s\n",(sethost?shost[0]:IFACE_UNSET),(tshs>1?" <...>":
3386 ""));
3387 }
3388 }
3389 EI(!SNCC(iread,"initial",7)){
3390 IF(!parameter(iread,1,0x20)){
3391 IF(initsend)
3392 FR(iswrite);
3393 parsecmdline(parm);
3394 IF(!(iswrite=(C *)SDU(parsedline)))
3395 pe("iface(): duplication of memory error",1);
3396 initsend=1;
3397 }
3398 nsprint("initial: %s\n",(initsend?iswrite:IFACE_UNSET));
3399 }
3400 EI(!SNCC(iread,"logfile",7)){
3401 IF(isprivileged)
3402 nsprint("logfile: can not log data to a file with privileged access.\n");
3403 E{
3404 IF(!parameter(iread,1,0x20)){
3405 IF(islog)
3406 FR(logfile);
3407 parsecmdline(parm);
3408 IF(!(logfile=(C *)SDU(parsedline)))
3409 pe("iface(): duplication of memory error",1);
3410 islog=1;
3411 }
3412 nsprint("logfile: %s\n",(islog?logfile:IFACE_UNSET));
3413 }
3414 }
3415 #ifdef NCURSES
3416 EI(!SNCC(iread,"ncurseslabel",12)){
3417 IF(!parameter(iread,1,0x20)){
3418 IF(isncursesl){
3419 F(k=0;k<isncursesl;k++)
3420 FR(nclabel[k]);
3421 isncursesl=0;
3422 }
3423 parsecmdline(parm);
3424 W(!parameter(parsedline,isncursesl,0x3A)&&isncursesl<2){
3425 IF(!(nclabel[isncursesl++]=(C *)SDU(SL(parm)?parm:"nolabel")))
3426 pe("iface(): duplication of memory error",1);
3427 }
3428 }
3429 nsprint("ncurseslabel: %s%s\n",(isncursesl?nclabel[0]:IFACE_UNSET),
3430 (isncursesl>1?" <...>":""));
3431 }
3432 EI(!SNCC(iread,"ncurses",7)){
3433 isncursesa=(isncursesa?0:1);
3434 nsprint("ncurses: %sabled\n",(isncursesa?"en":"dis"));
3435 }
3436 #endif
3437 EI(!SNCC(iread,"nonprintables",13)){
3438 printonly=(printonly?0:1);
3439 nsprint("nonprintables: %sabled\n",(printonly?"en":"dis"));
3440 }
3441 EI(!SNCC(iread,"notelnetshowopt",15)){
3442 notnetopt=(notnetopt?0:1);
3443 nsprint("notelnetshowopt: %sabled\n",(notnetopt?"en":"dis"));
3444 }
3445 EI(!SNCC(iread,"nowordwrap",10)){
3446 nowrap=(nowrap?0:1);
3447 nsprint("nowordwrap: %sabled\n",(nowrap?"en":"dis"));
3448 }
3449 EI(!SNCC(iread,"omit",4)){
3450 IF(!parameter(iread,1,0x20)){
3451 IF(omitchars)
3452 FR(ochars);
3453 parsecmdline(parm);
3454 IF(!(ochars=(C *)SDU(parsedline)))
3455 pe("iface(): duplication of memory error",1);
3456 omitchars=1;
3457 }
3458 nsprint("omit: %s\n",(omitchars?ochars:IFACE_UNSET));
3459 }
3460 EI(!SNCC(iread,"perm",4)){
3461 IF(!parameter(iread,1,0x20)){
3462 IF(!setperms){
3463 parsecmdline(parm);
3464 setpermissions(parsedline,0);
3465 setperms=1;
3466 }
3467 E
3468 nsprint("perm: permissions are already defined, can not re-define.\n");
3469 }
3470 nsprint("perm: %u.%u <%s>\n",nuid,ngid,(setperms?"set":"unset"));
3471 }
3472 EI(!SNCC(iread,"pnotify",7)){
3473 noshowp=(noshowp?0:1);
3474 nsprint("pnotify: %sabled\n",(noshowp?"en":"dis"));
3475 }
3476 EI(!SNCC(iread,"port",4)){
3477 IF(!parameter(iread,1,0x20))
3478 sport=portentry(parm);
3479 nsprint("port: %d\n",sport);
3480 }
3481 EI(!SNCC(iread,"routehost",9)){
3482 IF(!parameter(iread,1,0x20)){
3483 IF(setroute)
3484 FR(rhost);
3485 parsecmdline(parm);
3486 IF(!(rhost=(C *)SDU(parsedline)))
3487 pe("iface(): duplication of memory error",1);
3488 setroute=1;
3489 }
3490 nsprint("routehost: %s\n",(setroute?rhost:IFACE_UNSET));
3491 }
3492 EI(!SNCC(iread,"routenoincoming",15)){
3493 norrecv=(norrecv?0:1);
3494 nsprint("routenoincoming: %sabled\n",(norrecv?"en":"dis"));
3495 }
3496 EI(!SNCC(iread,"routenooutgoing",15)){
3497 norsend=(norsend?0:1);
3498 nsprint("routenooutgoing: %sabled\n",(norsend?"en":"dis"));
3499 }
3500 EI(!SNCC(iread,"routeport",9)){
3501 IF(!parameter(iread,1,0x20)){
3502 IF(AI(parm)<0)
3503 nsprint("routeport: argument1 must be a positive integer, can not define."
3504 "\n");
3505 E
3506 rport=AI(parm);
3507 }
3508 nsprint("routeport: %d\n",rport);
3509 }
3510 EI(!SNCC(iread,"routeudp",8)){
3511 isudpr=(isudpr?0:1);
3512 nsprint("routeudp: %sabled\n",(isudpr?"en":"dis"));
3513 }
3514 EI(!SNCC(iread,"rulesetedit",11)){
3515 editrules=(editrules?0:1);
3516 nsprint("rulesetedit: %sabled\n",(editrules?"en":"dis"));
3517 }
3518 EI(!SNCC(iread,"rulesetinput",12)){
3519 IF(setfile)
3520 nsprint("rulesetinput: there is a ruleset file defined to use, can not def"
3521 "ine.\n");
3522 E{
3523 inputrules=(inputrules?0:1);
3524 nsprint("rulesetinput: %sabled\n",(inputrules?"en":"dis"));
3525 }
3526 }
3527 EI(!SNCC(iread,"ruleset",7)){
3528 IF(inputrules)
3529 nsprint("ruleset: ruleset input is already defined, can not define.\n");
3530 E{
3531 IF(!parameter(iread,1,0x20)){
3532 IF(setfile)
3533 FR(rulesfile);
3534 parsecmdline(parm);
3535 IF(!(rulesfile=(C *)SDU(parsedline)))
3536 pe("iface(): duplication of memory error",1);
3537 setfile=1;
3538 }
3539 nsprint("ruleset: %s\n",(setfile?rulesfile:IFACE_UNSET));
3540 }
3541 }
3542 EI(!SNCC(iread,"sdelay",5)){
3543 IF(!parameter(iread,1,0x20)){
3544 IF(AI(parm)<0)
3545 nsprint("sdelay: argument1 must be a positive integer, can not define."
3546 "\n");
3547 E
3548 sdelay=AI(parm);
3549 }
3550 nsprint("sdelay: %d\n",sdelay);
3551 }
3552 EI(!SNCC(iread,"showlines",10)){
3553 lnum=(lnum?0:1);
3554 IF(lnum)
3555 lnum=lnum_i=lnum_o=nowrap=1;
3556 nsprint("showlines: %sabled\n",(lnum?"en":"dis"));
3557 }
3558 EI(!SNCC(iread,"showversion",11)){
3559 showv=(showv?0:2);
3560 nsprint("showversion: %sabled\n",(showv?"en":"dis"));
3561 }
3562 EI(!SNCC(iread,"socketopts",10)){
3563 IF(!parameter(iread,1,0x20)){
3564 IF(soptions)
3565 FR(sopts);
3566 parsecmdline(parm);
3567 IF(!(sopts=(C *)SDU(parsedline)))
3568 pe("iface(): duplication of memory error",1);
3569 soptions=1;
3570 }
3571 nsprint("socketopts: %s\n",(soptions?sopts:IFACE_UNSET));
3572 }
3573 #ifndef DISABLE_SYSLOG
3574 EI(!SNCC(iread,"syslog",6)){
3575 slog=(slog?0:1);
3576 nsprint("syslog: %sabled\n",(slog?"en":"dis"));
3577 }
3578 #endif
3579 EI(!SNCC(iread,"telnettype",10)){
3580 IF(tnetraw++>1)
3581 tnetraw=0;
3582 nsprint("telnettype: %s\n",(!tnetraw?"disabled":(tnetraw==1?"stderr":
3583 "stdout")));
3584 }
3585 EI(!SNCC(iread,"telnet",6)){
3586 tnet=(tnet?0:1);
3587 nsprint("telnet: %sabled\n",(tnet?"en":"dis"));
3588 }
3589 EI(!SNCC(iread,"timedexit",9)){
3590 IF(!parameter(iread,1,0x20)){
3591 IF(AI(parm)<0)
3592 nsprint("timedexit: argument1 must be a positive integer, can not define."
3593 "\n");
3594 E
3595 alrm=AI(parm);
3596 }
3597 nsprint("timedexit: %d\n",alrm);
3598 }
3599 EI(!SNCC(iread,"udpmode",7)){
3600 isudp=(isudp?0:1);
3601 nsprint("udpmode: %sabled\n",(isudp?"en":"dis"));
3602 }
3603 EI(!SNCC(iread,"udelay",5)){
3604 IF(!parameter(iread,1,0x20)){
3605 IF(AI(parm)<0)
3606 nsprint("udelay: argument1 must be a positive integer, can not define."
3607 "\n");
3608 E
3609 sudelay=AI(parm);
3610 }
3611 nsprint("udelay: %d\n",sudelay);
3612 }
3613 EI(!SNCC(iread,"var",3)){
3614 IF(!parameter(iread,1,0x20)){
3615 IF(ID((U I)parm[0])){
3616 j=(parm[0]-0x30);
3617 IF(dynamicvarset[j]!=2)
3618 FR(dynamicvar[j]);
3619 IF(!parameter(iread,2,0x20)){
3620 parsecmdline(parm);
3621 IF(!(dynamicvar[j]=(C *)SDU(parsedline)))
3622 pe("iface(): duplication of memory error",1);
3623 dynamicvarset[j]=2;
3624 }
3625 nsprint("var(%d): %s\n",j,(dynamicvarset[j]==2?dynamicvar[j]:
3626 IFACE_UNSET));
3627 }
3628 E
3629 nsprint("var(*): parameter1 is not a value between 0 and 9.\n");
3630 }
3631 E
3632 nsprint("var(syntax): var <0-9> <data>\n");
3633 }
3634 EI(!SNCC(iread,"vhost",5)){
3635 IF(!parameter(iread,1,0x20)){
3636 IF(isvhost)
3637 FR(vhost);
3638 parsecmdline(parm);
3639 IF(!(vhost=(C *)SDU(parsedline)))
3640 pe("iface(): duplication of memory error",1);
3641 isvhost=1;
3642 }
3643 nsprint("vhost: %s\n",(isvhost?vhost:IFACE_UNSET));
3644 }
3645 EI(!SNCC(iread,"exit",4)||!SNCC(iread,"quit",4))
3646 nsexit(0,0);
3647 EI(!SNCC(iread,"run",3)||!SNCC(iread,"launch",6))
3648 r=1;
3649 EI(!SNCC(iread,"&cwd",4)){
3650 IF(!parameter(iread,1,0x20)){
3651 parsecmdline(parm);
3652 CD(parm);
3653 }
3654 B(icwd,(BASE_BUFFER*4+1));
3655 GWD(icwd,(BASE_BUFFER*4+1));
3656 nsprint("&cwd: %s\n",icwd);
3657 }
3658 EI(!SNCC(iread,"&id",3)){
3659 IF(!(tmpname=(C **)M(5*(SO(C *)))))
3660 pe("iface(): allocation of memory error",1);
3661 B((V *)tmpname,SO(tmpname));
3662 IF((pent=GPU(GU()))&&SL(pent->pw_name)){
3663 IF(!(tmpname[0]=(C *)SDU(pent->pw_name)))
3664 pe("iface(): duplication of memory error",1);
3665 }
3666 E{
3667 IF(!(tmpname[0]=(C *)SDU("unknown")))
3668 pe("iface(): duplication of memory error",1);
3669 }
3670 IF((pent=GPU(GEU()))&&SL(pent->pw_name)){
3671 IF(!(tmpname[1]=(C *)SDU(pent->pw_name)))
3672 pe("iface(): duplication of memory error",1);
3673 }
3674 E{
3675 IF(!(tmpname[1]=(C *)SDU("unknown")))
3676 pe("iface(): duplication of memory error",1);
3677 }
3678 IF((gent=GGG(GG()))&&SL(gent->gr_name)){
3679 IF(!(tmpname[2]=(C *)SDU(gent->gr_name)))
3680 pe("iface(): duplication of memory error",1);
3681 }
3682 E{
3683 IF(!(tmpname[2]=(C *)SDU("unknown")))
3684 pe("iface(): duplication of memory error",1);
3685 }
3686 IF((gent=GGG(GEG()))&&SL(gent->gr_name)){
3687 IF(!(tmpname[3]=(C *)SDU(gent->gr_name)))
3688 pe("iface(): duplication of memory error",1);
3689 }
3690 E{
3691 IF(!(tmpname[3]=(C *)SDU("unknown")))
3692 pe("iface(): duplication of memory error",1);
3693 }
3694 nsprint("&id: uid=%u(%s) euid=%u(%s) gid=%u(%s) egid=%u(%s)\n",GU(),
3695 tmpname[0],GEU(),tmpname[1],GG(),tmpname[2],GEG(),tmpname[3]);
3696 FR(tmpname);
3697 }
3698 EI(!SNCC(iread,"&pid",4))
3699 nsprint("&pid: %lu (parent=%lu)\n",cpid,GPPD());
3700 EI(!SNCC(iread,"&time",6)){
3701 TM(&tm);
3702 IF(!(tmptime=(C *)SDU(CT(&tm))))
3703 pe("iface(): duplication of memory error",1);
3704 IF(tmptime[(SL(tmptime)-1)]==0x0A)
3705 tmptime[(SL(tmptime)-1)]=0x0;
3706 nsprint("&time: %s (value=%d)\n",tmptime,tm);
3707 FR(tmptime);
3708 }
3709 EI(SL(iread)&&iread[0]==0x21){
3710 IF(isprivileged)
3711 nsprint("!: can not execute third party programs with privileged access."
3712 "\n");
3713 E{
3714 F(i=1;i<SL(iread);i++)
3715 iread[(i-1)]=iread[i];
3716 iread[(i-1)]=0x0;
3717 SW(fp=FK()){
3718 CS -1:
3719 nsprint("!: fork() failed.\n");
3720 BR;
3721 CS 0:
3722 /* allow aborts to be handled, since its passed over to the program. */
3723 SG(SIGINT,SIG_DFL);
3724 EL(eshell,eshell,(SL(iread)?"-c":0),(SL(iread)?iread:0),0);
3725 _exit(1);
3726 BR;
3727 default:
3728 /* wait up. */
3729 WP(fp,0,0);
3730 BR;
3731 }
3732 }
3733 }
3734 EI(!SNCC(iread,"help",4)){
3735 nsprint("anotify\t\t\t\t- disables display of all netscript comments.\n"
3736 "background\t\t\t- sends netscript to the background.\n"
3737 "bind\t\t\t\t- binds to the supplied port.\n"
3738 "chdir\t\t<directory>\t- changes the working directory of netscript.\n"
3739 "chroot\t\t<directory>\t- changes the root directory of netscript.\n"
3740 "cnotify\t\t\t\t- disables display of connection notifications.\n"
3741 "disparrows\t\t\t- disables display of arrow precursors.\n"
3742 "dispincoming\t\t\t- disables display of incoming data.\n"
3743 "dispoutgoing\t\t\t- disables display of outgoing data.\n"
3744 "disptype\t\t\t- displays hex/dec values.\n"
3745 "execexit\t\t\t- kills netscript after the first dump.\n"
3746 "execfile\t<file>\t\t- dumps the program data to the socket.\n"
3747 "execinteractive\t\t\t- will allow interactive use of programs.\n"
3748 "execpre\t\t<data>\t\t- precurse data to attach for each line dumped.\n"
3749 "execshell\t<file>\t\t- will use an alternate shell for executions.\n"
3750 "execwait\t<second(s)>\t- kills the program if the program dump hangs.\n"
3751 "forever\t\t\t\t- when disconnected. reconnect, or rebind.\n"
3752 #ifdef GTK
3753 "gui\t\t\t\t- enables the gui frontend. (to normal/generic)\n"
3754 "guicolor\t<ffffff>\t- sets a text foreground color for the gui.\n"
3755 "guilabel\t<l1:l2:l3>\t- defines button labels for the gui.\n"
3756 "guipd\t\t\t\t- automatically start pulled down. (non-generic)\n"
3757 "guipdlen\t<size>\t\t- increase the length of the gui. (non-generic)\n"
3758 "guititle\t<title>\t\t- displays as the title for the gui.\n"
3759 #endif
3760 "host\t\t<host,host,...>\t- remote host (or ip) to connect to.\n"
3761 "initial\t\t<data>\t\t- send initial data once connected. (\"?\"=dyn)\n"
3762 "logfile\t\t<file>\t\t- turns input/output logging on.\n"
3763 #ifdef NCURSES
3764 "ncurses\t\t\t\t- switch console to ncurses visualization.\n"
3765 "ncurseslabel\t<l1:l2>\t\t- defines tab labels for the ncurses.\n"
3766 #endif
3767 "nonprintables\t\t\t- disables reading of non-printable characters.\n"
3768 "notelnetshowopt\t\t\t- disables display of verbose telnetd-opts.\n"
3769 "nowordwrap\t\t\t- disables wordwrap for in/out displaying.\n"
3770 "omit\t\t<charlist>\t- will omit socket reading of the charlist.\n"
3771 "perm\t\t<user[.group]>\t- changes netscript id permissions.\n"
3772 "pnotify\t\t\t\t- disables display of unimportant ruleset info.\n"
3773 "port\t\t<port>\t\t- remote port to connect to, or bind to.\n"
3774 "routehost\t<host>\t\t- will set a host, to route socket data to.\n"
3775 "routenoincoming\t\t\t- disable routed sending of incoming data.\n"
3776 "routenooutgoing\t\t\t- disable routed sending of outgoing data.\n"
3777 "routeport\t<port>\t\t- will set a port to connect on the route host.\n"
3778 "routeudp\t\t\t- switches the route host to the UDP protocol.\n"
3779 "ruleset\t\t<file>\t\t- input/output (ruleset) file.\n"
3780 "rulesetedit\t\t\t- edit the temporary/ruleset with an editor.\n"
3781 "rulesetinput\t\t\t- input/output ruleset, via input.\n"
3782 "sdelay\t\t<second(s)>\t- delay before processing incoming data. \n"
3783 "showlines\t\t\t- displays the value of each line.\n"
3784 "showversion\t\t\t- displays the version info of netscript.\n"
3785 "socketopts\t<#,#,#:...>\t- sets socket option(s) inside netscript.\n"
3786 #ifndef DISABLE_SYSLOG
3787 "syslog\t\t\t\t- enables system logging.\n"
3788 #endif
3789 "telnet\t\t\t\t- attempt to interpret the telnet protocol.\n"
3790 "telnettype\t\t\t- dump raw socket data. (to stderr/stdout)\n"
3791 "timedexit\t<second(s)>\t- closes the connection after alloted time.\n"
3792 "udpmode\t\t\t\t- switches netscript to the UDP protocol.\n"
3793 "udelay\t\t<usecond(s)>\t- delay before processing incoming data.\n"
3794 "var\t\t<0-9> <data>\t- will statically define the dynamic variable.\n"
3795 "vhost\t\t<host>\t\t- will define a virtual host to use, or bind to.\n"
3796 "&cwd AND &id AND &pid AND &time\t- local (only) interactive display comman"
3797 "ds.\n"
3798 "![command]\t\t\t- shell out of interactive netscript.\n"
3799 "run AND launch\t\t\t- execute the provided information.\n"
3800 "exit AND quit\t\t\t- exit netscript.\n"
3801 "help\t\t\t\t- this screen, displays interactive commands.\n");
3802 }
3803 EI(SL(iread)&&iread[0]!=0x23)
3804 nsprint("unknown command: %s (try \'help\' for a command list)\n",iread);
3805 }
3806 SG(SIGINT,sighandler);
3807 R;
3808 }
3809 /* display of variable uses, the -d argument. finally went for \t's */
displayv(V)3810 V displayv(V){
3811 nsprint("Defined ruleset match, and replacement variables used by netscript:"
3812 "\n"
3813 "IN/OUT\tTYPE\t\tDOES/ACTION\t\t\t\tVARIABLE\n"
3814 "I/O\treplace\t\twill replace with the in/out used above\t\"%s\"\n"
3815 "O\tpre-data\tstops use of the ruleset\t\t\"%s\"\n"
3816 "O\tpre-data\trestarts use of the ruleset\t\t\"%s\"\n"
3817 "O\tpre-data\tstops the ruleset reading cycle\t\t\"%s\"\n"
3818 "O\tpre-data\tcloses the socket\t\t\t\"%s\"\n"
3819 "O\tpre-data\tasks for input response to send\t\t\"%s\"\n"
3820 "O\tpre-data\ttruncates characters from server data\t\"%s\"\n"
3821 "O\tpre-data\ttruncates tokens from server data (l)\t\"%s\"\n"
3822 "O\tpre-data\ttruncates tokens from server data (r)\t\"%s\"\n"
3823 "O\tpre-data\ttruncates strings from server data\t\"%s\"\n"
3824 "O\tpre-data\tformats the received input data\t\t\"%s\"\n"
3825 "O\tpre-data\tdisplays the supplied data\t\t\"%s\"\n"
3826 "O\tpre-data\twrites the supplied data without a CR\t\"%s\"\n"
3827 "O\tpre-data\tuses rule only one time (requires data)\t\"%s\"\n"
3828 "O\tpre-data\tdisables a rule from the ruleset\t\"%s\"\n"
3829 "O\tpre-data\tdumps the file used after variable\t\"%s\"\n"
3830 "O\tpre-data\twrites to the file used after variable\t\"%s\"\n"
3831 "O\tpre-data\tappends to the file used after variable\t\"%s\"\n"
3832 "O\tpre-data\tchange to the dir used after variable\t\"%s\"\n"
3833 "O\tpre-data\tsends supplied data to the route host\t\"%s\"\n"
3834 "O\tpre-data\tonly sends data if time has passed\t\"%s\"\n"
3835 "O\tpre-data\texecutes the file used after variable\t\"%s\"\n"
3836 "O\tpre-data\texecutes the file to be used in rules\t\"%s\"\n"
3837 "I\tpre-data\tcheck for a reverse/negative match\t\"%s\"\n"
3838 "I\twildcard\tanything after point\t\t\t\"%s\"\n"
3839 "I\twildcard\tanything that is a value\t\t\"%s\"\n"
3840 "I\twildcard\tanything that is alphabetical\t\t\"%s\"\n"
3841 "I\twildcard\tanything that is numerical\t\t\"%s\"\n"
3842 "I\twildcard\tanything that is alphabetical|numerical\t\"%s\"\n"
3843 "I\twildcard\tanything that is upper case\t\t\"%s\"\n"
3844 "I\twildcard\tanything that is lower case\t\t\"%s\"\n"
3845 "I\twildcard\tanything that is punctuated\t\t\"%s\"\n"
3846 "I\twildcard\tanything that is a control word\t\t\"%s\"\n"
3847 "I\twildcard\tanything that is a printable word\t\"%s\"\n"
3848 "I\twildcard\t<\"%c####\" anything that is equal to length, #=num>\n"
3849 "O\tend-data\t<\"%c#####\" delay in secs before processing rule, #=num>\n"
3850 "O\treplace\t\t<\"%c#\" will replace with the argument from input, #=num>\n"
3851 "I/O\treplace\t\t<\"%c{#}\" will replace with stored dynamic data, #=num>\n"
3852 "I/O\treplace\t\t<\"%c##\" will replace with hex->chr value, ##=01-FF>\n"
3853 "I/O\treplace\t\t<\"%c###\" will replace with dec->chr value, ###=001-255>\n"
3854 "I/O\treplace\t\t<\"%c&\" will replace with a random letter>\n"
3855 "I/O\treplace\t\t<\"%c#\" will replace with a random number, #=#>\n"
3856 "\nDefined environmental variables used by netscript:\n"
3857 "DOES/ACTION\t\t\t\t\t\t\tVARIABLE\n"
3858 "treated as a command line\t\t\t\t\t\"$%s\"\n"
3859 "treated as a connection timeout time\t\t\t\t\"$%s\"\n"
3860 #ifndef DISABLE_MODULES
3861 "treated as a file to use for module support\t\t\t\"$%s\"\n"
3862 #endif
3863 "treated as a virtual host to use\t\t\t\t\"$%s\"\n"
3864 "treated as a backlog used for binding\t\t\t\t\"$%s\"\n"
3865 "treated as a maximum limit of text per line\t\t\t\"$%s\"\n"
3866 "treated as a shell to execute third party programs\t\t\"$%s\"\n"
3867 "treated as a text editor to make/edit (temporary) rulesets\t\"$%s\"\n\n"
3868 "Note: variables surrounded by <>'s are static, and unchangeable variables.\n"
3869 " consult documentation for more definitions on variables.\n",NS_REPEAT,
3870 NS_STOP,NS_START,NS_HALT,NS_QUIT,NS_ASK,NS_TRUNC,NS_TOKENL,NS_TOKENR,NS_STR,
3871 NS_FMT,NS_ECHO,NS_RAW,NS_ONCE,NS_DISABLE,NS_DUMP,NS_WRITE,NS_APPEND,NS_CHDIR,
3872 NS_ROUTE,NS_TIMED,NS_EXEC,NS_EXECF,NS_NMATCH,NS_ALL,NS_ANY,NS_ALPHA,NS_DIGIT,
3873 NS_ALNUM,NS_UPPER,NS_LOWER,NS_PUNCT,NS_CNTRL,NS_PRINT,PARAMETER_VAR_CHAR,
3874 PARAMETER_VAR_CHAR,PARAMETER_VAR_CHAR,PARAMETER_VAR_CHAR,PARAMETER_VAR_CHAR,
3875 PARAMETER_VAR_CHAR,PARAMETER_VAR_CHAR,PARAMETER_VAR_CHAR,ENV_CMDLINE,
3876 ENV_TIMEOUT,
3877 #ifndef DISABLE_MODULES
3878 ENV_MODULE,
3879 #endif
3880 ENV_VHOST,ENV_BACKLOG,ENV_COLUMNS,ENV_SHELL,
3881 ENV_EDITOR);
3882 nsexit(0,0);
3883 }
3884 /* stated in displayv(). also, finally went for the \t's here too. */
usage(U SH extended)3885 V usage(U SH extended){
3886 nsprint("Usage: %s [extended options...] -s|-r file -b|-h host -p port\n"
3887 "Usage: %s file (must be a +rx internal argument supplied ruleset file)\n"
3888 "Usage: %s --list [path:path:...] (must be used by command line only)\n"
3889 "Usage: %s --hist [#]|[clear] (must be used by command line only)\n"
3890 "Usage: %s [--interactive] (will enter interactive prompted mode)\n",
3891 progname,progname,progname,progname,progname);
3892 IF(extended)
3893 nsprint("\n -r <file>\t\tinput/output (ruleset) file. (required, or -s)\n"
3894 " -h <host>\t\tremote host (or ip) to connect to. (required, or -b)\n"
3895 " -p <port>\t\tremote port to connect to, or bind to. (required)\n"
3896 " -# <data>\t\twill statically define the dynamic variable. (#=0-9)\n"
3897 " -i <data>\t\tsend initial data once connected. (\"?\" for dynamic)\n"
3898 " -m <path>\t\twill change the working directory of netscript.\n"
3899 " -M <path>\t\twill change the root directory of netscript. (superuser)\n"
3900 " -R <host>\t\twill set a host, to route socket data to.\n"
3901 " -k <port>\t\twill set a port to connect to on the route host. (-R)\n"
3902 " -u <data>\t\tchanges netscript id permissions. (\"user[.group]\" style)\n"
3903 " -q <host>\t\twill define a virtual host to use, or bind to.\n"
3904 " -o <data>\t\twill omit socket reading of the supplied character(s).\n"
3905 " -S <time>\t\tdelay before processing incoming data. (seconds)\n"
3906 " -U <time>\t\tdelay before processing incoming data. (useconds)\n"
3907 " -t <time>\t\tclose the connection after alloted time.\n"
3908 " -Q <data>\t\tsets local socket option(s). (\"#,#,#:#,#,#:...\" style)\n"
3909 " -l <file>\t\tturns input/output logging on, writes to the file.\n"
3910 #ifdef GTK
3911 " -G <name>\t\tdisplays the name as the title for the gui. (-g)\n"
3912 " -+ <size>\t\tchanges the length of the pulldown. (non-generic) (-g)\n"
3913 " -# <data>\t\tsets foreground color for the gui. (\"ffffff\" style) (-g)\n"
3914 " -K <data>\t\tsets button labels for the gui. (\"l1:l2:l3\" style) (-g)\n"
3915 #endif
3916 #ifdef NCURSES
3917 " -= <data>\t\tsets tab labels for ncurses. (\"l1:l2\" style) (-_)\n"
3918 #endif
3919 " -e <prog>\t\tdumps the program data to the socket.\n"
3920 " -E <data>\t\tprecurse data to attach for each line dumped. (-e)\n"
3921 " -O <prog>\t\twill use an alternate shell for executions. (-e)\n"
3922 " -x <time>\t\tkills the program if the program dump hangs. (-e)\n"
3923 " -X\t\t\tkills netscript after the program has been dumped. (-e)\n"
3924 " -a\t\t\twill allow interactive use of programs. (-e)\n"
3925 " -f\t\t\twill run a third party edtior to define the ruleset.\n"
3926 " -@\t\t\twill switch netscript to the UDP protocol.\n"
3927 " -^\t\t\twill switch the route host to the UDP protocol.\n"
3928 " -B\t\t\tsends netscript to the background.\n"
3929 " -n\t\t\tdisables display of outgoing data.\n"
3930 " -N\t\t\tdisables display of incoming data.\n"
3931 " -j\t\t\tdisable routed sending of outgoing data. (-R)\n"
3932 " -J\t\t\tdisable routed sending of incoming data. (-R)\n"
3933 " -F\t\t\tdisables display of arrow precursors.\n"
3934 " -I\t\t\twhen disconnected. reconnect, or rebind.\n"
3935 " -s\t\t\ttakes the ruleset from standard input instead of a file.\n"
3936 " -b\t\t\tbinds to the supplied port, instead of connecting out.\n"
3937 #ifdef GTK
3938 " -g\t\t\tuses the gui frontend. (use twice for generic version)\n"
3939 " -W\t\t\tautomatically starts pulled down. (non-generic) (-g)\n"
3940 #endif
3941 #ifdef NCURSES
3942 " -_\t\t\tswitch console display to ncurses visualization.\n"
3943 #endif
3944 #ifndef DISABLE_SYSLOG
3945 " -Z\t\t\tuses system logging. (if syslog is accessible)\n"
3946 #endif
3947 " -T\t\t\tattempts to interpret the telnet protocol.\n"
3948 " -y\t\t\twill dump raw socket data to standard error. (-T)\n"
3949 " -Y\t\t\twill dump raw socket data to standard output. (-T)\n"
3950 " -z\t\t\tdisables display of verbose telnetd-opt input/output.\n"
3951 " -L\t\t\tdisplays the value of each line as a precursor.\n"
3952 " -H\t\t\tdisplays hex values, instead of character values. (ff)\n"
3953 " -D\t\t\tdisplays dec values, instead of character values. (255)\n"
3954 " -w\t\t\tdisables wordwrap for in/out displaying.\n"
3955 " -P\t\t\tdisables reading of non-printable characters.\n"
3956 " -c\t\t\tdisables display of connection notifications.\n"
3957 " -C\t\t\tdisables display of ruleset info that is not required.\n"
3958 " -A\t\t\tdisables display of all prompted netscript comments.\n"
3959 " -d\t\t\tdisplays the variables used by the ruleset, and environ.\n"
3960 " -v\t\t\tdisplays the version info of netscript, and exits.\n"
3961 " -V\t\t\tdisplays the version info of netscript, and continues.\n"
3962 "\nAuthor: %s. [ihadnihn]\n",author);
3963 nsexit(0,0);
3964 }
3965 /* any global exit routines can be placed here, your choice. */
nsexit(SH i,U SH type)3966 V nsexit(SH i,U SH type){
3967 /* clear the screen for ncurses. */
3968 #ifdef NCURSES
3969 IF(isncurses)
3970 endwin();
3971 #endif
3972 /* just idle out until really closed. */
3973 #ifdef GTK
3974 IF(isgui&&isgui!=3&&isagui){
3975 pe("all processing finished, awaiting exit request",0);
3976 isgui=2;
3977 W(isgui!=3)
3978 USLP(250000);
3979 }
3980 #endif
3981 #ifndef DISABLE_SYSLOG
3982 /* only if something happened, note this one. */
3983 IF(!(!slnum_s&&!slnum_t))
3984 wrso("%d-%d id: %lu-%u.%u.%u.%u exit: %s (%s)",slnum_t,slnum_s,cpid,GU(),
3985 GEU(),GG(),GEG(),(i?"abnormal":"normal"),(cpid==GPD()?"main":"branch"));
3986 #endif
3987 /* check, and use the ns_exit() symbol, it passes the exit value, and exit */
3988 /* type(main/branch). (short, unsigned short) */
3989 #ifndef DISABLE_MODULES
3990 IF(vmodule){
3991 (*exit_function)(i,type);
3992 /* added clean-up for the module file here, since it is going to exit. */
3993 dlclose(dyn);
3994 }
3995 #endif
3996 /* clean up a possible build up with raw telnet on exit. */
3997 IF(tnetraw&&truetnet){
3998 nsprint("\n");
3999 /* same goes for logging. */
4000 IF(islog)
4001 logdata("\n",3);
4002 }
4003 closesocket(0);
4004 closesocket(1);
4005 IF(type)
4006 _exit(i);
4007 E
4008 exit(i);
4009 }
4010 /* the following function is only for the ncurses mode. */
4011 #ifdef NCURSES
ncursesinit(V)4012 V ncursesinit(V) {
4013 U I i=0;
4014 initscr();
4015 cbreak();
4016 nonl();
4017 keypad(stdscr,TRUE);
4018 /* reset columns to ncurses information. */
4019 columns=(COLS-1);
4020 /* no need for anything larger, unless you are trying to bother memory. */
4021 IF(1024<columns){
4022 pe("COLS is too large",0);
4023 columns=DFL_COLUMNS;
4024 }
4025 /* the prompt itself must be counted in the most minimal of cases. */
4026 IF((1>columns&&nofrom)||(4>columns&&!nofrom)){
4027 pe("COLS is too small",0);
4028 columns=DFL_COLUMNS;
4029 }
4030 /* setup tab labels. */
4031 F(i=0;i<COLS;i++)
4032 NWV(stdscr,((LINES-3-1)/2),i,'-');
4033 F(i=0;i<COLS;i++)
4034 NWV(stdscr,(LINES-3),i,'-');
4035 NMW(((LINES-3-1)/2),0,"[-<");
4036 NMW(((LINES-3-1)/2),3,(isncursesl?nclabel[0]:"Output stream"));
4037 NMW(((LINES-3-1)/2),(isncursesl?(SL(nclabel[0])+3):16),">");
4038 NMW(((LINES-3-1)/2),(COLS-1),"]");
4039 NMW((LINES-3),0,"[-<");
4040 NMW((LINES-3),3,(isncursesl>1?nclabel[1]:"Input stream"));
4041 NMW((LINES-3),(isncursesl>1?(SL(nclabel[1])+3):15),">");
4042 NMW((LINES-3),(COLS-1),"]");
4043 move((LINES-3+1),0);
4044 NR();
4045 /* make (ncurses) windows. */
4046 nw1=NSW(stdscr,((LINES-3-1)/2),COLS,0,0);
4047 NSO(nw1,1);
4048 nw2=NSW(stdscr,((LINES-3-1)/2),COLS,((LINES-3-1)/2)+1,0);
4049 NSO(nw2,1);
4050 nw3=NSW(stdscr,(3-1),COLS,((LINES-3)+1),0);
4051 NSO(nw3,1);
4052 touchwin(stdscr);
4053 NR();
4054 /* straighten up. */
4055 NE(nw1);
4056 NRE(nw1);
4057 NE(nw2);
4058 NRE(nw2);
4059 NE(nw3);
4060 NRE(nw3);
4061 /* nsprint() defaultly goes to the main (ncurses) window. */
4062 nfocus=nw3;
4063 /* ready to go. */
4064 isncurses=1;
4065 R;
4066 }
4067 #endif
4068 /* the following functions are only for the gui mode. */
4069 #ifdef GTK
4070 /* function triggered when return is pressed for an entry. (gui mode) */
gtkec(GW * gw,GW * ge)4071 V gtkec(GW *gw,GW *ge){
4072 GC *et;
4073 et=gtk_entry_get_text(GTK_ENTRY(ge));
4074 IF(SL(et)&&isgui==1){
4075 IF(isguiwait){
4076 /* write the response to the socket. */
4077 wro(et,SL(et),0);
4078 wro("\n",1,0);
4079 /* log if requested. */
4080 IF(islog)
4081 logdata(et,0);
4082 /* reset waiting loop. */
4083 isguiwait=0;
4084 gtk_entry_set_text(GTK_ENTRY(ge),"");
4085 /* only for non-generic gui. */
4086 IF(!isbgui){
4087 /* away you go. */
4088 GWH(gen);
4089 /* window refresh. */
4090 GWSU(giw,guiw,guih);
4091 /* refocus on the last button made, which is the exit button. */
4092 GWGF(gbu);
4093 }
4094 }
4095 }
4096 R;
4097 }
4098 /* function to clear the screen. (gui mode) */
gtkcl(GW * gw,GPT gd)4099 V gtkcl(GW *gw,GPT gd){
4100 IF(gtk_text_get_length(GTK_TEXT(gte)))
4101 gtk_text_backward_delete(GTK_TEXT(gte),gtk_text_get_length(GTK_TEXT(gte)));
4102 R;
4103 }
4104 /* function to pull down the gui, using 300 as a general/default value. */
4105 /* (non-generic gui mode) */
gtkpd(GW * gw,GPT gd)4106 V gtkpd(GW *gw,GPT gd){
4107 IF(GTK_TOGGLE_BUTTON(gpd)->active==TRUE)
4108 guih+=(guio?guio:300);
4109 E
4110 guih-=(guio?guio:300);
4111 /* set the new position. */
4112 GWSU(giw,guiw,guih);
4113 R;
4114 }
4115 /* function that is triggered to close the program. (gui mode) */
gtkca(GW * gw,GPT gd)4116 V gtkca(GW *gw,GPT gd){
4117 gtk_main_quit();
4118 /* finalize the close. */
4119 isgui=3;
4120 /* just incase netscript is waiting anywheres else. */
4121 nsexit(0,0);
4122 }
4123 /* create, and launch the display. (gui mode) */
gtkrun(C * dispname)4124 V gtkrun(C *dispname){
4125 C *disptitle;
4126 /* check for normal, non-generic font. */
4127 IF(!isbgui&&!(GFL(GUI_FONT)))
4128 pe("error loading font, use the -g option twice for generic mode",1);
4129 /* set up the soon-to-be titlebar. */
4130 IF(!(disptitle=(C *)M((isguititle?SL(guititle):SL(dispname))+SL(VERSION)+33+1)
4131 ))
4132 pe("gtkrun(): allocation of memory error",1);
4133 B(disptitle,((isguititle?SL(guititle):SL(dispname))+SL(VERSION)+33+1));
4134 SP(disptitle,"Netscript/v%s(%.3s)-Xvisualization: %s",VERSION,COMPTYPE,
4135 (isguititle?guititle:dispname));
4136 /* setup the window. */
4137 giw=gtk_window_new(GTK_WINDOW_TOPLEVEL);
4138 GWSU(giw,(isbgui?520:(guiw=440)),(isbgui?200:(guih=150)));
4139 /* defined to not be allowed to make too small, does not look so hot. */
4140 gtk_window_set_policy(GTK_WINDOW(giw),FALSE,(isbgui?TRUE:FALSE),FALSE);
4141 GSC(GTK_OBJECT(giw),"destroy",GTK_SIGNAL_FUNC(gtkca),0);
4142 gtk_window_set_title(GTK_WINDOW(giw),disptitle);
4143 /* done with title buffer. */
4144 FR(disptitle);
4145 GCSBW(GTK_CONTAINER(giw),0);
4146 gb1=GVN(FALSE,0);
4147 gtk_container_add(GTK_CONTAINER(giw),gb1);
4148 GWS(gb1);
4149 gb2=GVN(FALSE,0);
4150 GCSBW(GTK_CONTAINER(gb2),5);
4151 GBPS(GTK_BOX(gb1),gb2,TRUE,TRUE,0);
4152 GWS(gb2);
4153 gta=gtk_table_new(2,2,FALSE);
4154 GBPS(GTK_BOX(gb2),gta,TRUE,TRUE,0);
4155 GWS(gta);
4156 /* text widget, vertical bar gets added on next. */
4157 gte=gtk_text_new(0,0);
4158 gtk_text_set_editable(GTK_TEXT(gte),FALSE);
4159 gtk_text_set_word_wrap(GTK_TEXT(gte),FALSE);
4160 GTA(GTK_TABLE(gta),gte,0,1,0,1,GTK_EXPAND|GTK_SHRINK|GTK_FILL,GTK_EXPAND|
4161 GTK_SHRINK|GTK_FILL,0,0);
4162 GWS(gte);
4163 /* vertical scrollbar, for the text widget. */
4164 gvs=gtk_vscrollbar_new(GTK_TEXT(gte)->vadj);
4165 GTA(GTK_TABLE(gta),gvs,1,2,0,1,GTK_FILL,GTK_EXPAND|GTK_SHRINK|GTK_FILL,0,0);
4166 GWS(gvs);
4167 gtk_widget_realize(gte);
4168 gtk_text_freeze(GTK_TEXT(gte));
4169 gtk_text_thaw(GTK_TEXT(gte));
4170 gvn=GVN(TRUE,0);
4171 GBPS(GTK_BOX(gb2),gvn,FALSE,FALSE,0);
4172 GWS(gvn);
4173 /* entry box. (do not show until needed, unless generic mode is on) */
4174 gen=gtk_entry_new_with_max_length(BASE_BUFFER);
4175 GSC(GTK_OBJECT(gen),"activate",GTK_SIGNAL_FUNC(gtkec),gen);
4176 GBPS(GTK_BOX(gvn),gen,FALSE,FALSE,0);
4177 IF(isbgui)
4178 GWS(gen);
4179 /* pulldown/up button/box. (only in non-generic gui mode) */
4180 IF(!isbgui){
4181 /* button box. */
4182 gpb=GHN(TRUE,0);
4183 GBPS(GTK_BOX(gvn),gpb,FALSE,FALSE,0);
4184 GWS(gpb);
4185 /* check button. */
4186 gpd=gtk_check_button_new_with_label(isguil>2?gblabel[2]:"Pulldown");
4187 GSC(GTK_OBJECT(gpd),"clicked",GTK_SIGNAL_FUNC(gtkpd),0);
4188 GBPS(GTK_BOX(gpb),gpd,TRUE,TRUE,0);
4189 GTK_WIDGET_SET_FLAGS(gpd,GTK_CAN_DEFAULT);
4190 GWS(gpd);
4191 }
4192 /* button box. */
4193 ghb=GHN(TRUE,0);
4194 GBPS((isbgui?GTK_BOX(gvn):GTK_BOX(gpb)),ghb,FALSE,TRUE,0);
4195 GWS(ghb);
4196 /* clear button. */
4197 gbu=gtk_button_new_with_label(isguil>1?gblabel[1]:"Clear");
4198 GSC(GTK_OBJECT(gbu),"clicked",GTK_SIGNAL_FUNC(gtkcl),0);
4199 GBPS(GTK_BOX(ghb),gbu,TRUE,TRUE,0);
4200 GTK_WIDGET_SET_FLAGS(gbu,GTK_CAN_DEFAULT);
4201 GWS(gbu);
4202 /* exit button. */
4203 gbu=gtk_button_new_with_label(isguil?gblabel[0]:"Exit");
4204 GSC(GTK_OBJECT(gbu),"clicked",GTK_SIGNAL_FUNC(gtkca),0);
4205 GBPS(GTK_BOX(ghb),gbu,TRUE,TRUE,0);
4206 GTK_WIDGET_SET_FLAGS(gbu,GTK_CAN_DEFAULT);
4207 GWS(gbu);
4208 /* focus on the entry/exit button. (depending if generic mode is on) */
4209 GWGF(isbgui?gen:gbu);
4210 /* pulldown on start. (-W option) */
4211 IF(!isbgui&&isguis)
4212 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(gpd),TRUE);
4213 /* show the window. */
4214 GWS(giw);
4215 /* allow output/display use. */
4216 isagui=1;
4217 /* update the gui. */
4218 GTE();
4219 gtk_main();
4220 GTL();
4221 /* netscript is done. */
4222 pthread_exit(0);
4223 R;
4224 }
4225 #endif
4226 /* this function is to check for the reverse wildcard check. if it does */
4227 /* not occur it gets passed normally along to wordmatch(). */
prewordmatch(C * wildcard,C * in)4228 U SH prewordmatch(C *wildcard,C *in){
4229 U SH r=0;
4230 U I i=0;
4231 C *tmpwildcard;
4232 IF(!(tmpwildcard=(C *)SDU(wildcard)))
4233 pe("prewordmatch(): duplication of memory error",1);
4234 /* check for the negative/reverse match rule. */
4235 IF(SL(tmpwildcard)>SL(NS_NMATCH)&&!SNCC(tmpwildcard,NS_NMATCH,SL(NS_NMATCH))){
4236 F(i=SL(NS_NMATCH);i<SL(tmpwildcard);i++)
4237 tmpwildcard[(i-SL(NS_NMATCH))]=tmpwildcard[i];
4238 tmpwildcard[(i-SL(NS_NMATCH))]=0x0;
4239 r=wordmatch(tmpwildcard,in);
4240 /* done with that. */
4241 FR(tmpwildcard);
4242 /* reverse it, the idea of this pre-function. */
4243 R(r?0:1);
4244 }
4245 /* otherwise, just like normal. */
4246 E
4247 R wordmatch(wildcard,in);
4248 }
4249 /* for the real wildcard match checking. */
wordmatch(C * wildcard,C * in)4250 U SH wordmatch(C *wildcard,C *in){
4251 U I i=0;
4252 U I j=0;
4253 U I k=0;
4254 U I r=0;
4255 U I tmp=0;
4256 C *tmpbuf;
4257 /* handles the dynamic variables. (${0-9}) */
4258 parsedynamic(wildcard);
4259 /* remove back-to-back spaces for parsing with the remote data. */
4260 F(j=0;j<SL(in);j++){
4261 IF(!(in[j+1]&&in[j]==0x20&&in[j+1]==0x20))
4262 in[k++]=in[j];
4263 }
4264 in[k]=0x0;
4265 /* remove back-to-back spaces for parsing with the ruleset. */
4266 F(k=j=0;j<SL(parseddynamic);j++)
4267 IF(!(parseddynamic[j+1]&&parseddynamic[j]==0x20&&parseddynamic[j+1]==0x20))
4268 parseddynamic[k++]=parseddynamic[j];
4269 parseddynamic[k]=0x0;
4270 /* quick exact match check. */
4271 IF(!SC(parseddynamic,in))
4272 R(0);
4273 W(!parameter(parseddynamic,i,0x20)){
4274 IF(!(tmpbuf=(C *)SDU(parm)))
4275 pe("wordmatch(): duplication of memory error",1);
4276 /* checks for a wildcard match for anything after that point. before */
4277 /* checking the next parameter. */
4278 IF(SC(tmpbuf,NS_ALL)){
4279 /* gets the input parameter, to check for the rest of the wildcards, or */
4280 /* possible perfect matches. if no more parameters, returns failure. */
4281 /* also increases the word for the next loop run. */
4282 IF(parameter(in,i++,0x20)){
4283 FR(tmpbuf);
4284 R(1);
4285 }
4286 /* checking for all wildcard word matches. (length wildcard is next) */
4287 IF(!SC(tmpbuf,parm)||!SCC(tmpbuf,NS_ANY)||(!SCC(tmpbuf,NS_ALPHA)&&wischeck(
4288 parm,0))||(!SCC(tmpbuf,NS_DIGIT)&&wischeck(parm,1))||(!SCC(tmpbuf,NS_ALNUM)
4289 &&wischeck(parm,2))||(!SCC(tmpbuf,NS_UPPER)&&wischeck(parm,3))||(!SCC(
4290 tmpbuf,NS_LOWER)&&wischeck(parm,4))||(!SCC(tmpbuf,NS_PUNCT)&&wischeck(parm,
4291 5))||(!SCC(tmpbuf,NS_CNTRL)&&wischeck(parm,6))||(!SCC(tmpbuf,NS_PRINT)&&
4292 wischeck(parm,7)))
4293 r=0;
4294 /* the length wildcard, must be four digits long, and then will be */
4295 /* processed accordingly. */
4296 EI(SL(tmpbuf)==5&&tmpbuf[0]==PARAMETER_VAR_CHAR&&ID((U I)tmpbuf[1])&&
4297 ID((U I)tmpbuf[2])&&ID((U I)tmpbuf[3])&&ID((U I)tmpbuf[4])){
4298 tmp=(((tmpbuf[1]-0x30)*1000)+((tmpbuf[2]-0x30)*100)+((tmpbuf[3]-0x30)*10)+
4299 (tmpbuf[4]-0x30));
4300 /* match. */
4301 IF(SL(parm)==tmp)
4302 r=0;
4303 /* did not match. */
4304 E
4305 r=1;
4306 }
4307 E
4308 r=1;
4309 IF(r){
4310 FR(tmpbuf);
4311 R(r);
4312 }
4313 }
4314 E{
4315 FR(tmpbuf);
4316 R(r);
4317 }
4318 FR(tmpbuf);
4319 }
4320 /* leftover data does not count as a match. just using int i again for the */
4321 /* loop. checks to see if uneven arguments. 1 = failed, 0 = success. */
4322 i=0;
4323 W(!parameter(parseddynamic,i,0x20))
4324 i++;
4325 IF(!parameter(in,i,0x20))
4326 /* un-even. */
4327 r=1;
4328 E
4329 /* even. */
4330 r=0;
4331 R(r);
4332 }
4333 /* this is meant to pluck a word out of a sentence, then duplicated it to */
4334 /* the character string "parm". kind of like a strtok() without tokenizing. */
parameter(C * string,I i,U I sep)4335 U SH parameter(C *string,I i,U I sep){
4336 U I j=0;
4337 U I k=0;
4338 U I r=0;
4339 /* no comparison. */
4340 C *buf;
4341 IF(!(buf=(C *)M(SL(string)+1)))
4342 pe("parameter(): allocation of memory error",1);
4343 B(buf,(SL(string)+1));
4344 IF(i<0)
4345 r=1;
4346 E
4347 F(j=0;j<SL(string);j++){
4348 IF(string[j]==sep)
4349 i--;
4350 EI(!i)
4351 buf[k++]=string[j];
4352 IF(string[j]==0x0A||string[j]==0x0)
4353 j=(SL(string)+1);
4354 }
4355 IF(i>0)
4356 r=1;
4357 FR(parm);
4358 IF(!(parm=(C *)SDU(buf)))
4359 pe("parameter(): duplication of memory error",1);
4360 FR(buf);
4361 R(r);
4362 }
4363 /* this function checks word format of their counterpart, instead of a */
4364 /* single character. for some reason i like using strlen() instead of *buf */
4365 /* to check for use, old habit i suppose. */
wischeck(C * word,U I type)4366 U SH wischeck(C *word,U I type){
4367 U I i=0;
4368 IF(!SL(word))
4369 R(0);
4370 F(i=0;i<SL(word);i++)
4371 IF((!IL((U I)word[i])&&type==0)||(!ID((U I)word[i])&&type==1)||(!isalnum(
4372 (U I)word[i])&&type==2)||(!isupper((U I)word[i])&&type==3)||(!islower((U I)
4373 word[i])&&type==4)||(!ispunct((U I)word[i])&&type==5)||(!iscntrl((U I)
4374 word[i])&&type==6)||(!IP((U I)word[i])&&type==7))
4375 R(0);
4376 R(1);
4377 }
4378 /* this function handles the --list command line argument. */
usefilelist(C * path)4379 U SH usefilelist(C *path){
4380 U SH r=0;
4381 U I i=0;
4382 C *tmppath;
4383 C lread[(BASE_BUFFER*4+1)];
4384 FL *lfd;
4385 glob_t gb;
4386 gb.gl_offs=0;
4387 F(i=0;!parameter(path,i,0x3A);i++){
4388 IF(SL(parm)){
4389 IF(!(tmppath=(C *)M(SL(parm)+3)))
4390 pe("usefilelist(): allocation of memory error",1);
4391 B(tmppath,(SL(parm)+3));
4392 SP(tmppath,"%s/*",parm);
4393 GB(tmppath,(i==0?GLOB_DOOFFS:(GLOB_DOOFFS|GLOB_APPEND)),0,&gb);
4394 FR(tmppath);
4395 }
4396 }
4397 F(i=0;(i<gb.gl_pathc&&i<1000);i++)
4398 nsprint("%.3d\t%.64s%s\n",i,gb.gl_pathv[i],(SL(gb.gl_pathv[i])>64?"...":""));
4399 IF(!i){
4400 pe("no files found to list",1);
4401 r=0;
4402 }
4403 E{
4404 nsprint("enter list value to use(0-%d): ",(i-1));
4405 IF(!(lfd=FO(ttyn,"r")))
4406 pe("could not open standard input for read",1);
4407 E{
4408 B(lread,(BASE_BUFFER*4+1));
4409 IF(FS(lread,(SO(lread)-1),lfd))
4410 F(i=0;i<SL(lread);i++)
4411 IF(lread[i]==0x0A)
4412 lread[i]=0x0;
4413 }
4414 FC(lfd);
4415 IF(!SL(lread)||!wischeck(lread,1))
4416 r=0;
4417 E{
4418 IF(gb.gl_pathc<=AI(lread)||0>AI(lread))
4419 r=0;
4420 E{
4421 IF(!(tofile=(C *)SDU(gb.gl_pathv[AI(lread)])))
4422 pe("usefilelist(): duplication of memory error",1);
4423 r=1;
4424 }
4425 }
4426 }
4427 GBF(&gb);
4428 R(r);
4429 }
4430 /* this function is for using the stored history file(~/.nshistory) to */
4431 /* quickly activate netscript. (most) output stderr, for this function. */
usehistory(C * preread,U SH type)4432 U SH usehistory(C *preread,U SH type){
4433 U I i=0;
4434 U I j=0;
4435 U I k=0;
4436 U C hread[(BASE_BUFFER*4+1)];
4437 FL *hfd;
4438 IF(!type){
4439 IF(!(hfd=FO(histfile,"r")))
4440 pe("history file does not appear to exist, or is not readable",1);
4441 E{
4442 B(hread,(BASE_BUFFER*4+1));
4443 W(FS(hread,(SO(hread)-1),hfd)&&j<1000){
4444 F(i=0;i<SL(hread);i++)
4445 IF(hread[i]==0x0A)
4446 hread[i]=0x0;
4447 nsprint("%.3d\t%.64s%s\n",j++,hread,(SL(hread)>64?"...":""));
4448 }
4449 }
4450 FC(hfd);
4451 IF(j==0)
4452 pe("history file does not contain any data",1);
4453 nsprint("enter history value to use(0-%d/clear): ",(j-1));
4454 IF(!(hfd=FO(ttyn,"r")))
4455 pe("could not open standard input for read",1);
4456 E{
4457 B(hread,(BASE_BUFFER*4+1));
4458 IF(FS(hread,(SO(hread)-1),hfd))
4459 F(i=0;i<SL(hread);i++)
4460 IF(hread[i]==0x0A)
4461 hread[i]=0x0;
4462 }
4463 FC(hfd);
4464 IF(!SNC(hread,"clear",5))
4465 nsexit(delhistory(histfile),0);
4466 IF(!SL(hread)||!wischeck(hread,1))
4467 R(0);
4468 k=AI(hread);
4469 }
4470 E{
4471 IF(!SL(preread)||!wischeck(preread,1))
4472 R(0);
4473 k=AI(preread);
4474 }
4475 j=0;
4476 IF(!(hfd=FO(histfile,"r")))
4477 pe("history file does not appear to exist, or is not readable",1);
4478 E{
4479 B(hread,(BASE_BUFFER*4+1));
4480 W(FS(hread,(SO(hread)-1),hfd)){
4481 IF(j==k){
4482 F(i=0;i<SL(hread);i++)
4483 IF(hread[i]==0x0A)
4484 hread[i]=0x0;
4485 IF(!(toenv=(C *)M(SL(hread)+1)))
4486 pe("usehistory(): allocation of memory error",1);
4487 B(toenv,(SL(hread)+1));
4488 /* memory compatibility issue. so, instead, allocate+copy. */
4489 SCP(toenv,hread);
4490 FC(hfd);
4491 R(1);
4492 }
4493 E
4494 j++;
4495 }
4496 }
4497 FC(hfd);
4498 R(0);
4499 }
4500 /* funcation to delete the history file. */
delhistory(C * file)4501 U SH delhistory(C *file){
4502 /* check for existence, and write access. */
4503 IF(AC(file,F_OK)&&AC(file,W_OK)){
4504 pe("could not access the history file to delete",0);
4505 R(1);
4506 }
4507 /* no errors above, attempt to delete. */
4508 EI(UN(file)){
4509 pe("could not delete the history file",0);
4510 R(1);
4511 }
4512 /* deleted without a problem. */
4513 pe("successfully removed the history file",0);
4514 R(0);
4515 }
4516 /* gets arguments out of +x files, if no arguments it will return false, and */
4517 /* not continue. */
getexecargs(C * ruleset)4518 U SH getexecargs(C *ruleset){
4519 U I i=0;
4520 U I j=0;
4521 /* if it is bigger than that someone is just trying to be evil. */
4522 U C rread[(BASE_BUFFER*4+1)];
4523 FL *fd;
4524 IF(!(fd=FO(ruleset,"r")))
4525 pe("ruleset file does not appear to exist, or is not readable",1);
4526 E{
4527 B(rread,(BASE_BUFFER*4+1));
4528 /* only need to read the first two lines for the arguments. */
4529 W(FS(rread,(SO(rread)-1),fd)&&j<2){
4530 IF(SL(rread)>2&&!SNC(rread,"#?",2)){
4531 /* ?(args) + -2("#?") + ?(ruleset) + 4(-r,space,space) + 1(extra). */
4532 IF(!(toenv=(C *)M(SL(rread)-2+SL(ruleset)+4+1)))
4533 pe("getexecargs(): allocation of memory error",1);
4534 B(toenv,(SL(rread)-2+SL(ruleset)+4+1));
4535 SP(toenv,"-r %s ",ruleset);
4536 F(i=2;i<SL(rread);i++){
4537 /* finish true, and append 0x0. */
4538 IF(rread[i]==0x0A){
4539 toenv[SL(toenv)]=0x0;
4540 FC(fd);
4541 R(1);
4542 }
4543 toenv[SL(toenv)]=rread[i];
4544 }
4545 }
4546 j++;
4547 }
4548 }
4549 FC(fd);
4550 R(0);
4551 }
4552 /* function to read /etc/services in conjunction with the -p option to */
4553 /* support services in the form of a string. for example: "finger". */
4554 /* port should really be a short instead of an int. but, i wanted error */
4555 /* checking. so, i used int. */
portentry(C * service)4556 U I portentry(C *service){
4557 S servent *se;
4558 IF(!(se=GS(service,(isudp?"udp":"tcp"))))
4559 R(AI(service));
4560 E
4561 /* convert back from the network byte order that the function does. */
4562 R(NHS(se->s_port));
4563 /* will never really make it here. */
4564 R(0);
4565 }
4566 /* program initializes here. gets things started. */
main(I ac,C ** av)4567 I main(I ac,C **av){
4568 U SH sethist=0;
4569 U SH setlist=0;
4570 U I i=0;
4571 U I j=0;
4572 U I k=0;
4573 U I l=0;
4574 U I m=0;
4575 U I n=0;
4576 /* the pid of the background process. */
4577 PT bgpid=0;
4578 C *avo;
4579 C *envcmd;
4580 C *histline;
4581 /* threads are only needed for the gui. */
4582 #ifdef GTK
4583 pthread_t pt;
4584 #endif
4585 /* set the static pid value. (for display) */
4586 cpid=GPD();
4587 /* set the program name. this is kind of like rindex()/strrchr(). but, */
4588 /* slightly different. */
4589 F(i=SL(av[0]);(av[0][i]!=0x2F&&i>0);i--)
4590 j++;
4591 IF(i<=0){
4592 IF(!(progname=(C *)SDU(av[0])))
4593 pe("main(): duplication of memory error",1);
4594 }
4595 E{
4596 /* do not add extra zero'd byte, it is already there at this point. */
4597 IF(!(progname=(C *)M(j)))
4598 pe("main(): allocation of memory error",1);
4599 B(progname,j);
4600 F(i=SL(av[0]);j;i--){
4601 j--;
4602 progname[j]=av[0][i];
4603 }
4604 }
4605 /* ctrl-c. */
4606 SG(SIGINT,sighandler);
4607 /* segmentation fault, hope not to see that. */
4608 SG(SIGSEGV,sighandler);
4609 /* kill, or terminate signal. */
4610 SG(SIGTERM,sighandler);
4611 /* used for timed killing of netscript. */
4612 SG(SIGALRM,sighandler);
4613 /* other signals to catch, for clean up. (not defined in the handler) */
4614 SG(SIGILL,sighandler);
4615 SG(SIGTRAP,sighandler);
4616 SG(SIGBUS,sighandler);
4617 SG(SIGQUIT,sighandler);
4618 /* ignored for binding(with -I). do not want to exit due to it. */
4619 SG(SIGPIPE,SIG_IGN);
4620 /* make global non-other, and non-group permissions for files made by */
4621 /* netscript. */
4622 UM(077);
4623 /* using this method for global knowledge that if netscript was started */
4624 /* privileged, or not. any other way the -u option could change the */
4625 /* effects of checking. since this gets processed first, it will know. */
4626 /* just in the rare case netscript would need to be set*id. disables */
4627 /* modules, file reading/writing, and third party execution support. if */
4628 /* started set*id. (or could use stored values for later checking. but, i */
4629 /* like this method) */
4630 IF(GU()!=GEU()||GG()!=GEG())
4631 isprivileged=1;
4632 E
4633 isprivileged=0;
4634 /* set*id = sete*id. (mainly for proper permission changes) */
4635 SUD(GEU());
4636 SGD(GEG());
4637 /* write to the array of the defined options. (when compiled) */
4638 setdefined();
4639 /* only time this should be used. */
4640 IF(!isprivileged){
4641 setrc(RCFILE);
4642 sethistory(HISTFILE);
4643 }
4644 /* take care of the modules environmental variable first. */
4645 #ifndef DISABLE_MODULES
4646 IF(G(ENV_MODULE)){
4647 IF(isprivileged)
4648 pe("environmental variable module file ignored with privileged access",0);
4649 E
4650 modhandler((C *)G(ENV_MODULE));
4651 }
4652 /* check, and use the ns_init() symbol, it passes the number of command */
4653 /* line arguments, and the arguments. (int, char **) */
4654 IF(vmodule)
4655 (*init_function)(ac,av);
4656 #endif
4657 /* set the shell for executing third party programs. make sure it is */
4658 /* executable. */
4659 IF(G(ENV_SHELL)&&!AC((C *)G(ENV_SHELL),X_OK)){
4660 IF(!(eshell=(C *)SDU((C *)G(ENV_SHELL))))
4661 pe("main(): duplication of memory error",1);
4662 }
4663 /* if all else fails. set default, and hope. */
4664 E{
4665 IF(!(eshell=(C *)SDU(SHPATH)))
4666 pe("main(): duplication of memory error",1);
4667 }
4668 /* set up the display name. */
4669 setdname();
4670 /* set up the tty name. */
4671 IF(!AC(TN(0),R_OK)){
4672 IF(!(ttyn=(C *)SDU(TN(0))))
4673 pe("main(): duplication of memory error",1);
4674 }
4675 E{
4676 IF(!(ttyn=(C *)SDU(INPUTPATH)))
4677 pe("main(): duplication of memory error",1);
4678 }
4679 /* made sure the usage is seen. */
4680 IF(ac>=2&&!SNC(av[1],"--help",6))
4681 usage(1);
4682 /* generalized support for the --hist[ory] option to read ~/.nshistory. */
4683 IF(ac>=2&&!SNC(av[1],"--hist",6)){
4684 IF(isprivileged)
4685 pe("can not use \"--hist\" while in privileged mode",1);
4686 E{
4687 IF(ac>=3&&!SNC(av[2],"clear",5))
4688 nsexit(delhistory(histfile),0);
4689 E{
4690 k=usehistory((ac>=3?av[2]:0),(ac>=3?1:0));
4691 IF(!k)
4692 pe("invalid history value",1);
4693 E
4694 sethist=1;
4695 }
4696 }
4697 }
4698 IF(G(ENV_PATH)||(ac>=2&&!SNC(av[1],"--list",6))){
4699 IF(isprivileged)
4700 pe("can not use \"--list\" while in privileged mode",1);
4701 E{
4702 /* handle the list, environmental variable overrides command line. */
4703 setlist=usefilelist(G(ENV_PATH)?(C *)G(ENV_PATH):(ac>=3?av[2]:"."));
4704 IF(!setlist)
4705 pe("invalid list value",1);
4706 }
4707 }
4708 /* +x ruleset file support, generalized support. (or modified) */
4709 IF(((av[1]&&!av[2])||setlist)&&!AC((setlist?tofile:av[1]),R_OK)&&!AC((setlist?
4710 tofile:av[1]),X_OK))
4711 k=getexecargs(setlist?tofile:av[1]);
4712 /* last use of --list, then everything is passed over. */
4713 IF(setlist){
4714 FR(tofile);
4715 IF(!k)
4716 pe("not a valid (internal argument supplied) netscript ruleset",1);
4717 }
4718 /* check the environment for the command line override variable. or, take */
4719 /* +x file arguments as env controller, all in one deal. */
4720 IF(G(ENV_CMDLINE)||k){
4721 /* priority 1 is +x files, priority 2 is env var, and priority 3 is the */
4722 /* normal command line. */
4723 IF(k){
4724 IF(!(envcmd=(C *)M(SL(toenv)+SL(av[0])+2)))
4725 pe("main(): allocation of memory error",1);
4726 B(envcmd,(SL(toenv)+SL(av[0])+2));
4727 }
4728 E{
4729 IF(!(envcmd=(C *)M(SL((C *)G(ENV_CMDLINE))+SL(av[0])+2)))
4730 pe("main(): allocation of memory error",1);
4731 B(envcmd,(SL((C *)G(ENV_CMDLINE))+SL(av[0])+2));
4732 }
4733 IF(k){
4734 SP(envcmd,"%s %s",av[0],toenv);
4735 /* done with that buffer. */
4736 FR(toenv);
4737 }
4738 E
4739 SP(envcmd,"%s %s",av[0],(C *)G(ENV_CMDLINE));
4740 /* used this method to make a fresh argument list. */
4741 /* finding out how many elements are needed. then, nulling the loop */
4742 /* routine since it was all done in the process itself. */
4743 F(ac=0;!parameter(envcmd,ac,0x20);ac++);
4744 /* creates the argument array. also, added an extra slot for argv[0], */
4745 /* which will remain unused. but, getopt() expects it. */
4746 IF(!(av=(C **)M((ac+1)*(SO(C *)))))
4747 pe("main(): allocation of memory error",1);
4748 /* fill the array with the data from the env var, or +x file. */
4749 /* (ENV_CMDLINE|+x) */
4750 F(ac=0;!parameter(envcmd,ac,0x20);ac++){
4751 IF(!(av[ac]=(C *)SDU(parm)))
4752 pe("main(): duplication of memory error",1);
4753 }
4754 FR(envcmd);
4755 }
4756 /* add the -g option automatically, if it is linked by "gnetscript". */
4757 #ifdef GTK
4758 IF((!SC(((C *)RI(progname,0x2F)?(C *)RI(progname,0x2F):"0"),"/gnetscript")||
4759 !strcmp(progname,"gnetscript"))&&!isprivileged)
4760 isgui=1;
4761 #endif
4762 /* add the -_ option automatically, if it is linked by "nnetscript". */
4763 #ifdef NCURSES
4764 IF((!SC(((C *)RI(progname,0x2F)?(C *)RI(progname,0x2F):"0"),"/nnetscript")||
4765 !strcmp(progname,"nnetscript")))
4766 isncursesa=1;
4767 #endif
4768 IF(ac>1&&SNC(av[1],"--interactive",13)){
4769 /* set up, and build the (get) option list. */
4770 n=89;
4771 #ifdef GTK
4772 n+=10;
4773 #endif
4774 #ifdef NCURSES
4775 n+=3;
4776 #endif
4777 #ifndef DISABLE_SYSLOG
4778 n+=1;
4779 #endif
4780 IF(!(avo=(C *)M(n+1)))
4781 pe("main(): allocation of memory error",1);
4782 B(avo,(n+1));
4783 SCP(avo,"r:h:p:0:1:2:3:4:5:6:7:8:9:i:m:M:R:k:u:q:o:S:U:t:Q:l:e:E:O:x:Xaf@^Bn"
4784 "NjJFIsbTyYzLHDwPcCAdvV");
4785 #ifdef GTK
4786 SCA(avo,"G:+:#:K:gW");
4787 #endif
4788 #ifdef NCURSES
4789 SCA(avo,"_=:");
4790 #endif
4791 #ifndef DISABLE_SYSLOG
4792 SCA(avo,"Z");
4793 #endif
4794 /* interpret out the arguments supplied. */
4795 /* i changed a method here, due to me using shorts for most of these */
4796 /* options. i did not want a possible loop over bug to occur if someone */
4797 /* was trying to break netscript with repeated arguments. (65536) */
4798 W((i=getopt(ac,av,avo))!=EOF){
4799 SW(i){
4800 /* does not matter if a user has privileged access, and loads a ruleset. */
4801 /* because, it never gets relayed verbose. (unless someone knows a rule, */
4802 /* or is traced back/memory) no major concern. */
4803 CS 'r':
4804 /* can not have both. */
4805 IF(!inputrules&&!setfile){
4806 /* does both parsedynamic(), and parsecharvars(). gets used often. */
4807 parsecmdline(optarg);
4808 IF(!(rulesfile=(C *)SDU(parsedline)))
4809 pe("main(): duplication of memory error",1);
4810 setfile=1;
4811 }
4812 BR;
4813 CS 'h':
4814 IF(!bindmode&&!sethost){
4815 W(!parameter(optarg,tshs,0x2C)){
4816 parsecmdline(parm);
4817 IF(!(shost[tshs++]=(C *)SDU(SL(parsedline)?parsedline:"0")))
4818 pe("main(): duplication of memory error",1);
4819 IF(tshs>=MAX_ARGS)
4820 pe("too many slots to store in memory",1);
4821 }
4822 sethost=1;
4823 }
4824 BR;
4825 CS 'p':
4826 IF(!sport)
4827 sport=portentry(optarg);
4828 BR;
4829 /* not very pretty. but, it will do. all of these will be handled the */
4830 /* same way. the statically set dynamic variable options. */
4831 CS '0':
4832 CS '1':
4833 CS '2':
4834 CS '3':
4835 CS '4':
4836 CS '5':
4837 CS '6':
4838 CS '7':
4839 CS '8':
4840 CS '9':
4841 /* do not reset the variable, could cause memory problems. */
4842 IF(dynamicvarset[(i-0x30)]!=2){
4843 parsecmdline(optarg);
4844 IF(!(dynamicvar[(i-0x30)]=(C *)SDU(parsedline)))
4845 pe("main(): duplication of memory error",1);
4846 /* define it not to be changed, or reset. */
4847 dynamicvarset[(i-0x30)]=2;
4848 }
4849 BR;
4850 CS 'i':
4851 IF(!initsend){
4852 parsecmdline(optarg);
4853 IF(!(iswrite=(C *)SDU(parsedline)))
4854 pe("main(): duplication of memory error",1);
4855 initsend=1;
4856 }
4857 BR;
4858 CS 'm':
4859 IF(!setcdir){
4860 parsecmdline(optarg);
4861 IF(!(cdir=(C *)SDU(parsedline)))
4862 pe("main(): duplication of memory error",1);
4863 setcdir=1;
4864 }
4865 BR;
4866 CS 'M':
4867 IF(!setrdir){
4868 parsecmdline(optarg);
4869 IF(!(rdir=(C *)SDU(parsedline)))
4870 pe("main(): duplication of memory error",1);
4871 setrdir=1;
4872 }
4873 BR;
4874 CS 'R':
4875 IF(!setroute){
4876 parsecmdline(optarg);
4877 IF(!(rhost=(C *)SDU(parsedline)))
4878 pe("main(): duplication of memory error",1);
4879 setroute=1;
4880 }
4881 BR;
4882 CS 'k':
4883 IF(AI(optarg)>0&&!rport)
4884 rport=AI(optarg);
4885 BR;
4886 CS 'u':
4887 IF(!setperms){
4888 setpermissions(optarg,0);
4889 setperms=1;
4890 }
4891 BR;
4892 CS 'q':
4893 IF(!isvhost){
4894 IF(!(vhost=(C *)SDU(optarg)))
4895 pe("main(): duplication of memory error",1);
4896 isvhost=1;
4897 }
4898 BR;
4899 CS 'o':
4900 IF(!omitchars){
4901 parsecmdline(optarg);
4902 IF(!(ochars=(C *)SDU(parsedline)))
4903 pe("main(): duplication of memory error",1);
4904 omitchars=1;
4905 }
4906 BR;
4907 CS 'S':
4908 IF(AI(optarg)>0&&!sdelay)
4909 sdelay=AI(optarg);
4910 BR;
4911 CS 'U':
4912 IF(AL(optarg)>0&&!sudelay)
4913 sudelay=AL(optarg);
4914 BR;
4915 CS 't':
4916 IF(AI(optarg)>0&&!alrm)
4917 alrm=AI(optarg);
4918 BR;
4919 CS 'Q':
4920 IF(!soptions){
4921 parsecmdline(optarg);
4922 IF(!(sopts=(C *)SDU(parsedline)))
4923 pe("main(): duplication of memory error",1);
4924 soptions=1;
4925 }
4926 BR;
4927 CS 'l':
4928 IF(isprivileged)
4929 pe("can not log data to a file with privileged access",0);
4930 E
4931 IF(!islog){
4932 parsecmdline(optarg);
4933 IF(!(logfile=(C *)SDU(parsedline)))
4934 pe("main(): duplication of memory error",1);
4935 islog=1;
4936 }
4937 BR;
4938 #ifdef GTK
4939 CS 'G':
4940 IF(!isguititle){
4941 parsecmdline(optarg);
4942 IF(!(guititle=(C *)SDU(parsedline)))
4943 pe("main(): duplication of memory error",1);
4944 isguititle=1;
4945 }
4946 BR;
4947 CS '+':
4948 IF(AI(optarg)>0&&!guio)
4949 guio=(AI(optarg)>GUI_MAXLEN?GUI_MAXLEN:AI(optarg));
4950 BR;
4951 CS '#':
4952 IF(!isguic){
4953 parsecmdline(optarg);
4954 IF(SL(parsedline)==6){
4955 B((V *)guic,SO(guic));
4956 F(isguic=i=0;i<6;i+=2){
4957 IF(IL((U I)parsedline[i]))
4958 j=(TL(parsedline[i])-0x56);
4959 E
4960 j=(parsedline[i]-0x2F);
4961 j*=16;
4962 IF(IL((U I)parsedline[i+1]))
4963 j+=(TL(parsedline[i+1])-0x56);
4964 E
4965 j+=(parsedline[i+1]-0x2F);
4966 j-=17;
4967 IF(j>=0&&j<256)
4968 guic[isguic]=(j*257);
4969 isguic++;
4970 }
4971 }
4972 }
4973 BR;
4974 CS 'K':
4975 IF(!isguil){
4976 parsecmdline(optarg);
4977 W(!parameter(parsedline,isguil,0x3A)&&isguil<3){
4978 IF(!(gblabel[isguil++]=(C *)SDU(SL(parm)?parm:"nolabel")))
4979 pe("main(): duplication of memory error",1);
4980 }
4981 }
4982 BR;
4983 #endif
4984 CS 'e':
4985 IF(isprivileged)
4986 pe("third party programs can not be executed with privileged access",0);
4987 E
4988 IF(!runcmd){
4989 parsecmdline(optarg);
4990 IF(!(execfile=(C *)SDU(parsedline)))
4991 pe("main(): duplication of memory error",1);
4992 runcmd=1;
4993 }
4994 BR;
4995 CS 'E':
4996 IF(!runpre){
4997 parsecmdline(optarg);
4998 IF(!(execpre=(C *)SDU(parsedline)))
4999 pe("main(): duplication of memory error",1);
5000 runpre=1;
5001 }
5002 BR;
5003 CS 'O':
5004 IF(!setshell){
5005 parsecmdline(optarg);
5006 /* make sure it is executable. */
5007 IF(!AC(parsedline,X_OK)){
5008 /* was set by the environment, or default earlier. free it. */
5009 FR(eshell);
5010 IF(!(eshell=(C *)SDU(parsedline)))
5011 pe("main(): duplication of memory error",1);
5012 setshell=1;
5013 }
5014 }
5015 BR;
5016 CS 'x':
5017 IF(AI(optarg)>0&&!xalrm)
5018 xalrm=AI(optarg);
5019 BR;
5020 CS 'X':
5021 runexit=1;
5022 BR;
5023 CS 'a':
5024 isiexec=1;
5025 BR;
5026 CS 'f':
5027 editrules=1;
5028 BR;
5029 CS '@':
5030 isudp=1;
5031 BR;
5032 CS '^':
5033 isudpr=1;
5034 BR;
5035 CS 'B':
5036 isbg=1;
5037 BR;
5038 CS 'n':
5039 nossend=1;
5040 BR;
5041 CS 'N':
5042 nosrecv=1;
5043 BR;
5044 CS 'j':
5045 norsend=1;
5046 BR;
5047 CS 'J':
5048 norrecv=1;
5049 BR;
5050 CS 'F':
5051 nofrom=1;
5052 BR;
5053 CS 'I':
5054 forever=1;
5055 BR;
5056 CS 's':
5057 /* can not have both. */
5058 IF(!setfile)
5059 inputrules=1;
5060 BR;
5061 CS 'b':
5062 /* can not have both. */
5063 IF(!sethost)
5064 bindmode=1;
5065 BR;
5066 #ifdef GTK
5067 CS 'g':
5068 IF(!isgui){
5069 IF(!isprivileged)
5070 isgui=1;
5071 E
5072 pe("the gui frontend can not be used when netscript is privileged",0);
5073 }
5074 E
5075 isbgui=1;
5076 BR;
5077 CS 'W':
5078 isguis=1;
5079 BR;
5080 #endif
5081 #ifdef NCURSES
5082 CS '_':
5083 isncursesa=1;
5084 BR;
5085 CS '=':
5086 IF(!isncursesl){
5087 parsecmdline(optarg);
5088 W(!parameter(parsedline,isncursesl,0x3A)&&isncursesl<2){
5089 IF(!(nclabel[isncursesl++]=(C *)SDU(SL(parm)?parm:"nolabel")))
5090 pe("main(): duplication of memory error",1);
5091 }
5092 }
5093 #endif
5094 #ifndef DISABLE_SYSLOG
5095 CS 'Z':
5096 slog=1;
5097 BR;
5098 #endif
5099 CS 'T':
5100 tnet=1;
5101 BR;
5102 CS 'y':
5103 tnetraw=1;
5104 BR;
5105 CS 'Y':
5106 tnetraw=2;
5107 BR;
5108 CS 'z':
5109 notnetopt=1;
5110 BR;
5111 CS 'L':
5112 /* set option, and force the no wrapping option. (-w option) */
5113 lnum=lnum_i=lnum_o=nowrap=1;
5114 BR;
5115 CS 'H':
5116 /* 0 = character, 1 = hex, 2 = decimal. */
5117 displaytype=1;
5118 BR;
5119 CS 'D':
5120 /* 0 = character, 1 = hex, 2 = decimal. */
5121 displaytype=2;
5122 BR;
5123 CS 'w':
5124 nowrap=1;
5125 BR;
5126 CS 'P':
5127 printonly=1;
5128 BR;
5129 CS 'c':
5130 noshowc=1;
5131 BR;
5132 CS 'C':
5133 noshowp=1;
5134 BR;
5135 CS 'A':
5136 noshowa=1;
5137 BR;
5138 CS 'd':
5139 displayv();
5140 BR;
5141 CS 'v':
5142 showinfo(1);
5143 nsexit(0,0);
5144 BR;
5145 CS 'V':
5146 showv=2;
5147 BR;
5148 default:
5149 usage(0);
5150 BR;
5151 }
5152 }
5153 /* done with buffer forever. */
5154 FR(avo);
5155 }
5156 E
5157 iface(IFACE_PREFIX);
5158 /* if chroot, handle first. */
5159 IF(setrdir){
5160 CR(rdir);
5161 FR(rdir);
5162 }
5163 /* if chdir, handle second. */
5164 IF(setcdir){
5165 CD(cdir);
5166 FR(cdir);
5167 }
5168 /* check for -r|s|f, -h|b, and -p(int->short style) options. */
5169 IF((!setfile&&!inputrules&&!editrules)||(!sethost&&!bindmode)||(1>sport||
5170 65535<sport)){
5171 pe("no ruleset option, host|bind option, and/or port option defined",0);
5172 IF(ac>1)
5173 usage(1);
5174 E
5175 nsexit(0,0);
5176 }
5177 /* default if invalid, or non-existent. */
5178 IF(1>rport||65535<rport)
5179 rport=sport;
5180 /* ruleset editor. (-f option) */
5181 IF(editrules&&!inputrules){
5182 IF(setfile)
5183 editrules=2;
5184 ruleedit(setfile,(setfile?rulesfile:0));
5185 }
5186 /* make, and define the ruleset. */
5187 makelists(rulesfile);
5188 /* remove temporary ruleset, only if a temporary file. (no verbose) */
5189 IF(editrules==1)
5190 UN(rulesfile);
5191 /* if gui mode is on, disable certain option(s). */
5192 #ifdef GTK
5193 /* can not do both, at least making sense. */
5194 IF(isbg)
5195 isgui=0;
5196 EI(isgui&&tnetraw){
5197 tnetraw=0;
5198 tnet=1;
5199 }
5200 #endif
5201 /* if one of the telnet fix options is supplied, fix conflicting option(s). */
5202 /* also, forces telnet mode. (-y, and -Y options) */
5203 IF(tnetraw)
5204 tnet=noshowa=nossend=nosrecv=1;
5205 #ifdef GTK
5206 IF(isgui){
5207 g_thread_init(0);
5208 /* gtk initialization, passes arguments for gtk to handle. */
5209 gtk_init(&ac,&av);
5210 /* get things going. if it fails for some reason, exit. */
5211 IF(pthread_create(&pt,0,(V *)*gtkrun,(inputrules?"(standard input)":rulesfile
5212 )))
5213 pe("could not create pthread, for the gui",1);
5214 /* time to catch up. */
5215 W(!isagui)
5216 USLP(250000);
5217 }
5218 #endif
5219 /* main argument checking done, continuing on. */
5220 IF(showv)
5221 showinfo(showv);
5222 /* check for non-dfl columns, for the pd() display function with wordwrap. */
5223 /* do this before using the pd() function at all. */
5224 IF(G(ENV_COLUMNS)){
5225 columns=AI((C *)G(ENV_COLUMNS));
5226 /* no need for anything larger, unless you are trying to bother memory. */
5227 IF(1024<columns){
5228 pe("ENV_COLUMNS environmental variable is too large",0);
5229 columns=DFL_COLUMNS;
5230 }
5231 /* the prompt itself must be counted in the most minimal of cases. */
5232 IF((1>columns&&nofrom)||(4>columns&&!nofrom)){
5233 pe("ENV_COLUMNS environmental variable is too small",0);
5234 columns=DFL_COLUMNS;
5235 }
5236 }
5237 E
5238 columns=DFL_COLUMNS;
5239 /* same idea as above. except a different kind of checking. */
5240 IF(G(ENV_BACKLOG)){
5241 blog=AI((C *)G(ENV_BACKLOG));
5242 IF(128<blog){
5243 pe("ENV_BACKLOG environmental variable is too large",0);
5244 blog=DFL_BACKLOG;
5245 }
5246 IF(1>blog){
5247 pe("ENV_BACKLOG environmental variable is too small",0);
5248 blog=DFL_BACKLOG;
5249 }
5250 }
5251 E
5252 blog=DFL_BACKLOG;
5253 /* command line is a priority. */
5254 IF(!isvhost&&G(ENV_VHOST)){
5255 IF(!(vhost=(C *)SDU((C *)G(ENV_VHOST))))
5256 pe("main(): duplication of memory error",1);
5257 isvhost=1;
5258 }
5259 /* there would atleast have been one argument to have made it this far. */
5260 F(j=1;j<ac;j++)
5261 /* +1 for the space. (CR) */
5262 m+=(SL(av[j])+1);
5263 IF(!(histline=(C *)M(m+1)))
5264 pe("main(): allocation of memory error",1);
5265 B(histline,(m+1));
5266 F(j=1;j<ac;j++){
5267 SCA(histline,av[j]);
5268 IF((j+1)!=ac)
5269 SCA(histline," ");
5270 }
5271 #ifndef DISABLE_SYSLOG
5272 wrso("%d-%d id: %lu-%u.%u.%u.%u init: %s",slnum_t,(slnum_s++),cpid,GU(),GEU(),
5273 GG(),GEG(),(SL(histline)?histline:"<no command line>"));
5274 #endif
5275 /* no need to re-write history. (sethist) */
5276 IF(!isprivileged&&!sethist&&SL(histline))
5277 addhistory(histline);
5278 /* done with this, forever. */
5279 FR(histline);
5280 SW(isbg?(bgpid=FK()):0){
5281 CS -1:
5282 pe("could not fork into the background",1);
5283 BR;
5284 CS 0:
5285 /* only if really backgrounding. */
5286 IF(isbg){
5287 /* no more output now. close up shop, just to make sure nothing is */
5288 /* outputed. */
5289 CL(0);
5290 CL(1);
5291 CL(2);
5292 isbga=1;
5293 }
5294 /* initialize ncurses, after everything is ready to go. (compiled option) */
5295 #ifdef NCURSES
5296 IF(!(!isncursesa||isbg||tnetraw))
5297 #ifdef GTK
5298 IF(!isgui)
5299 #endif
5300 ncursesinit();
5301 #endif
5302 /* infinite connecting/binding. (-I option) */
5303 IF(forever){
5304 W(1){
5305 /* either stops after all those hosts, to get reset. or, stays binded */
5306 /* forever. */
5307 W(l<tshs||bindmode){
5308 parsesocket(bindmode?0:shost[l++],sport);
5309 #ifndef DISABLE_SYSLOG
5310 /* should only log closings, if is a multi-remote run. otherwise, it */
5311 /* would show the static close, and exit everytime. a waste of space. */
5312 wrso("%d-%d id: %lu-%u.%u.%u.%u closed: %d",slnum_t,slnum_s,cpid,GU(),
5313 GEU(),GG(),GEG(),slnum_t);
5314 /* reset system log counter. */
5315 slnum_s=0;
5316 /* +1 the total. */
5317 slnum_t++;
5318 #endif
5319 /* better safe than sorry, do not want fds to fill up. */
5320 closesocket(0);
5321 SLP(1);
5322 }
5323 l=0;
5324 }
5325 }
5326 E{
5327 W(l<tshs||bindmode){
5328 parsesocket(bindmode?0:shost[l++],sport);
5329 /* turn bindmode off to leave this loop, and exit. (if bindmode) */
5330 bindmode=0;
5331 /* better safe than sorry, do not want fds to fill up. */
5332 closesocket(0);
5333 SLP(1);
5334 }
5335 }
5336 /* for backgrounding only. */
5337 IF(isbga)
5338 nsexit(0,1);
5339 BR;
5340 default:
5341 nsprint("PID: [%lu@%s]\n",bgpid,nname);
5342 BR;
5343 }
5344 nsexit(0,0);
5345 /* never will actually make it to this point. but, will shut up warnings. */
5346 exit(0);
5347 }
5348 /* EOF */
5349