home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / unix / volume26 / pcomm202 / part03 < prev    next >
Encoding:
Text File  |  1993-04-13  |  96.7 KB  |  4,104 lines

  1. Newsgroups: comp.sources.unix
  2. From: fthood!egray@uxc.cso.uiuc.edu (Emmet Gray)
  3. Subject: v26i155: pcomm-2.0.2 - a serial communications program (clone of ProComm), Part03/06
  4. Sender: unix-sources-moderator@vix.com
  5. Approved: paul@vix.com
  6.  
  7. Submitted-By: fthood!egray@uxc.cso.uiuc.edu (Emmet Gray)
  8. Posting-Number: Volume 26, Issue 155
  9. Archive-Name: pcomm-2.0.2/part03
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 3 (of 6)."
  18. # Contents:  Makefile cmd.c d_lib.c d_menu.c input.c p_lib.c s_modem.c
  19. #   terminal.c x_ascii.c x_batch.c x_menu.c xmodem.c
  20. # Wrapped by vixie@gw.home.vix.com on Wed Apr 14 00:38:42 1993
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f 'Makefile' -a "${1}" != "-c" ; then 
  23.   echo shar: Will not clobber existing file \"'Makefile'\"
  24. else
  25. echo shar: Extracting \"'Makefile'\" \(6622 characters\)
  26. sed "s/^X//" >'Makefile' <<'END_OF_FILE'
  27. X#                PCOMM v2.0
  28. X#                 for generic SVR4
  29. X
  30. X#for 80286 versions of SCO Xenix
  31. X#CFLAGS = -Od -DM_TERMINFO -Mle2 -LARGE
  32. X#LDFLAGS = -SEG 1000 -F 5000 -Mle2
  33. X#CURSES = -ltinfo -lx
  34. X
  35. X#for 80386 versions of SCO Xenix
  36. X#CFLAGS = -O -DM_TERMINFO
  37. X#LDFLAGS = -s
  38. X#CURSES = -ltinfo -lx
  39. X
  40. X#for the AT&T Unix PC 7300/3b1
  41. X#LD = ld
  42. X#SHLIB = /lib/crt0s.o /lib/shlib_c.ifile
  43. X#OTHER = /lib/setvbuf.o /lib/doprnt.o -luipc
  44. X
  45. X#for Sun OS (using the System V compiler)
  46. X#CC = /usr/5bin/cc
  47. X#LD = /usr/5bin/cc
  48. X
  49. LD = cc
  50. SHLIB =
  51. OTHER =
  52. CFLAGS = -O
  53. LDFLAGS = -s
  54. SHAR = shar -a
  55. X
  56. BIN_DIR = /usr/local/bin
  57. MAN_DIR = /usr/man1
  58. MAN_EXT = 1
  59. PCOMM_LIB = /usr/local/lib/pcomm
  60. X
  61. X#for old curses (i.e. Berkeley systems)
  62. X#CURSES = -lcurses -ltermcap
  63. CURSES = -lcurses
  64. X
  65. X#for systems without getcwd(3) or getopt(3)
  66. X#GETCWD.O = getcwd.o
  67. X#GETCWD.C = getcwd.c
  68. X#GETOPT.O = getopt.o
  69. X#GETOPT.C = getopt.c
  70. X
  71. X#for System V or Berkeley TTY interface
  72. X#TTY.O = tty_ucb.o
  73. X#TTY.C = tty_ucb.c
  74. TTY.O = tty_att.o
  75. TTY.C = tty_att.c
  76. X
  77. X#for System V poll() or Berkeley select()
  78. X#IPC.O = ipc_ucb.o
  79. X#IPC.C = ipc_ucb.c
  80. IPC.O = ipc_att.o
  81. IPC.C = ipc_att.c
  82. X
  83. PCOMM = $(GETCWD.O) $(GETOPT.O) $(TTY.O) $(IPC.O) admin.o chg_dir.o cmd.o \
  84. X    curses.o d_delete.o d_lib.o d_manual.o d_menu.o d_print.o \
  85. X    d_prompt.o d_revise.o data_log.o di_delay.o di_win.o dial.o \
  86. X    e_lib.o expand.o help.o info.o init.o input.o list_dir.o ls_menu.o \
  87. X    m_lib.o macro.o main.o n_shell.o p_lib.o passthru.o pexit.o \
  88. X    port.o redial.o s_axfer.o s_extrnl.o s_gen.o s_menu.o s_modem.o \
  89. X    s_prompt.o s_term.o s_tty.o screen.o script.o st_line.o \
  90. X    strings.o terminal.o vcs.o x_ascii.o x_batch.o x_extrnl.o \
  91. X    x_menu.o x_rcv.o x_send.o x_win.o xmodem.o
  92. X
  93. all:    pcomm waitfor matches pcomm_cmd
  94. X
  95. pcomm:    $(PCOMM)
  96. X    $(LD) $(LDFLAGS) $(PCOMM) $(OTHER) -o pcomm $(CURSES) $(SHLIB)
  97. X
  98. waitfor: waitfor.o
  99. X    $(LD) $(LDFLAGS) waitfor.o -o waitfor $(SHLIB)
  100. X
  101. matches: matches.o
  102. X    $(LD) $(LDFLAGS) matches.o -o matches $(SHLIB)
  103. X
  104. pcomm_cmd: pcomm_cmd.o
  105. X    $(LD) $(LDFLAGS) pcomm_cmd.o -o pcomm_cmd $(SHLIB)
  106. X
  107. pcomm_cmd.o:
  108. X    $(CC) $(CFLAGS) -DIPC=\"$(IPC.C)\" -c pcomm_cmd.c
  109. X
  110. install:
  111. X    cp pcomm waitfor matches pcomm_cmd $(BIN_DIR)
  112. X#    obviously this requires super-user privelidges...
  113. X#    chmod 4755 $(BIN_DIR)/pcomm
  114. X#    chown uucp $(BIN_DIR)/pcomm
  115. X
  116. install_man:
  117. X    cp Pcomm.1 $(MAN_DIR)/pcomm.$(MAN_EXT)
  118. X    cp Pcomm_cmd.1 $(MAN_DIR)/pcomm_cmd.$(MAN_EXT)
  119. X    cp Waitfor.1 $(MAN_DIR)/waitfor.$(MAN_EXT)
  120. X    cp Matches.1 $(MAN_DIR)/matches.$(MAN_EXT)
  121. X
  122. install_support:
  123. X    cp Pcomm.dial_dir $(PCOMM_LIB)/pcomm.dial_dir
  124. X    cp Pcomm.modem $(PCOMM_LIB)/pcomm.modem
  125. X    cp Pcomm.param $(PCOMM_LIB)/pcomm.param
  126. X    cp Pcomm.extrnl $(PCOMM_LIB)/pcomm.extrnl
  127. X
  128. clean:
  129. X    rm pcomm waitfor matches pcomm_cmd
  130. X
  131. lint:
  132. X    lint -p -Dlint $(GETCWD.C) $(GETOPT.C) $(TTY.C) $(IPC.C) admin.c \
  133. X    chg_dir.c cmd.c curses.c d_delete.c d_lib.c d_manual.c d_menu.c \
  134. X    d_print.c d_prompt.c d_revise.c data_log.c di_delay.c di_win.c \
  135. X    dial.c e_lib.c expand.c help.c info.c init.c input.c list_dir.c \
  136. X    ls_menu.c m_lib.c macro.c main.c n_shell.c p_lib.c passthru.c \
  137. X    pexit.c port.c redial.c s_axfer.c s_extrnl.c s_gen.c s_menu.c \
  138. X    s_modem.c s_prompt.c s_term.c s_tty.c screen.c script.c \
  139. X    st_line.c strings.c terminal.c vcs.c x_ascii.c x_batch.c \
  140. X    x_extrnl.c x_menu.c x_rcv.c x_send.c x_win.c xmodem.c $(CURSES)
  141. X    lint -p -Dlint -DIPC=\"$(IPC.C)\" pcomm_cmd.c
  142. X    lint -p -Dlint waitfor.c
  143. X    lint -p -Dlint matches.c
  144. X
  145. shar:
  146. X    $(SHAR) Doc.me > pcomm_sh.1
  147. X    $(SHAR) Configure.sh Convert.sh Makefile Matches.1 Pcomm.1 \
  148. X    Pcomm.dial_dir Pcomm.extrnl Pcomm.modem Pcomm.param Pcomm_cmd.1 \
  149. X    Q_and_A Readme Release.notes Sample > pcomm_sh.2
  150. X    $(SHAR) Unixpc.shar Waitfor.1 admin.c chg_dir.c cmd.c cmd.h \
  151. X    config.h curses.c d_delete.c d_lib.c d_manual.c > pcomm_sh.3
  152. X    $(SHAR) d_menu.c d_print.c d_prompt.c d_revise.c data_log.c \
  153. X    di_delay.c di_win.c dial.c dial_dir.h e_lib.c expand.c extrnl.h \
  154. X    getcwd.c getopt.c help.c > pcomm_sh.4
  155. X    $(SHAR) info.c init.c input.c ipc.h ipc_att.c ipc_ucb.c \
  156. X    list_dir.c ls_menu.c m_lib.c macro.c main.c matches.c misc.h \
  157. X    modem.h n_shell.c > pcomm_sh.5
  158. X    $(SHAR) p_lib.c param.h passthru.c patchlevel.h pcomm_cmd.c \
  159. X    pexit.c port.c redial.c s_axfer.c s_extrnl.c s_gen.c > pcomm_sh.6
  160. X    $(SHAR) s_menu.c s_modem.c s_prompt.c s_term.c s_tty.c screen.c \
  161. X    script.c st_line.c status.h strings.c terminal.c tty_att.c \
  162. X    tty_ucb.c > pcomm_sh.7
  163. X    $(SHAR) vcs.c vcs.h waitfor.c x_ascii.c x_batch.c x_extrnl.c \
  164. X    x_menu.c x_rcv.c > pcomm_sh.8
  165. X    $(SHAR) x_send.c x_win.c xmodem.c xmodem.h > pcomm_sh.9
  166. X#    $(SHAR) Doc.out Matches.out Pcomm.out Pcomm_cmd.out Waitfor.out \
  167. X#    > pcomm_sh.10
  168. X
  169. admin.o:    config.h dial_dir.h param.h
  170. chg_dir.o:    config.h misc.h
  171. cmd.o:        cmd.h config.h dial_dir.h extrnl.h modem.h param.h status.h xmodem.h
  172. curses.o:    config.h misc.h status.h
  173. d_delete.o:    dial_dir.h misc.h param.h
  174. d_lib.o:    dial_dir.h param.h
  175. d_manual.o:    config.h dial_dir.h misc.h
  176. d_menu.o:    config.h dial_dir.h misc.h param.h
  177. d_print.o:    config.h dial_dir.h misc.h
  178. d_prompt.o:    dial_dir.h misc.h
  179. d_revise.o:    dial_dir.h misc.h param.h
  180. data_log.o:    misc.h param.h status.h
  181. di_delay.o:    misc.h param.h
  182. di_win.o:    dial_dir.h misc.h modem.h param.h status.h
  183. dial.o:        config.h dial_dir.h misc.h modem.h param.h
  184. e_lib.o:    extrnl.h
  185. expand.o:    config.h
  186. getopt.o:    config.h
  187. help.o:        config.h misc.h
  188. info.o:        patchlevel.h
  189. init.o:        config.h misc.h status.h
  190. input.o:    config.h misc.h param.h status.h vcs.h
  191. ipc_att.o:    ipc.h
  192. ipc_ucb.o:    ipc.h
  193. list_dir.o:    misc.h
  194. ls_menu.o:    dial_dir.h misc.h param.h
  195. m_lib.o:    modem.h
  196. macro.o:    misc.h param.h
  197. main.o:        config.h dial_dir.h extrnl.h misc.h modem.h param.h status.h
  198. n_shell.o:    config.h
  199. p_lib.o:    param.h
  200. passthru.o:    config.h misc.h
  201. pexit.o:    dial_dir.h misc.h param.h status.h
  202. port.o:        config.h dial_dir.h modem.h status.h
  203. redial.o:    config.h dial_dir.h misc.h
  204. s_axfer.o:    misc.h param.h
  205. s_extrnl.o:    extrnl.h misc.h
  206. s_gen.o:    misc.h param.h
  207. s_menu.o:    misc.h
  208. s_modem.o:    misc.h modem.h
  209. s_prompt.o:    misc.h
  210. s_term.o:    dial_dir.h misc.h param.h
  211. s_tty.o:    misc.h modem.h
  212. screen.o:    param.h status.h
  213. script.o:    config.h dial_dir.h misc.h modem.h status.h 
  214. st_line.o:    config.h dial_dir.h misc.h modem.h param.h status.h
  215. strings.o:    config.h
  216. terminal.o:    config.h dial_dir.h ipc.h misc.h modem.h param.h status.h xmodem.h
  217. tty_att.o:    dial_dir.h modem.h param.h
  218. tty_ucb.o:    dial_dir.h modem.h param.h
  219. vcs.o:        config.h status.h vcs.h
  220. x_ascii.o:    config.h misc.h param.h
  221. x_batch.o:    config.h misc.h xmodem.h
  222. x_extrnl.o:    config.h
  223. x_menu.o:    extrnl.h misc.h xmodem.h
  224. x_rcv.o:    config.h dial_dir.h misc.h xmodem.h
  225. x_send.o:    config.h dial_dir.h misc.h xmodem.h
  226. x_win.o:    dial_dir.h misc.h status.h xmodem.h
  227. xmodem.o:    config.h misc.h param.h xmodem.h
  228. X
  229. pcomm_cmd.o:    config.h cmd.h $(IPC.C)
  230. matches.o:    config.h
  231. waitfor.o:    config.h
  232. END_OF_FILE
  233. if test 6622 -ne `wc -c <'Makefile'`; then
  234.     echo shar: \"'Makefile'\" unpacked with wrong size!
  235. fi
  236. # end of 'Makefile'
  237. fi
  238. if test -f 'cmd.c' -a "${1}" != "-c" ; then 
  239.   echo shar: Will not clobber existing file \"'cmd.c'\"
  240. else
  241. echo shar: Extracting \"'cmd.c'\" \(7048 characters\)
  242. sed "s/^X//" >'cmd.c' <<'END_OF_FILE'
  243. X/*
  244. X * Pcomm script commands.  Since these will be executed from a forked
  245. X * shell script, the commands, queries, and responses are sent thru an
  246. X * IPC channel to Pcomm.
  247. X */
  248. X
  249. X#include <stdio.h>
  250. X#include <curses.h>
  251. X#include "cmd.h"
  252. X#include "config.h"
  253. X#include "dial_dir.h"
  254. X#include "extrnl.h"
  255. X#include "modem.h"
  256. X#include "param.h"
  257. X#include "status.h"
  258. X#include "xmodem.h"
  259. X
  260. static void send_reply(), do_xfer(), cmode(), tmode();
  261. X
  262. void
  263. cmd_input()
  264. X{
  265. X    extern int fd;
  266. X    int cmd, arg1, i, n, ret_code;
  267. X    char buf[256], *s, arg2[256], *strchr(), *str_rep();
  268. X    char *entry, *strtok(), ld_code;
  269. X    void hang_up(), line_set(), pexit(), screen_dump(), log_toggle();
  270. X    void lpr_toggle();
  271. X
  272. X    if (ipc_read(status->cmd_ipc, buf, 256))
  273. X        return;
  274. X
  275. X                    /* parse the comand line */
  276. X    if (sscanf(buf, "%d %d %s\n", &cmd, &arg1, arg2) != 3)
  277. X        return;
  278. X
  279. X    ret_code = 0;
  280. X    switch(cmd) {
  281. X        case SET:        /* the SET command */
  282. X            switch(arg1) {
  283. X                case BAUD:    
  284. X                    dir->baud[0] = (unsigned int) atoi(arg2);
  285. X                    line_set();
  286. X                    break;
  287. X                case PARITY:
  288. X                    dir->parity[0] = arg2[0];
  289. X                    line_set();
  290. X                    break;
  291. X                case DATA_BITS:
  292. X                    dir->data_bits[0] = atoi(arg2);
  293. X                    line_set();
  294. X                    break;
  295. X                case STOP_BITS:
  296. X                    dir->stop_bits[0] = atoi(arg2);
  297. X                    line_set();
  298. X                    break;
  299. X                case DUPLEX:
  300. X                    dir->duplex[0] = arg2[0];
  301. X                    line_set();
  302. X                    break;
  303. X                case AUX:
  304. X                    dir->aux[0] = str_rep(dir->aux[0], arg2);
  305. X                    break;
  306. X                case HOT_KEY:
  307. X                    param->hot_key = atoi(arg2);
  308. X                    break;
  309. X                case ASCII_HOT:
  310. X                    param->ascii_hot = str_rep(param->ascii_hot, arg2);
  311. X                    break;
  312. X                case FLOW_CTRL:
  313. X                    param->flow_ctrl = str_rep(param->flow_ctrl, arg2);
  314. X                    break;
  315. X                case CR_IN:    
  316. X                    param->cr_in = str_rep(param->cr_in, arg2);
  317. X                    break;
  318. X                case CR_OUT:
  319. X                    param->cr_out = str_rep(param->cr_out, arg2);
  320. X                    break;
  321. X                case LOGFILE:
  322. X                    param->logfile = str_rep(param->logfile, arg2);
  323. X                    break;
  324. X                case DUMPFILE:
  325. X                    param->dumpfile = str_rep(param->dumpfile, arg2);
  326. X                    break;
  327. X                case STRIP:    
  328. X                    param->strip = str_rep(param->strip, arg2);
  329. X                    break;
  330. X                case LOCAL_ECHO:    
  331. X                    param->local_echo = str_rep(param->local_echo, arg2);
  332. X                    break;
  333. X                case EXPAND:
  334. X                    param->expand = str_rep(param->expand, arg2);
  335. X                    break;
  336. X                case CR_DELAY:
  337. X                    param->cr_delay = atoi(arg2);
  338. X                    break;
  339. X                case PACE:
  340. X                    param->pace = str_rep(param->pace, arg2);
  341. X                    break;
  342. X                case CR_UP:
  343. X                    param->cr_up = str_rep(param->cr_up, arg2);
  344. X                    break;
  345. X                case LF_UP:
  346. X                    param->lf_up = str_rep(param->lf_up, arg2);
  347. X                    break;
  348. X                case TIMER:
  349. X                    param->timer = atoi(arg2);
  350. X                    break;
  351. X                case CR_DN:
  352. X                    param->cr_dn = str_rep(param->cr_dn, arg2);
  353. X                    break;
  354. X                case LF_DN:    
  355. X                    param->lf_dn = str_rep(param->lf_dn, arg2);
  356. X                    break;
  357. X                default:
  358. X                    break;
  359. X            }
  360. X            break;
  361. X        case QUERY:        /* the QUERY commands */
  362. X            switch(arg1) {
  363. X                case TTY_NAME:
  364. X                    if (modem->t_cur != -1)
  365. X                        send_reply(modem->tty[modem->t_cur]);
  366. X                    else
  367. X                        send_reply("NONE");
  368. X                    ret_code = 99;
  369. X                    break;
  370. X                case MODEM_NAME:
  371. X                    if (modem->m_cur != -1)
  372. X                        send_reply(modem->mname[modem->m_cur]);
  373. X                    else
  374. X                        send_reply("NONE");
  375. X                    ret_code = 99;
  376. X                    break;
  377. X                default:
  378. X                    break;
  379. X            }
  380. X            break;
  381. X        case IF:        /* the IF commands */
  382. X            switch(arg1) {
  383. X                case CONNECTED:
  384. X                    if (status->connected)
  385. X                        ret_code = 1;
  386. X                    break;
  387. X                case LOG_STATUS:
  388. X                    if (status->log_status)
  389. X                        ret_code = 1;
  390. X                    break;
  391. X                case PRINTER_STATUS:
  392. X                    if (status->print_status)
  393. X                        ret_code = 1;
  394. X                    break;
  395. X                default:
  396. X                    break;
  397. X            }
  398. X            break;
  399. X        case DIAL:
  400. X            cmode();
  401. X            ld_code = '\0';
  402. X            s = arg2;
  403. X            if (strchr("+-@#", *s)) {
  404. X                ld_code = *s;
  405. X                s++;
  406. X            }
  407. X
  408. X            if (arg1 == 1) {    /* manual dial */
  409. X                dir->name[0] = str_rep(dir->number[0], s);
  410. X                dir->number[0] = str_rep(dir->number[0], s);
  411. X                dir->d_cur = 0;
  412. X                dir->q_num[0] = 0;
  413. X            }
  414. X            else {
  415. X                n = atoi(s);
  416. X                if (n == 0 || n > NUM_DIR) {
  417. X                    tmode();
  418. X                    break;
  419. X                }
  420. X
  421. X                dir->d_cur = n;
  422. X                dir->q_num[0] = n;
  423. X            }
  424. X            dir->q_ld[0] = ld_code;
  425. X            dir->q_num[1] = -1;
  426. X            ret_code = dial_win(1);
  427. X            tmode();
  428. X            break;
  429. X        case REDIAL:
  430. X            cmode();
  431. X            entry = strtok(arg2, " ");
  432. X            for (i=0; i<NUM_QUEUE; i++) {
  433. X                if (entry == NULL) {
  434. X                    dir->q_num[i] = -1;
  435. X                    break;
  436. X                }
  437. X
  438. X                ld_code = '\0';
  439. X                if (strchr("+-@#", *entry)) {
  440. X                    ld_code = *entry;
  441. X                    entry++;
  442. X                }
  443. X
  444. X                n = atoi(entry);
  445. X                if (n > NUM_DIR || *dir->number[n] == '\0')
  446. X                    continue;
  447. X
  448. X                dir->q_ld[i] = ld_code;
  449. X                dir->q_num[i] = n;
  450. X                entry = strtok((char *) NULL, " \t");
  451. X            }
  452. X            ret_code = dial_win(10);
  453. X            tmode();
  454. X            break;
  455. X        case EXIT:
  456. X            pexit();
  457. X            break;
  458. X        case CLEAR_SCREEN:
  459. X            fixterm();
  460. X            erase();
  461. X            refresh();
  462. X            resetterm();
  463. X            break;
  464. X        case CHG_DIR:
  465. X            chdir(arg2);
  466. X            break;
  467. X        case HANG_UP:
  468. X            hang_up(QUIET);
  469. X            break;
  470. X        case PRINTER:
  471. X            if (status->print_status + arg1 == 1)
  472. X                lpr_toggle();
  473. X            break;
  474. X        case MODEM_BREAK:
  475. X            tty_break(fd);
  476. X            break;
  477. X        case SEND:
  478. X            do_xfer(arg1, UP_LOAD, arg2);
  479. X            break;
  480. X        case RECEIVE:
  481. X            do_xfer(arg1, DOWN_LOAD, arg2);
  482. X            break;
  483. X        case SCREEN_DUMP:
  484. X            screen_dump();
  485. X            break;
  486. X        case DATA_LOG:
  487. X            if (status->log_status + arg1 == 1) {
  488. X                if (arg1 == 1 && !strcmp(status->log_path, "NOT_DEFINED"))
  489. X                    status->log_path = str_rep(status->log_path, param->logfile);
  490. X                log_toggle();
  491. X            }
  492. X            break;
  493. X        default:
  494. X            break;
  495. X    }
  496. X    if (ret_code != 99) {
  497. X        sprintf(buf, "%d", ret_code);
  498. X        send_reply(buf);
  499. X    }
  500. X    return;
  501. X}
  502. X
  503. X/*
  504. X * Send a string back to pcomm_cmd
  505. X */
  506. X
  507. static void
  508. send_reply(s)
  509. char *s;
  510. X{
  511. X    char buf[256];
  512. X
  513. X    sprintf(buf, "%254.254s\n", s);
  514. X    if (ipc_write(status->cmd_ipc, buf, 256))
  515. X        fprintf(stderr, "Can't write to IPC\n");
  516. X    return;
  517. X}
  518. X
  519. X/*
  520. X * Put the screen in the "curses" mode
  521. X */
  522. X
  523. static void
  524. cmode()
  525. X{
  526. X    void load_vs(), st_line();
  527. X
  528. X    fixterm();
  529. X    load_vs();
  530. X    st_line("");
  531. X    return;
  532. X}
  533. X
  534. X/*
  535. X * Put the screen in the "terminal" mode
  536. X */
  537. X
  538. static void
  539. tmode()
  540. X{
  541. X    extern int fd;
  542. X    void term_mode();
  543. X
  544. X    if (fd != -1) {
  545. X        touchwin(stdscr);
  546. X        refresh();
  547. X    }
  548. X    resetterm();
  549. X    term_mode();
  550. X    return;
  551. X}
  552. X
  553. X/*
  554. X * Do the file transfers
  555. X */
  556. X
  557. static void
  558. do_xfer(type, up, files)
  559. int type, up;
  560. char *files;
  561. X{
  562. X    int n, is_batch, num_extrnl;
  563. X    char buf[256], *strcpy(), *strcat();
  564. X    void xfer_win(), xfer_ascii(), do_extrnl();
  565. X
  566. X    num_extrnl = (up == UP_LOAD) ? extrnl->up_entries : extrnl->dn_entries;
  567. X    
  568. X    is_batch = 0;
  569. X    switch(type) {
  570. X        case MODEM7:
  571. X        case YMODEM:
  572. X        case YMODEM_G:        /* built-in batch protocols */
  573. X            is_batch++;
  574. X            /* FALLTHRU */
  575. X        case XMODEM:
  576. X        case XMODEM_1k:        /* non-batch built-ins */
  577. X            cmode();
  578. X            if (up == UP_LOAD || !is_batch)
  579. X                xfer_win(files, up, type);
  580. X            else
  581. X                xfer_win("", up, type);
  582. X            tmode();
  583. X            break;
  584. X        case XASCII:        /* ascii xfer, yuck! */
  585. X            xfer_ascii(files, up);
  586. X            break;
  587. X        case EXT_1:
  588. X        case EXT_2:
  589. X        case EXT_3:        /* one of the externals */
  590. X            n = type -NUM_INTERNAL -1;
  591. X            if (n > num_extrnl)
  592. X                break;
  593. X            strcpy(buf, extrnl->command[up][n]);
  594. X                    /* see if we need to add files */
  595. X            if (extrnl->prompt[up][n] == 'Y') {
  596. X                strcat(buf, " ");
  597. X                strcat(buf, files);
  598. X            }
  599. X            do_extrnl(buf);
  600. X            break;
  601. X        default:
  602. X            break;
  603. X    }
  604. X    return;
  605. X}
  606. END_OF_FILE
  607. if test 7048 -ne `wc -c <'cmd.c'`; then
  608.     echo shar: \"'cmd.c'\" unpacked with wrong size!
  609. fi
  610. # end of 'cmd.c'
  611. fi
  612. if test -f 'd_lib.c' -a "${1}" != "-c" ; then 
  613.   echo shar: Will not clobber existing file \"'d_lib.c'\"
  614. else
  615. echo shar: Extracting \"'d_lib.c'\" \(6988 characters\)
  616. sed "s/^X//" >'d_lib.c' <<'END_OF_FILE'
  617. X/*
  618. X * Routines to manipulate the dialing directory file pcomm.dial_dir
  619. X */
  620. X
  621. X#include <stdio.h>
  622. X#include "dial_dir.h"
  623. X#include "param.h"
  624. X
  625. X/*
  626. X * Read the dialing directory.  Returns a pointer to a static area
  627. X * containing the DIAL_DIR structure.  All of the entries are created
  628. X * regardless of the number of physical entries in the file.  Element
  629. X * number zero is reserved for the "manual" entry.  All errors are fatal.
  630. X */
  631. X
  632. struct DIAL_DIR *
  633. read_dir()
  634. X{
  635. X    extern char *null_ptr;
  636. X    FILE *fp, *uid_fopen();
  637. X    int i, line, oops;
  638. X    char *str_dup(), buf[200], *temp_token, *str, *str_tok(), token[20];
  639. X    char message[80], *sep, *findfile();
  640. X    static struct DIAL_DIR d;
  641. X    void error_win();
  642. X
  643. X    if ((d.d_path = findfile("pcomm.dial_dir")) == NULL)
  644. X        error_win(1, "Support file \"pcomm.dial_dir\" is missing", "or no read permission");
  645. X
  646. X    if (!(fp = uid_fopen(d.d_path, "r"))) {
  647. X        sprintf(buf, "\"%s\" for read", d.d_path);
  648. X        error_win(1, "Can't open dialing directory file", buf);
  649. X    }
  650. X
  651. X    sep = ";;---;;\n";
  652. X    line = 0;
  653. X    oops = 0;
  654. X    while (fgets(buf, 200, fp) != NULL) {
  655. X        line++;
  656. X        if (line > NUM_DIR)
  657. X            break;
  658. X                    /* get the token */
  659. X        if (!(temp_token = str_tok(buf, '='))) {
  660. X            sprintf(message, "is missing a token at line %d", line);
  661. X            oops++;
  662. X            break;
  663. X        }
  664. X        /*
  665. X         * Parse the rest of the line.  This is similar to using
  666. X         * the "real" strtok() function, but this version returns
  667. X         * a pointer to NULL if the token is missing.  Note the use
  668. X         * of the array of field separators.
  669. X         */
  670. X        for (i=0; i<8; i++) {
  671. X            if (!(str = str_tok((char *) NULL, sep[i]))) {
  672. X                sprintf(message, "is missing a parameter at line %d", line);
  673. X                oops++;
  674. X                break;
  675. X            }
  676. X            switch (i) {
  677. X                case 0:
  678. X                    d.name[line] = str_dup(str);
  679. X                    break;
  680. X                case 1:
  681. X                    d.number[line] = str_dup(str);
  682. X                    break;
  683. X                case 2:
  684. X                    d.baud[line] = (unsigned int) atoi(str);
  685. X                    break;
  686. X                case 3:
  687. X                    d.parity[line] = *str;
  688. X                    break;
  689. X                case 4:
  690. X                    d.data_bits[line] = atoi(str);
  691. X                    break;
  692. X                case 5:
  693. X                    d.stop_bits[line] = atoi(str);
  694. X                    break;
  695. X                case 6:
  696. X                    d.duplex[line] = *str;
  697. X                    break;
  698. X                case 7:
  699. X                    d.aux[line] = str_dup(str);
  700. X                    break;
  701. X            }
  702. X        }
  703. X        if (oops)
  704. X            break;
  705. X                    /* sanity checking */
  706. X        sprintf(token, "DIR_%d", line);
  707. X        if (strcmp(temp_token, token)) {
  708. X            sprintf(message, "is corrupted at line %d", line);
  709. X            oops++;
  710. X            break;
  711. X        }
  712. X    }
  713. X    fclose(fp);
  714. X
  715. X    if (oops) {
  716. X        sprintf(buf, "Dialing directory file \"%s\"", d.d_path);
  717. X        error_win(1, buf, message);
  718. X    }
  719. X    d.d_entries = line;
  720. X                    /* if empty database */
  721. X    if (!line) {
  722. X        sprintf(buf, "Dialing directory file \"%s\"", d.d_path);
  723. X        error_win(0, buf, "has no data");
  724. X    }
  725. X                    /* fill in the rest with defaults */
  726. X    for (i=line+1; i<=NUM_DIR; i++) {
  727. X        d.name[i] = null_ptr;
  728. X        d.number[i] = null_ptr;
  729. X        d.baud[i] = param->d_baud;
  730. X        d.parity[i] = param->d_parity;
  731. X        d.data_bits[i] = param->d_data_bits;
  732. X        d.stop_bits[i] = param->d_stop_bits;
  733. X        d.duplex[i] = *param->d_duplex;
  734. X        d.aux[i] = null_ptr;
  735. X    }
  736. X                    /* create an empty "manual" entry */
  737. X    d.name[0] = null_ptr;
  738. X    d.number[0] = null_ptr;
  739. X    d.baud[0] = param->d_baud;
  740. X    d.parity[0] = param->d_parity;
  741. X    d.data_bits[0] = param->d_data_bits;
  742. X    d.stop_bits[0] = param->d_stop_bits;
  743. X    d.duplex[0] = *param->d_duplex;
  744. X    d.aux[0] = null_ptr;
  745. X                    /* create an empty queue */
  746. X    for (i=0; i<NUM_QUEUE; i++) {
  747. X        d.q_ld[i] = '\0';
  748. X        d.q_num[i] = -1;
  749. X    }
  750. X                    /* the start up d_cur is 0 */
  751. X    d.d_cur = 0;
  752. X    return(&d);
  753. X}
  754. X
  755. X/*
  756. X * Update a dialing directory entry.  Update only the one entry asked for,
  757. X * not the entire image in memory.  If the new entry is beyond the end of
  758. X * the physical file, then fill in the holes, and update "dir->d_entries".
  759. X * A non-zero return code means a non-fatal error.
  760. X */
  761. X
  762. int
  763. up_dir(entry)
  764. int entry;
  765. X{
  766. X    FILE *fp_in, *fp_out, *uid_fopen();
  767. X    int i;
  768. X    char *temp[NUM_DIR+1], buf[200], *str_dup(), *str_rep();
  769. X    void error_win(), free_ptr();
  770. X
  771. X                    /* open for read */
  772. X    if (!(fp_in = uid_fopen(dir->d_path, "r"))) {
  773. X        sprintf(buf, "\"%s\" for read", dir->d_path);
  774. X        error_win(1, "Can't open dialing directory file", buf);
  775. X    }
  776. X                    /* read in a temporary version */
  777. X    i = 0;
  778. X    while (fgets(buf, 200, fp_in) != NULL)
  779. X        temp[++i] = str_dup(buf);
  780. X
  781. X    fclose(fp_in);
  782. X                    /* alter only 1 entry */
  783. X    sprintf(buf, "DIR_%d=%s;%s;%d-%c-%d-%d;%c;%s\n", entry,
  784. X     dir->name[entry], dir->number[entry], dir->baud[entry],
  785. X     dir->parity[entry], dir->data_bits[entry], dir->stop_bits[entry],
  786. X     dir->duplex[entry], dir->aux[entry]);
  787. X
  788. X    if (entry <= dir->d_entries)
  789. X        temp[entry] = str_rep(temp[entry], buf);
  790. X    else
  791. X        temp[entry] = str_dup(buf);
  792. X
  793. X                    /* fill in holes if beyond end */
  794. X    if (entry > dir->d_entries+1) {
  795. X        for (i=dir->d_entries+1; i<entry; i++) {
  796. X            sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i,
  797. X             param->d_baud, param->d_parity, param->d_data_bits,
  798. X             param->d_stop_bits, *param->d_duplex);
  799. X            temp[i] = str_dup(buf);
  800. X        }
  801. X    }
  802. X                    /* update "dir->d_entries" */
  803. X    if (entry > dir->d_entries)
  804. X        dir->d_entries = entry;
  805. X
  806. X                    /* open for write */
  807. X    if (!(fp_out = uid_fopen(dir->d_path, "w"))) {
  808. X        for (i=1; i<=dir->d_entries; i++)
  809. X            free_ptr(temp[i]);
  810. X        sprintf(buf, "\"%s\"", dir->d_path);
  811. X        error_win(0, "No write permission on dialing directory file", buf);
  812. X        return(1);
  813. X    }
  814. X                    /* put it back */
  815. X    for (i=1; i<=dir->d_entries; i++) {
  816. X        fputs(temp[i], fp_out);
  817. X        free_ptr(temp[i]);
  818. X    }
  819. X
  820. X    fclose(fp_out);
  821. X    return(0);
  822. X}
  823. X
  824. X/*
  825. X * Delete a range of dialing directory entries.  Actually, just copies
  826. X * default (empty) entries in place of deleted entries.  However, it will
  827. X * shrink the file if deletions occur at the physical EOF.  A non-zero
  828. X * return code means a non-fatal error.
  829. X */
  830. X
  831. int
  832. del_dir(first, last)
  833. int first, last;
  834. X{
  835. X    FILE *fp_in, *fp_out, *uid_fopen();
  836. X    int i;
  837. X    char *temp[NUM_DIR+1], buf[200], *str_dup(), *str_rep();
  838. X    void error_win(), free_ptr();
  839. X                    /* sanity checking */
  840. X    if (first > dir->d_entries)
  841. X        return(0);
  842. X    if (last > dir->d_entries)
  843. X        last = dir->d_entries;
  844. X
  845. X                    /* open for read */
  846. X    if (!(fp_in = uid_fopen(dir->d_path, "r"))) {
  847. X        sprintf(buf, "\"%s\" for read", dir->d_path);
  848. X        error_win(1, "Can't open dialing directory file", buf);
  849. X    }
  850. X                    /* read in a temporary version */
  851. X    i = 0;
  852. X    while (fgets(buf, 200, fp_in) != NULL)
  853. X        temp[++i] = str_dup(buf);
  854. X
  855. X    fclose(fp_in);
  856. X                    /* delete the range of values */
  857. X    for (i=first; i<=last; i++) {
  858. X        sprintf(buf, "DIR_%d=;;%d-%c-%d-%d;%c;\n", i, param->d_baud,
  859. X         param->d_parity, param->d_data_bits, param->d_stop_bits,
  860. X         *param->d_duplex);
  861. X        temp[i] = str_rep(temp[i], buf);
  862. X    }
  863. X                    /* shrink the file? */
  864. X    if (last >= dir->d_entries) {
  865. X        for (i=first; i<=last; i++)
  866. X            free_ptr(temp[i]);
  867. X        dir->d_entries = first-1;
  868. X    }
  869. X                    /* open for write */
  870. X    if (!(fp_out = uid_fopen(dir->d_path, "w"))) {
  871. X        for (i=1; i<=dir->d_entries; i++)
  872. X            free_ptr(temp[i]);
  873. X        sprintf(buf, "\"%s\"", dir->d_path);
  874. X        error_win(0, "No write permission on dialing directory file", buf);
  875. X        return(1);
  876. X    }
  877. X                    /* put it all back */
  878. X    for (i=1; i<=dir->d_entries; i++) {
  879. X        fputs(temp[i], fp_out);
  880. X        free_ptr(temp[i]);
  881. X    }
  882. X
  883. X    fclose(fp_out);
  884. X    return(0);
  885. X}
  886. END_OF_FILE
  887. if test 6988 -ne `wc -c <'d_lib.c'`; then
  888.     echo shar: \"'d_lib.c'\" unpacked with wrong size!
  889. fi
  890. # end of 'd_lib.c'
  891. fi
  892. if test -f 'd_menu.c' -a "${1}" != "-c" ; then 
  893.   echo shar: Will not clobber existing file \"'d_menu.c'\"
  894. else
  895. echo shar: Extracting \"'d_menu.c'\" \(7134 characters\)
  896. sed "s/^X//" >'d_menu.c' <<'END_OF_FILE'
  897. X/*
  898. X * Routines for the dialing directory menu.
  899. X */
  900. X
  901. X#include <stdio.h>
  902. X#include <curses.h>
  903. X#include "config.h"
  904. X#include "dial_dir.h"
  905. X#include "misc.h"
  906. X#include "param.h"
  907. X
  908. static int current = 1;
  909. static void dir_scroll(), active_ld(), disp_ld();
  910. X
  911. X/*
  912. X * Display the dialing directory and prompt for options.  A non-zero return
  913. X * code means we're ready to dial.
  914. X */
  915. X
  916. int
  917. dial_menu()
  918. X{
  919. X    extern int xmc;
  920. X    WINDOW *dm_win, *newwin();
  921. X    char buf[5], ld_code;
  922. X    int ans, start, needs_repair, count, x, y, i, ret_code;
  923. X    void print_dir(), st_line();
  924. X
  925. X    touchwin(stdscr);
  926. X    refresh();
  927. X    st_line("");
  928. X
  929. X    dm_win = newwin(22, 78, 1, 1);
  930. X    mvwattrstr(dm_win, 1, 20, A_BOLD, "D I A L I N G       D I R E C T O R Y");
  931. X    horizontal(dm_win, 2, 0, 78);
  932. X    mvwattrstr(dm_win, 3, 0, A_STANDOUT, "           Name                   Number        Baud P D S Dpx  Auxiliary     ");
  933. X                    /* show 10 entries */
  934. X    dir_scroll(dm_win, current);
  935. X
  936. X    mvwaddstr(dm_win, 15, 4, "==>");
  937. X    mvwattrch(dm_win, 15, 14, A_BOLD, 'R');
  938. X    waddstr(dm_win, " Revise");
  939. X    mvwattrch(dm_win, 15, 34, A_BOLD, 'M');
  940. X    waddstr(dm_win, " Manual Dialing");
  941. X    mvwaddstr(dm_win, 15, 55, "Entry to Dial");
  942. X
  943. X    mvwattrch(dm_win, 16, 14, A_BOLD, 'P');
  944. X    waddstr(dm_win, " LD Codes");
  945. X    mvwattrch(dm_win, 16, 34, A_BOLD, 'D');
  946. X    waddstr(dm_win, " Delete Entry");
  947. X    mvwattrstr(dm_win, 16, 55, A_BOLD, "<CR>");
  948. X    waddstr(dm_win, " Scroll Down");
  949. X
  950. X#ifdef OLDCURSES
  951. X    mvwattrstr(dm_win, 17, 14, A_BOLD, "U/N");
  952. X#else /* OLDCURSES */
  953. X    mvwattrstr(dm_win, 17, 14, A_BOLD, "<up>/<down>");
  954. X#endif /* OLDCURSES */
  955. X    waddstr(dm_win, " Page");
  956. X    mvwattrch(dm_win, 17, 34, A_BOLD, 'L');
  957. X    waddstr(dm_win, " Print Entries");
  958. X    mvwattrstr(dm_win, 17, 55, A_BOLD, "<ESC>");
  959. X    waddstr(dm_win, " Exit");
  960. X
  961. X    mvwaddstr(dm_win, 19, 4, "LD Codes Active:");
  962. X                    /* show which LD codes are active */
  963. X    active_ld(dm_win);
  964. X
  965. X    box(dm_win, VERT, HORZ);
  966. X    y = 15;
  967. X    x = 8;
  968. X    wmove(dm_win, 15, 8);
  969. X    wrefresh(dm_win);
  970. X
  971. X#ifndef OLDCURSES
  972. X    keypad(dm_win, TRUE);
  973. X#endif /* OLDCURSES */
  974. X                    /* prompt for options */
  975. X    count = 0;
  976. X    ld_code = '\0';
  977. X    ret_code = 0;
  978. X    do {
  979. X        needs_repair = 0;
  980. X        ans = wgetch(dm_win);
  981. X                    /* get an entry number */
  982. X        if (ans >= '0' && ans <= '9') {
  983. X            if (count > 2) {
  984. X                beep();
  985. X                continue;
  986. X            }
  987. X            buf[count] = (char) ans;
  988. X            waddch(dm_win, (chtype) ans);
  989. X            wrefresh(dm_win);
  990. X            count++;
  991. X            continue;
  992. X        }
  993. X        switch (ans) {
  994. X            case DEL:
  995. X            case BS:    /* do our own backspace */
  996. X                if (!count) {
  997. X                    beep();
  998. X                    break;
  999. X                }
  1000. X                count--;
  1001. X                if (!count)
  1002. X                    ld_code = '\0';
  1003. X                buf[count] = '\0';
  1004. X                getyx(dm_win, y, x);
  1005. X                x--;
  1006. X                wmove(dm_win, y, x);
  1007. X                waddch(dm_win, (chtype) ' ');
  1008. X                wmove(dm_win, y, x);
  1009. X                wrefresh(dm_win);
  1010. X                break;
  1011. X#ifndef OLDCURSES
  1012. X            case KEY_UP:
  1013. X#endif /* OLDCURSES */
  1014. X            case 'u':
  1015. X            case 'U':    /* up arrow key */
  1016. X                if (current == 1) {
  1017. X                    beep();
  1018. X                    break;
  1019. X                }
  1020. X                start = current - 10;
  1021. X                if (start < 1)
  1022. X                    start = 1;
  1023. X                current = start;
  1024. X                dir_scroll(dm_win, start);
  1025. X                break;
  1026. X#ifndef OLDCURSES
  1027. X            case KEY_DOWN:
  1028. X            case '\n':
  1029. X#endif /* OLDCURSES */
  1030. X            case 'n':
  1031. X            case 'N':    /* down arrow key */
  1032. X                if (current == NUM_DIR-9) {
  1033. X                    beep();
  1034. X                    break;
  1035. X                }
  1036. X                start = current + 10;
  1037. X                if (start > NUM_DIR-9)
  1038. X                    start = NUM_DIR-9;
  1039. X                current = start;
  1040. X                dir_scroll(dm_win, start);
  1041. X                break;
  1042. X            case '\r':    /* <CR> key */
  1043. X                if (!count) {
  1044. X                    if (current == NUM_DIR-9) {
  1045. X                        beep();
  1046. X                        break;
  1047. X                    }
  1048. X                    current++;
  1049. X                    if (current > NUM_DIR-9)
  1050. X                        current = NUM_DIR-9;
  1051. X                    dir_scroll(dm_win, current);
  1052. X                }
  1053. X                /*
  1054. X                 * The <CR> is used for the scroll-down-one-line
  1055. X                 * function, and to terminate numeric input.
  1056. X                 */
  1057. X                else {
  1058. X                    buf[count] = '\0';
  1059. X                    i = atoi(buf);
  1060. X                    if (!i || i > NUM_DIR) {
  1061. X                        beep();
  1062. X                        mvwaddstr(dm_win, 15, 8, "   ");
  1063. X                        x = 8;
  1064. X                        count = 0;
  1065. X                        break;
  1066. X                    }
  1067. X                    dir->q_ld[0] = ld_code;
  1068. X                    dir->q_num[0] = i;
  1069. X                    dir->d_cur = i;
  1070. X
  1071. X                    /* end of queue marker */
  1072. X                    dir->q_num[1] = -1;
  1073. X
  1074. X                    ret_code++;
  1075. X                    break;
  1076. X                }
  1077. X                break;
  1078. X            case 'r':
  1079. X            case 'R':    /* revise */
  1080. X                if (revise()) {
  1081. X                    active_ld(dm_win);
  1082. X                    dir_scroll(dm_win, current);
  1083. X                }
  1084. X                touchwin(dm_win);
  1085. X                break;
  1086. X            case 'p':    /* display LD codes */
  1087. X            case 'P':
  1088. X                disp_ld();
  1089. X                touchwin(dm_win);
  1090. X                needs_repair++;
  1091. X                break;
  1092. X            case 'd':
  1093. X            case 'D':    /* delete a range of entries */
  1094. X                if (delete())
  1095. X                    dir_scroll(dm_win, current);
  1096. X                touchwin(dm_win);
  1097. X                break;
  1098. X            case 'm':
  1099. X            case 'M':    /* manual dial */
  1100. X                if (manual()) {
  1101. X                    ret_code++;
  1102. X                    break;
  1103. X                }
  1104. X                touchwin(dm_win);
  1105. X                needs_repair++;
  1106. X                break;
  1107. X            case 'l':
  1108. X            case 'L':    /* print the entries */
  1109. X                print_dir();
  1110. X                touchwin(dm_win);
  1111. X                needs_repair++;
  1112. X                break;
  1113. X            case '+':    /* LD codes */
  1114. X            case '-':
  1115. X            case '@':
  1116. X            case '#':
  1117. X                waddch(dm_win, (chtype) ans);
  1118. X                wrefresh(dm_win);
  1119. X                ld_code = (char) ans;
  1120. X                continue;
  1121. X            case ESC:    /* <ESC> key (exit) */
  1122. X                break;
  1123. X            default:
  1124. X                beep();
  1125. X        }
  1126. X        if (ret_code)
  1127. X            break;
  1128. X                    /* magic cookie terminal? */
  1129. X        if (xmc > 0 && needs_repair) {
  1130. X            clear_line(dm_win, 1, 0, FALSE);
  1131. X            clear_line(dm_win, 3, 0, FALSE);
  1132. X            wrefresh(dm_win);
  1133. X            mvwattrstr(dm_win, 1, 20, A_BOLD, "D I A L I N G       D I R E C T O R Y");
  1134. X            mvwattrstr(dm_win, 3, 0, A_STANDOUT, "           Name                   Number        Baud P D S Dpx  Auxiliary     ");
  1135. X            box(dm_win, VERT, HORZ);
  1136. X        }
  1137. X        wmove(dm_win, y, x);
  1138. X        wrefresh(dm_win);
  1139. X    } while (ans != ESC);
  1140. X
  1141. X    werase(dm_win);
  1142. X    wrefresh(dm_win);
  1143. X    delwin(dm_win);
  1144. X    if (ret_code) {
  1145. X        touchwin(stdscr);
  1146. X        refresh();
  1147. X    }
  1148. X    return(ret_code);
  1149. X}
  1150. X
  1151. X/*
  1152. X * Scroll the dialing directory.  Actually, we're not doing a real scroll
  1153. X * function on the screen, we're just repainting 10 lines.
  1154. X */
  1155. X
  1156. static void
  1157. dir_scroll(win, start)
  1158. WINDOW *win;
  1159. int start;
  1160. X{
  1161. X    int i;
  1162. X
  1163. X    wmove(win, 4, 0);
  1164. X    for (i=start; i<start+10; i++)
  1165. X        wprintw(win,
  1166. X         "%4d- %-20.20s %18.18s  %5d-%c-%d-%d  %c  %-14.14s\n", i,
  1167. X         dir->name[i], dir->number[i], dir->baud[i], dir->parity[i],
  1168. X         dir->data_bits[i], dir->stop_bits[i], dir->duplex[i],
  1169. X         dir->aux[i]);
  1170. X    box(win, VERT, HORZ);
  1171. X    return;
  1172. X}
  1173. X
  1174. X/*
  1175. X * Display the Long Distance codes.  Press any key to continue.
  1176. X */
  1177. X
  1178. static void
  1179. disp_ld()
  1180. X{
  1181. X    WINDOW *ld_win, *newwin();
  1182. X
  1183. X    ld_win = newwin(12, 30, 0, 0);
  1184. X    mvwaddstr(ld_win, 1, 5, "Long Distance Codes\n");
  1185. X    horizontal(ld_win, 2, 0, 30);
  1186. X    mvwprintw(ld_win, 3, 2, "+ %-20.20s", param->ld_plus);
  1187. X    mvwprintw(ld_win, 5, 2, "- %-20.20s", param->ld_minus);
  1188. X    mvwprintw(ld_win, 7, 2, "@ %-20.20s", param->ld_at);
  1189. X    mvwprintw(ld_win, 9, 2, "# %-20.20s", param->ld_pound);
  1190. X    box(ld_win, VERT, HORZ);
  1191. X
  1192. X    mvwaddstr(ld_win, 11, 8, " Press any key ");
  1193. X    wmove(ld_win, 11, 29);
  1194. X    wrefresh(ld_win);
  1195. X    wgetch(ld_win);
  1196. X                    /* it overlaps, so erase it */
  1197. X    werase(ld_win);
  1198. X    wrefresh(ld_win);
  1199. X    delwin(ld_win);
  1200. X    return;
  1201. X}
  1202. X
  1203. X/*
  1204. X * Display which of the Long Distance codes are active.
  1205. X */
  1206. X
  1207. static void
  1208. active_ld(win)
  1209. WINDOW *win;
  1210. X{
  1211. X    mvwaddstr(win, 19, 21, "        ");
  1212. X    wmove(win, 19, 21);
  1213. X                    /* a NULL means it's not active */
  1214. X    if (*param->ld_plus != '\0')
  1215. X        waddstr(win, "+ ");
  1216. X    if (*param->ld_minus != '\0')
  1217. X        waddstr(win, "- ");
  1218. X    if (*param->ld_at != '\0')
  1219. X        waddstr(win, "@ ");
  1220. X    if (*param->ld_pound != '\0')
  1221. X        waddstr(win, "# ");
  1222. X    return;
  1223. X}
  1224. END_OF_FILE
  1225. if test 7134 -ne `wc -c <'d_menu.c'`; then
  1226.     echo shar: \"'d_menu.c'\" unpacked with wrong size!
  1227. fi
  1228. # end of 'd_menu.c'
  1229. fi
  1230. if test -f 'input.c' -a "${1}" != "-c" ; then 
  1231.   echo shar: Will not clobber existing file \"'input.c'\"
  1232. else
  1233. echo shar: Extracting \"'input.c'\" \(7330 characters\)
  1234. sed "s/^X//" >'input.c' <<'END_OF_FILE'
  1235. X/*
  1236. X * The input routines.
  1237. X */
  1238. X
  1239. X#include <stdio.h>
  1240. X#include "config.h"
  1241. X#include "misc.h"
  1242. X#include "param.h"
  1243. X#include "status.h"
  1244. X#include "vcs.h"
  1245. X
  1246. static int add_lf;
  1247. static void vs_scroll();
  1248. static FILE *logfp = (FILE *) NULL;
  1249. static FILE *lprfp = (FILE *) NULL;
  1250. X
  1251. X/*
  1252. X * Read the serial port and write the characters to the screen.  Watch
  1253. X * for changes in status structure to toggle the fancy options.
  1254. X * Writes the characters received to a virtual screen buffer.
  1255. X */
  1256. X
  1257. void
  1258. tty_input()
  1259. X{
  1260. X    extern int fd;
  1261. X    register int in_cnt, out_cnt;
  1262. X    char c, *bufp, in_buf[INPUT_BUF], out_buf[INPUT_BUF*2];
  1263. X    void vs_putchar();
  1264. X
  1265. X                    /* here we go... */
  1266. X    if ((in_cnt = read(fd, in_buf, INPUT_BUF)) <= 0)
  1267. X        return;
  1268. X
  1269. X    /*
  1270. X     * If we're doing a script, send a duplicate down the pipe
  1271. X     */
  1272. X    if (status->dup_fd != -1)
  1273. X        write(status->dup_fd, in_buf, in_cnt);
  1274. X
  1275. X                    /* "peel" the buffer one at a time */
  1276. X    out_cnt = 0;
  1277. X    bufp = in_buf;
  1278. X    add_lf = !strcmp(param->cr_in, "CR/LF");
  1279. X    while (--in_cnt >= 0) {
  1280. X        c = *bufp++ & 0xff;
  1281. X                    /* send to logfile? */
  1282. X        if (status->log_status) {
  1283. X            if (c == '\r' && add_lf)
  1284. X                putc('\n', logfp);
  1285. X                    /* no carriage returns in logfile */
  1286. X            if (c != '\r')
  1287. X                putc(c, logfp);
  1288. X        }
  1289. X                    /* send to printer too? */
  1290. X        if (status->print_status)
  1291. X            putc(c, lprfp);
  1292. X
  1293. X                    /* put a char in virtual screen */
  1294. X        vs_putchar(c);
  1295. X
  1296. X                    /* build the output buffer */
  1297. X        out_buf[out_cnt++] = c;
  1298. X        if (c == '\r' && add_lf)
  1299. X            out_buf[out_cnt++] = '\n';
  1300. X
  1301. X                    /* output in smaller chunks */
  1302. X        if (out_cnt >= OUTPUT_BUF) {
  1303. X            write(1, out_buf, out_cnt);
  1304. X            out_cnt = 0;
  1305. X        }
  1306. X    }
  1307. X    if (out_cnt)
  1308. X        write(1, out_buf, out_cnt);
  1309. X    
  1310. X    return;
  1311. X}
  1312. X
  1313. X/*
  1314. X * Put a character in the virtual screen.  This routine saves incoming
  1315. X * characters in a two dimensional buffer designed to mimic the real
  1316. X * screen.
  1317. X */
  1318. X
  1319. void
  1320. vs_putchar(c)
  1321. char c;
  1322. X{
  1323. X    register int i;
  1324. X    extern int vcs_param[NUM_VCS][5], vcs_opt[NUM_VCS][10];
  1325. X    char *memset();
  1326. X    int tab_stop;
  1327. X
  1328. X    switch (vcs_filter(c)) {
  1329. X        case MAYBE:        /* wait and see... */
  1330. X            break;
  1331. X        case 256+HOME:        /* home virtual screen "cursor" */
  1332. X            status->row = 0;
  1333. X            status->col = 0;
  1334. X            break;
  1335. X        case 256+CLR_EOL:    /* clear to end of line */
  1336. X            memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
  1337. X            status->col = status->max_col -1;
  1338. X            break;
  1339. X        case 256+CLR_EOS:    /* clear to end of screen */
  1340. X            memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
  1341. X            for (i=status->row+1; i<status->max_row; i++)
  1342. X                memset(status->vs[i], ' ', status->max_col);
  1343. X            status->row = status->max_row -1;
  1344. X            status->col = status->max_col -1;
  1345. X            break;
  1346. X        case 256+CLEAR:        /* clear all and home "cursor" */
  1347. X            for (i=0; i<status->max_row; i++)
  1348. X                memset(status->vs[i], ' ', status->max_col);
  1349. X            status->row = 0;
  1350. X            status->col = 0;
  1351. X            break;
  1352. X        case 256+MV_UP:        /* move "cursor" up */
  1353. X            status->row--;
  1354. X            if (status->row < 0)
  1355. X                status->row = 0;
  1356. X            break;
  1357. X        case 256+MV_DOWN:    /* move "cursor" down */
  1358. X            status->row++;
  1359. X            if (status->row >= status->max_row)
  1360. X                status->row = status->max_row -1;
  1361. X            break;
  1362. X        case 256+MV_RIGHT:    /* move "cursor" right */
  1363. X            status->col++;
  1364. X            if (status->col >= status->max_col)
  1365. X                status->col = status->max_col -1;
  1366. X            break;
  1367. X        case 256+MV_LEFT:    /* move "cursor" left */
  1368. X        case BS:        /* non destructive back space */
  1369. X            status->col--;
  1370. X            if (status->col < 0)
  1371. X                status->col = 0;
  1372. X            break;
  1373. X        case 256+MV_DIRECT:    /* direct cursor movement */
  1374. X            status->row = vcs_param[MV_DIRECT][0];
  1375. X            status->col = vcs_param[MV_DIRECT][1];
  1376. X
  1377. X                    /* if "add one" and "decimal" */
  1378. X            if (vcs_opt[MV_DIRECT][0] && vcs_opt[MV_DIRECT][1]) {
  1379. X                status->row--;
  1380. X                status->col--;
  1381. X            }
  1382. X                    /* if "character" */
  1383. X            if (vcs_opt[MV_DIRECT][2]) {
  1384. X                    /* if "add offset" */
  1385. X                if (vcs_opt[MV_DIRECT][3]) {
  1386. X                    status->row -= vcs_opt[MV_DIRECT][5];
  1387. X                    status->col -= vcs_opt[MV_DIRECT][5];
  1388. X                }
  1389. X                    /* if "subtract offset" */
  1390. X                if (vcs_opt[MV_DIRECT][4]) {
  1391. X                    status->row += vcs_opt[MV_DIRECT][5];
  1392. X                    status->col += vcs_opt[MV_DIRECT][5];
  1393. X                }
  1394. X                status->row--;
  1395. X                status->col--;
  1396. X            }
  1397. X                    /* sanity check... */
  1398. X            if (status->row < 0)
  1399. X                status->row = 0;
  1400. X            if (status->col < 0)
  1401. X                status->col = 0;
  1402. X            if (status->row >= status->max_row)
  1403. X                status->row = status->max_row -1;
  1404. X            if (status->col >= status->max_col)
  1405. X                status->col = status->max_col -1;
  1406. X            break;
  1407. X        case 0:
  1408. X        case 7:            /* skip NULL and "bell" character */
  1409. X            break;
  1410. X        case '\t':        /* tab character */
  1411. X            tab_stop = status->col + 8 - (status->col % 8);
  1412. X                    /* if wrap around */
  1413. X            if (tab_stop >= status->max_col) {
  1414. X                    /* spaces up to eol */
  1415. X                memset(&status->vs[status->row][status->col], ' ', status->max_col - status->col);
  1416. X                status->row++;
  1417. X                if (status->row >= status->max_row)
  1418. X                    vs_scroll();
  1419. X
  1420. X                    /* the remainder of the tab */
  1421. X                status->col = tab_stop - status->max_col;
  1422. X            }
  1423. X            else {
  1424. X                memset(&status->vs[status->row][status->col], ' ', tab_stop - status->col);
  1425. X                status->col = tab_stop;
  1426. X            }
  1427. X            break;
  1428. X        case '\r':        /* carriage return */
  1429. X            status->col = 0;
  1430. X            if (!add_lf)
  1431. X                break;
  1432. X            /* FALLTHRU */
  1433. X        case '\n':        /* line feed */
  1434. X            status->row++;
  1435. X            if (status->row >= status->max_row)
  1436. X                vs_scroll();
  1437. X            break;
  1438. X        default:        /* a normal character */
  1439. X            status->vs[status->row][status->col] = c;
  1440. X            status->col++;
  1441. X                    /* wrap around */
  1442. X            if (status->col >= status->max_col) {
  1443. X                status->col = 0;
  1444. X                status->row++;
  1445. X                if (status->row >= status->max_row)
  1446. X                    vs_scroll();
  1447. X            }
  1448. X            break;
  1449. X    }
  1450. X    return;
  1451. X}
  1452. X
  1453. X/*
  1454. X * Do a software scroll on the virtual screen.  Does not alter the
  1455. X * "col" variable.
  1456. X */
  1457. X
  1458. static void
  1459. vs_scroll()
  1460. X{
  1461. X    char *memset();
  1462. X                    /* move 'em up 1 line */
  1463. X#ifdef MEMMOVE
  1464. X    MEMMOVE(status->vs[0], status->vs[1], (status->max_row -1) * MAX_COL);
  1465. X#else /* MEMMOVE */
  1466. X    register int i;
  1467. X    char *strcpy();
  1468. X
  1469. X    for (i=0; i<status->max_row-1; i++)
  1470. X        strcpy(status->vs[i], status->vs[i+1]);
  1471. X#endif /* MEMMOVE */
  1472. X                    /* clear the bottom line */
  1473. X    memset(status->vs[status->max_row-1], ' ', status->max_col);
  1474. X
  1475. X    status->row = status->max_row -1;
  1476. X    return;
  1477. X}
  1478. X
  1479. X/*
  1480. X * A short-cut for charcters that are "echoed" in the half duplex
  1481. X * mode.  Since the TTY driver is putting the characters on the
  1482. X * screen (rather than being sent back by the modem), they need
  1483. X * to be faked as modem input.
  1484. X */
  1485. X
  1486. void
  1487. half_duplex(c)
  1488. char c;
  1489. X{
  1490. X                    /* send to logfile? */
  1491. X    if (status->log_status) {
  1492. X        if (c == '\r' && add_lf)
  1493. X            putc('\n', logfp);
  1494. X                    /* no carriage returns in logfile */
  1495. X        if (c != '\r')
  1496. X            putc(c, logfp);
  1497. X    }
  1498. X                    /* send to printer too? */
  1499. X    if (status->print_status)
  1500. X        putc(c, lprfp);
  1501. X
  1502. X                    /* put a char in virtual screen */
  1503. X    vs_putchar(c);
  1504. X    return;
  1505. X}
  1506. X
  1507. X/*
  1508. X * Toggle the printer log
  1509. X */
  1510. X
  1511. void
  1512. lpr_toggle()
  1513. X{
  1514. X    FILE *n_popen();
  1515. X
  1516. X    status->print_status = status->print_status ? 0 : 1;
  1517. X
  1518. X    if (status->print_status && lprfp == NULL) {
  1519. X        if (!(lprfp = n_popen(LPR, "w")))
  1520. X            status->print_status = 0;
  1521. X    }
  1522. X
  1523. X    if (!status->print_status && lprfp != NULL) {
  1524. X        putc('\f', lprfp);
  1525. X        n_pclose(lprfp);
  1526. X        lprfp = (FILE *) NULL;
  1527. X    }
  1528. X    return;
  1529. X}
  1530. X
  1531. X/*
  1532. X * Toggle the data log
  1533. X */
  1534. X
  1535. void
  1536. log_toggle()
  1537. X{
  1538. X    FILE *uid_fopen();
  1539. X
  1540. X    status->log_status = status->log_status ? 0 : 1;
  1541. X
  1542. X    if (status->log_status && logfp == NULL) {
  1543. X        if (!(logfp = uid_fopen(status->log_path, "a")))
  1544. X            status->log_status = 0;
  1545. X    }
  1546. X
  1547. X    if (!status->log_status && logfp != NULL) {
  1548. X        fclose(logfp);
  1549. X        logfp = (FILE *) NULL;
  1550. X    }
  1551. X    return;
  1552. X}
  1553. END_OF_FILE
  1554. if test 7330 -ne `wc -c <'input.c'`; then
  1555.     echo shar: \"'input.c'\" unpacked with wrong size!
  1556. fi
  1557. # end of 'input.c'
  1558. fi
  1559. if test -f 'p_lib.c' -a "${1}" != "-c" ; then 
  1560.   echo shar: Will not clobber existing file \"'p_lib.c'\"
  1561. else
  1562. echo shar: Extracting \"'p_lib.c'\" \(7341 characters\)
  1563. sed "s/^X//" >'p_lib.c' <<'END_OF_FILE'
  1564. X/*
  1565. X * Routines to manipulate the pcomm.param file.
  1566. X */
  1567. X
  1568. X#include <stdio.h>
  1569. X#include "param.h"
  1570. X
  1571. X/*
  1572. X * Read the parameter structure from the pcomm.param file.  Returns a
  1573. X * pointer to a static area containing the PARAM structure.  All errors
  1574. X * are fatal.
  1575. X */
  1576. X
  1577. struct PARAM *
  1578. read_param()
  1579. X{
  1580. X    FILE *fp, *uid_fopen();
  1581. X    int i, line, oops;
  1582. X    char buf[200], *temp_token, *str, *str_dup(), *findfile();
  1583. X    char message[80], *str_tok();
  1584. X    static char *token[NUM_PARAM] = {"D_BAUD", "D_PARITY",
  1585. X    "D_DATA_BITS", "D_STOP_BITS", "HOT_KEY", "ASCII_HOT", "D_DUPLEX",
  1586. X    "FLOW_CTRL", "CR_IN", "CR_OUT", "LOGFILE", "DUMPFILE", "STRIP",
  1587. X    "PAUSE_CHAR", "CR_CHAR", "CTRL_CHAR", "ESC_CHAR", "BRK_CHAR",
  1588. X    "ABORT", "C_DELAY", "R_DELAY", "LOCAL_ECHO", "EXPAND", "CR_DELAY",
  1589. X    "PACE", "CR_UP", "LF_UP", "TIMER", "CR_DN", "LF_DN", "LD_PLUS",
  1590. X    "LD_MINUS", "LD_AT", "LD_POUND", "MAC_1", "MAC_2", "MAC_3",
  1591. X    "MAC_4", "MAC_5", "MAC_6", "MAC_7", "MAC_8", "MAC_9", "MAC_0"};
  1592. X    static struct PARAM p;
  1593. X    void error_win();
  1594. X
  1595. X    if ((p.p_path = findfile("pcomm.param")) == NULL)
  1596. X        error_win(1, "Support file \"pcomm.param\" is missing", "or no read permission");
  1597. X
  1598. X    if (!(fp = uid_fopen(p.p_path, "r"))) {
  1599. X        sprintf(buf, "\"%s\" for read", p.p_path);
  1600. X        error_win(1, "Can't open parameter file", buf);
  1601. X    }
  1602. X
  1603. X    oops = 0;
  1604. X    line = 0;
  1605. X    for (i=0; i<NUM_PARAM; i++) {
  1606. X        line++;
  1607. X        if (fgets(buf, 200, fp) == NULL) {
  1608. X            sprintf(message, "is truncated at line %d", line);
  1609. X            oops++;
  1610. X            break;
  1611. X        }
  1612. X                    /* parse the input line */
  1613. X        if (!(temp_token = str_tok(buf, '='))) {
  1614. X            sprintf(message, "is missing a token at line %d", line);
  1615. X            oops++;
  1616. X            break;
  1617. X        }
  1618. X        if (!(str = str_tok((char *) NULL, '\n'))) {
  1619. X            sprintf(message, "is missing a parameter at line %d", line);
  1620. X            oops++;
  1621. X            break;
  1622. X        }
  1623. X                    /* sanity checking */
  1624. X        if (strcmp(temp_token, token[i])) {
  1625. X            sprintf(message, "is corrupted at line %d", line);
  1626. X            oops++;
  1627. X            break;
  1628. X        }
  1629. X
  1630. X        switch (i) {
  1631. X                    /* used in ls_menu() */
  1632. X            case LINE_SET:
  1633. X                p.d_baud = (unsigned int) atoi(str);
  1634. X                break;
  1635. X            case LINE_SET+1:
  1636. X                p.d_parity = *str;
  1637. X                break;
  1638. X            case LINE_SET+2:
  1639. X                p.d_data_bits = atoi(str);
  1640. X                break;
  1641. X            case LINE_SET+3:
  1642. X                p.d_stop_bits = atoi(str);
  1643. X                break;
  1644. X
  1645. X                    /* used in term_setup() */
  1646. X            case TERM_SETUP:
  1647. X                p.hot_key = atoi(str);
  1648. X                break;
  1649. X            case TERM_SETUP+1:
  1650. X                p.ascii_hot = str_dup(str);
  1651. X                break;
  1652. X            case TERM_SETUP+2:
  1653. X                p.d_duplex = str_dup(str);
  1654. X                break;
  1655. X            case TERM_SETUP+3:
  1656. X                p.flow_ctrl = str_dup(str);
  1657. X                break;
  1658. X            case TERM_SETUP+4:
  1659. X                p.cr_in = str_dup(str);
  1660. X                break;
  1661. X            case TERM_SETUP+5:
  1662. X                p.cr_out = str_dup(str);
  1663. X                break;
  1664. X
  1665. X                    /* used in gen_setup() */
  1666. X            case GEN_SETUP:
  1667. X                p.logfile = str_dup(str);
  1668. X                break;
  1669. X            case GEN_SETUP+1:
  1670. X                p.dumpfile = str_dup(str);
  1671. X                break;
  1672. X            case GEN_SETUP+2:
  1673. X                p.strip = str_dup(str);
  1674. X                break;
  1675. X            case GEN_SETUP+3:
  1676. X                p.pause_char = *str;
  1677. X                break;
  1678. X            case GEN_SETUP+4:
  1679. X                p.cr_char = *str;
  1680. X                break;
  1681. X            case GEN_SETUP+5:
  1682. X                p.ctrl_char = *str;
  1683. X                break;
  1684. X            case GEN_SETUP+6:
  1685. X                p.esc_char = *str;
  1686. X                break;
  1687. X            case GEN_SETUP+7:
  1688. X                p.brk_char = *str;
  1689. X                break;
  1690. X            case GEN_SETUP+8:
  1691. X                p.abort = str_dup(str);
  1692. X                break;
  1693. X
  1694. X                    /* used in gen_setup() delay_times() */
  1695. X            case DELAY_TIMES:
  1696. X                p.c_delay = atoi(str);
  1697. X                break;
  1698. X            case DELAY_TIMES+1:
  1699. X                p.r_delay = atoi(str);
  1700. X                break;
  1701. X
  1702. X                    /* used in axfer_setup() */
  1703. X            case ASCII_SETUP:
  1704. X                p.local_echo = str_dup(str);
  1705. X                break;
  1706. X            case ASCII_SETUP+1:
  1707. X                p.expand = str_dup(str);
  1708. X                break;
  1709. X            case ASCII_SETUP+2:
  1710. X                p.cr_delay = atoi(str);
  1711. X                break;
  1712. X            case ASCII_SETUP+3:
  1713. X                p.pace = str_dup(str);
  1714. X                break;
  1715. X            case ASCII_SETUP+4:
  1716. X                p.cr_up = str_dup(str);
  1717. X                break;
  1718. X            case ASCII_SETUP+5:
  1719. X                p.lf_up = str_dup(str);
  1720. X                break;
  1721. X            case ASCII_SETUP+6:
  1722. X                p.timer = atoi(str);
  1723. X                break;
  1724. X            case ASCII_SETUP+7:
  1725. X                p.cr_dn = str_dup(str);
  1726. X                break;
  1727. X            case ASCII_SETUP+8:
  1728. X                p.lf_dn = str_dup(str);
  1729. X                break;
  1730. X
  1731. X                    /* used in d_revise() */
  1732. X            case LD_CODES:
  1733. X                p.ld_plus = str_dup(str);
  1734. X                break;
  1735. X            case LD_CODES+1:
  1736. X                p.ld_minus = str_dup(str);
  1737. X                break;
  1738. X            case LD_CODES+2:
  1739. X                p.ld_at = str_dup(str);
  1740. X                break;
  1741. X            case LD_CODES+3:
  1742. X                p.ld_pound = str_dup(str);
  1743. X                break;
  1744. X
  1745. X                    /* used in macro() */
  1746. X            case MACROS:
  1747. X                p.mac_1 = str_dup(str);
  1748. X                break;
  1749. X            case MACROS+1:
  1750. X                p.mac_2 = str_dup(str);
  1751. X                break;
  1752. X            case MACROS+2:
  1753. X                p.mac_3 = str_dup(str);
  1754. X                break;
  1755. X            case MACROS+3:
  1756. X                p.mac_4 = str_dup(str);
  1757. X                break;
  1758. X            case MACROS+4:
  1759. X                p.mac_5 = str_dup(str);
  1760. X                break;
  1761. X            case MACROS+5:
  1762. X                p.mac_6 = str_dup(str);
  1763. X                break;
  1764. X            case MACROS+6:
  1765. X                p.mac_7 = str_dup(str);
  1766. X                break;
  1767. X            case MACROS+7:
  1768. X                p.mac_8 = str_dup(str);
  1769. X                break;
  1770. X            case MACROS+8:
  1771. X                p.mac_9 = str_dup(str);
  1772. X                break;
  1773. X            case MACROS+9:
  1774. X                p.mac_0 = str_dup(str);
  1775. X                break;
  1776. X        }
  1777. X    }
  1778. X    fclose(fp);
  1779. X    if (oops) {
  1780. X        sprintf(buf, "Parameter file \"%s\"", p.p_path);
  1781. X        error_win(1, buf, message);
  1782. X    }
  1783. X    return(&p);
  1784. X}
  1785. X
  1786. X/*
  1787. X * Write the updated param structure to disk.  The values in memory should
  1788. X * have already been "purified".  A non-zero return code means non-fatal
  1789. X * error.
  1790. X */
  1791. X
  1792. int
  1793. up_param()
  1794. X{
  1795. X    FILE *fp, *uid_fopen();
  1796. X    char buf[80];
  1797. X    void error_win();
  1798. X                    /* open for write */
  1799. X    if (!(fp = uid_fopen(param->p_path, "w"))) {
  1800. X        sprintf(buf, "\"%s\"", param->p_path);
  1801. X        error_win(0, "No write permission on parameter file", buf);
  1802. X        return(1);
  1803. X    }
  1804. X
  1805. X    fprintf(fp, "D_BAUD=%d\n", param->d_baud);
  1806. X    fprintf(fp, "D_PARITY=%c\n", param->d_parity);
  1807. X    fprintf(fp, "D_DATA_BITS=%d\n", param->d_data_bits);
  1808. X    fprintf(fp, "D_STOP_BITS=%d\n", param->d_stop_bits);
  1809. X    fprintf(fp, "HOT_KEY=%d\n", param->hot_key);
  1810. X    fprintf(fp, "ASCII_HOT=%s\n", param->ascii_hot);
  1811. X    fprintf(fp, "D_DUPLEX=%s\n", param->d_duplex);
  1812. X    fprintf(fp, "FLOW_CTRL=%s\n", param->flow_ctrl);
  1813. X    fprintf(fp, "CR_IN=%s\n", param->cr_in);
  1814. X    fprintf(fp, "CR_OUT=%s\n", param->cr_out);
  1815. X    fprintf(fp, "LOGFILE=%s\n", param->logfile);
  1816. X    fprintf(fp, "DUMPFILE=%s\n", param->dumpfile);
  1817. X    fprintf(fp, "STRIP=%s\n", param->strip);
  1818. X    fprintf(fp, "PAUSE_CHAR=%c\n", param->pause_char);
  1819. X    fprintf(fp, "CR_CHAR=%c\n", param->cr_char);
  1820. X    fprintf(fp, "CTRL_CHAR=%c\n", param->ctrl_char);
  1821. X    fprintf(fp, "ESC_CHAR=%c\n", param->esc_char);
  1822. X    fprintf(fp, "BRK_CHAR=%c\n", param->brk_char);
  1823. X    fprintf(fp, "ABORT=%s\n", param->abort);
  1824. X    fprintf(fp, "C_DELAY=%d\n", param->c_delay);
  1825. X    fprintf(fp, "R_DELAY=%d\n", param->r_delay);
  1826. X    fprintf(fp, "LOCAL_ECHO=%s\n", param->local_echo);
  1827. X    fprintf(fp, "EXPAND=%s\n", param->expand);
  1828. X    fprintf(fp, "CR_DELAY=%d\n", param->cr_delay);
  1829. X    fprintf(fp, "PACE=%s\n", param->pace);
  1830. X    fprintf(fp, "CR_UP=%s\n", param->cr_up);
  1831. X    fprintf(fp, "LF_UP=%s\n", param->lf_up);
  1832. X    fprintf(fp, "TIMER=%d\n", param->timer);
  1833. X    fprintf(fp, "CR_DN=%s\n", param->cr_dn);
  1834. X    fprintf(fp, "LF_DN=%s\n", param->lf_dn);
  1835. X    fprintf(fp, "LD_PLUS=%s\n", param->ld_plus);
  1836. X    fprintf(fp, "LD_MINUS=%s\n", param->ld_minus);
  1837. X    fprintf(fp, "LD_AT=%s\n", param->ld_at);
  1838. X    fprintf(fp, "LD_POUND=%s\n", param->ld_pound);
  1839. X    fprintf(fp, "MAC_1=%s\n", param->mac_1);
  1840. X    fprintf(fp, "MAC_2=%s\n", param->mac_2);
  1841. X    fprintf(fp, "MAC_3=%s\n", param->mac_3);
  1842. X    fprintf(fp, "MAC_4=%s\n", param->mac_4);
  1843. X    fprintf(fp, "MAC_5=%s\n", param->mac_5);
  1844. X    fprintf(fp, "MAC_6=%s\n", param->mac_6);
  1845. X    fprintf(fp, "MAC_7=%s\n", param->mac_7);
  1846. X    fprintf(fp, "MAC_8=%s\n", param->mac_8);
  1847. X    fprintf(fp, "MAC_9=%s\n", param->mac_9);
  1848. X    fprintf(fp, "MAC_0=%s\n", param->mac_0);
  1849. X
  1850. X    fclose(fp);
  1851. X    return(0);
  1852. X}
  1853. END_OF_FILE
  1854. if test 7341 -ne `wc -c <'p_lib.c'`; then
  1855.     echo shar: \"'p_lib.c'\" unpacked with wrong size!
  1856. fi
  1857. # end of 'p_lib.c'
  1858. fi
  1859. if test -f 's_modem.c' -a "${1}" != "-c" ; then 
  1860.   echo shar: Will not clobber existing file \"'s_modem.c'\"
  1861. else
  1862. echo shar: Extracting \"'s_modem.c'\" \(6948 characters\)
  1863. sed "s/^X//" >'s_modem.c' <<'END_OF_FILE'
  1864. X/*
  1865. X * Display the modem setup, query for changes.  A non-zero return code
  1866. X * means something was changed.
  1867. X */
  1868. X
  1869. X#include <stdio.h>
  1870. X#include <curses.h>
  1871. X#include "misc.h"
  1872. X#include "modem.h"
  1873. X
  1874. static int mod_prompt();
  1875. static void disp_modem();
  1876. X
  1877. int
  1878. modem_setup()
  1879. X{
  1880. X    WINDOW *mo_win, *newwin();
  1881. X    int i, j, ret_code;
  1882. X    char *ans, *str_rep(), *str_prompt(), *menu_prompt();
  1883. X    extern char *v_yn[];
  1884. X                    /* the current modem */
  1885. X    j = 0;
  1886. X    if (modem->m_cur != -1)
  1887. X        j = modem->m_cur;
  1888. X
  1889. X    mo_win = newwin(23, 80, 0, 0);
  1890. X
  1891. X    horizontal(mo_win, 0, 0, 33);
  1892. X    mvwattrstr(mo_win, 0, 34, A_BOLD, "Modem Setup");
  1893. X    horizontal(mo_win, 0, 46, 34);
  1894. X                    /* display the current settings */
  1895. X    disp_modem(mo_win, j);
  1896. X    horizontal(mo_win, 19, 0, 80);
  1897. X    mvwattrstr(mo_win, 20, 0, A_BOLD, "OPTION ==> ");
  1898. X    mvwaddstr(mo_win, 20, 58, "Press <ESC> to return");
  1899. X    wmove(mo_win, 20, 12);
  1900. X    touchwin(mo_win);
  1901. X    wrefresh(mo_win);
  1902. X                    /* get the option number */
  1903. X    ret_code = 0;
  1904. X    while ((i = get_num(mo_win, 2)) != -1) {
  1905. X        switch (i) {
  1906. X            case 1:
  1907. X                j = mod_prompt(mo_win);
  1908. X                break;
  1909. X            case 2:
  1910. X                if ((ans = str_prompt(mo_win, 3, 39, "Modem init string", "sent to the modem once")) != NULL) {
  1911. X                    modem->init[j] = str_rep(modem->init[j], ans);
  1912. X                    ret_code++;
  1913. X                }
  1914. X                break;
  1915. X            case 3:
  1916. X                if ((ans = str_prompt(mo_win, 4, 39, "Dialing command", "")) != NULL) {
  1917. X                    modem->dial[j] = str_rep(modem->dial[j], ans);
  1918. X                    ret_code++;
  1919. X                }
  1920. X                break;
  1921. X            case 4:
  1922. X                if ((ans = str_prompt(mo_win, 5, 39, "Dialing cmd suffix", "typically the <CR> character")) != NULL) {
  1923. X                    modem->suffix[j] = str_rep(modem->suffix[j], ans);
  1924. X                    ret_code++;
  1925. X                }
  1926. X                break;
  1927. X            case 5:
  1928. X                if ((ans = str_prompt(mo_win, 6, 39, "Hang up string", "")) != NULL) {
  1929. X                    modem->hang_up[j] = str_rep(modem->hang_up[j], ans);
  1930. X                    ret_code++;
  1931. X                }
  1932. X                break;
  1933. X            case 6:
  1934. X                if ((ans = menu_prompt(mo_win, 7, 39, "Auto Baud detect", v_yn)) != NULL) {
  1935. X                    modem->auto_baud[j] = *ans;
  1936. X                    ret_code++;
  1937. X                }
  1938. X                break;
  1939. X            case 7:
  1940. X                if ((ans = str_prompt(mo_win, 8, 39, "300 baud connect string", "")) != NULL) {
  1941. X                    modem->con_3[j] = str_rep(modem->con_3[j], ans);
  1942. X                    ret_code++;
  1943. X                }
  1944. X                break;
  1945. X            case 8:
  1946. X                if ((ans = str_prompt(mo_win, 9, 39, "1200 baud connect string", "")) != NULL) {
  1947. X                    modem->con_12[j] = str_rep(modem->con_12[j], ans);
  1948. X                    ret_code++;
  1949. X                }
  1950. X                break;
  1951. X            case 9:
  1952. X                if ((ans = str_prompt(mo_win, 10, 39, "2400 baud connect string", "")) != NULL) {
  1953. X                    modem->con_24[j] = str_rep(modem->con_24[j], ans);
  1954. X                    ret_code++;
  1955. X                }
  1956. X                break;
  1957. X            case 10:
  1958. X                if ((ans = str_prompt(mo_win, 11, 39, "4800 baud connect string", "")) != NULL) {
  1959. X                    modem->con_48[j] = str_rep(modem->con_48[j], ans);
  1960. X                    ret_code++;
  1961. X                }
  1962. X                break;
  1963. X            case 11:
  1964. X                if ((ans = str_prompt(mo_win, 12, 39, "9600 baud connect string", "")) != NULL) {
  1965. X                    modem->con_96[j] = str_rep(modem->con_96[j], ans);
  1966. X                    ret_code++;
  1967. X                }
  1968. X                break;
  1969. X            case 12:
  1970. X                if ((ans = str_prompt(mo_win, 13, 39, "19200 baud connect string", "")) != NULL) {
  1971. X                    modem->con_192[j] = str_rep(modem->con_192[j], ans);
  1972. X                    ret_code++;
  1973. X                }
  1974. X                break;
  1975. X            case 13:
  1976. X                if ((ans = str_prompt(mo_win, 14, 39, "38400 baud connect string", "")) != NULL) {
  1977. X                    modem->con_384[j] = str_rep(modem->con_384[j], ans);
  1978. X                    ret_code++;
  1979. X                }
  1980. X                break;
  1981. X            case 14:
  1982. X                if ((ans = str_prompt(mo_win, 15, 39, "No connect string 1", "")) != NULL) {
  1983. X                    modem->no_con1[j] = str_rep(modem->no_con1[j], ans);
  1984. X                    ret_code++;
  1985. X                }
  1986. X                break;
  1987. X            case 15:
  1988. X                if ((ans = str_prompt(mo_win, 16, 39, "No connect string 2", "")) != NULL) {
  1989. X                    modem->no_con2[j] = str_rep(modem->no_con2[j], ans);
  1990. X                    ret_code++;
  1991. X                }
  1992. X                break;
  1993. X            case 16:
  1994. X                if ((ans = str_prompt(mo_win, 17, 39, "No connect string 3", "")) != NULL) {
  1995. X                    modem->no_con3[j] = str_rep(modem->no_con3[j], ans);
  1996. X                    ret_code++;
  1997. X                }
  1998. X                break;
  1999. X            case 17:
  2000. X                if ((ans = str_prompt(mo_win, 18, 39, "No connect string 4", "")) != NULL) {
  2001. X                    modem->no_con4[j] = str_rep(modem->no_con4[j], ans);
  2002. X                    ret_code++;
  2003. X                }
  2004. X                break;
  2005. X            default:
  2006. X                beep();
  2007. X        }
  2008. X                    /* clear the previous prompts */
  2009. X        mvwaddstr(mo_win, 20, 12, "   ");
  2010. X        clear_line(mo_win, 21, 0, FALSE);
  2011. X        clear_line(mo_win, 22, 0, FALSE);
  2012. X        wmove(mo_win, 20, 12);
  2013. X        wrefresh(mo_win);
  2014. X    }
  2015. X    delwin(mo_win);
  2016. X    return(ret_code);
  2017. X}
  2018. X
  2019. X/*
  2020. X * Prompts for the modem name.  The user selects the currently showing
  2021. X * choice by hitting a carriage return.  Returns the modem entry number.
  2022. X * DOES NOT change the value of modem->m_cur.
  2023. X */
  2024. X
  2025. static int
  2026. mod_prompt(win)
  2027. WINDOW *win;
  2028. X{
  2029. X    char ans;
  2030. X    int i;
  2031. X    void disp_modem();
  2032. X                    /* print prompt lines */
  2033. X    mvwaddstr(win, 22, 0, "Press any key to change, or <CR> to accept");
  2034. X    mvwaddstr(win, 21, 0, "Modem name: ");
  2035. X                    /* show current choice */
  2036. X    i = 0;
  2037. X    if (modem->m_cur != -1)
  2038. X        i = modem->m_cur;
  2039. X    mvwprintw(win, 21, 12, "%-30.30s", modem->mname[i]);
  2040. X    wmove(win, 21, 12);
  2041. X    wrefresh(win);
  2042. X                    /* show the choices one at a time */
  2043. X    while ((ans = wgetch(win)) != '\r') {
  2044. X        i++;
  2045. X        if (*modem->mname[i] == '\0')
  2046. X            i = 0;
  2047. X        if (ans == ESC)
  2048. X            return(0);
  2049. X        mvwprintw(win, 21, 12, "%-30.30s", modem->mname[i]);
  2050. X        wmove(win, 21, 12);
  2051. X        wrefresh(win);
  2052. X    }
  2053. X                    /* display the new values */
  2054. X    disp_modem(win, i);
  2055. X                    /* display the name in bold */
  2056. X    clear_line(win, 2, 39, FALSE);
  2057. X    wrefresh(win);
  2058. X    mvwattrstr(win, 2, 39, A_BOLD, modem->mname[i]);
  2059. X    mvwprintw(win, 2, 25, "(%d of %d) ", i+1, modem->m_entries);
  2060. X
  2061. X    return(i);
  2062. X}
  2063. X
  2064. X/*
  2065. X * Show the current settings for the given modem entry number.
  2066. X */
  2067. X
  2068. static void
  2069. disp_modem(w, i)
  2070. WINDOW *w;
  2071. int i;
  2072. X{
  2073. X    mvwprintw(w, 2, 11, "1) Modem name ............. %-39.39s", modem->mname[i]);
  2074. X    mvwprintw(w, 2, 25, "(%d of %d) ", i+1, modem->m_entries);
  2075. X    mvwprintw(w, 3, 11, "2) Modem init string ...... %-39.39s", modem->init[i]);
  2076. X    mvwprintw(w, 4, 11, "3) Dialing command ........ %-39.39s", modem->dial[i]);
  2077. X    mvwprintw(w, 5, 11, "4) Dialing cmd suffix ..... %-39.39s", modem->suffix[i]);
  2078. X    mvwprintw(w, 6, 11, "5) Hang up string ......... %-39.39s", modem->hang_up[i]);
  2079. X    mvwprintw(w, 7, 11, "6) Auto baud detect ....... %c", modem->auto_baud[i]);
  2080. X    mvwprintw(w, 8, 11, "7) 300 baud connect ....... %-39.39s", modem->con_3[i]);
  2081. X    mvwprintw(w, 9, 11, "8) 1200 baud connect ...... %-39.39s", modem->con_12[i]);
  2082. X    mvwprintw(w, 10, 11, "9) 2400 baud connect ...... %-39.39s", modem->con_24[i]);
  2083. X    mvwprintw(w, 11, 10, "10) 4800 baud connect ...... %-39.39s", modem->con_48[i]);
  2084. X    mvwprintw(w, 12, 10, "11) 9600 baud connect ...... %-39.39s", modem->con_96[i]);
  2085. X    mvwprintw(w, 13, 10, "12) 19200 baud connect ..... %-39.39s", modem->con_192[i]);
  2086. X    mvwprintw(w, 14, 10, "13) 38400 baud connect ..... %-39.39s", modem->con_384[i]);
  2087. X    mvwprintw(w, 15, 10, "14) No connect string 1 .... %-39.39s", modem->no_con1[i]);
  2088. X    mvwprintw(w, 16, 10, "15) No connect string 2 .... %-39.39s", modem->no_con2[i]);
  2089. X    mvwprintw(w, 17, 10, "16) No connect string 3 .... %-39.39s", modem->no_con3[i]);
  2090. X    mvwprintw(w, 18, 10, "17) No connect string 4 .... %-39.39s", modem->no_con4[i]);
  2091. X    return;
  2092. X}
  2093. END_OF_FILE
  2094. if test 6948 -ne `wc -c <'s_modem.c'`; then
  2095.     echo shar: \"'s_modem.c'\" unpacked with wrong size!
  2096. fi
  2097. # end of 's_modem.c'
  2098. fi
  2099. if test -f 'terminal.c' -a "${1}" != "-c" ; then 
  2100.   echo shar: Will not clobber existing file \"'terminal.c'\"
  2101. else
  2102. echo shar: Extracting \"'terminal.c'\" \(8778 characters\)
  2103. sed "s/^X//" >'terminal.c' <<'END_OF_FILE'
  2104. X/*
  2105. X * Start the terminal dialogue, scan the TTY, keyboard, and the "script"
  2106. X * for input, watch for the hot key so we can execute an option.
  2107. X */
  2108. X
  2109. X#include <stdio.h>
  2110. X#include <curses.h>
  2111. X#include <signal.h>
  2112. X#include "config.h"
  2113. X#include "dial_dir.h"
  2114. X#include "ipc.h"
  2115. X#include "misc.h"
  2116. X#include "modem.h"
  2117. X#include "param.h"
  2118. X#include "status.h"
  2119. X#include "xmodem.h"
  2120. X
  2121. X#ifdef BSD
  2122. X#ifndef SIGCLD
  2123. X#define SIGCLD SIGCHLD
  2124. X#endif /* SIGCLD */
  2125. X#include <sys/file.h>
  2126. X#else /* BSD */
  2127. X#include <fcntl.h>
  2128. X#endif /* BSD */
  2129. X
  2130. X#ifdef UNIXPC
  2131. X#include <sys/phone.h>
  2132. X#endif /* UNIXPC */
  2133. X
  2134. static void key_input();
  2135. static int cr_lf;
  2136. X
  2137. void
  2138. terminal(script)
  2139. char *script;
  2140. X{
  2141. X    extern int fd;
  2142. X    int ret_code;
  2143. X    void tty_input(), st_line(), term_mode(), cmd_input(), do_script();
  2144. X    void is_active(), ipc_init();
  2145. X
  2146. X    ipc_init(fd, status->cmd_ipc);
  2147. X                    /* if not starting with -f option */
  2148. X    if (dir->q_num[0] == -1) {
  2149. X        erase();
  2150. X        refresh();
  2151. X        st_line("");
  2152. X    }
  2153. X                    /* put stdin/stdout in terminal mode */
  2154. X    resetterm();
  2155. X    term_mode();
  2156. X    cr_lf = !strcmp(param->cr_out, "CR/LF");
  2157. X
  2158. X                    /* play a script from command line */
  2159. X    if (script != NULL && *script != '\0')
  2160. X        do_script(script);
  2161. X
  2162. X                    /* the main loop ! */
  2163. X    /* CONSTCOND */
  2164. X    while (1) {
  2165. X        ret_code = ipc_poll(fd, status->cmd_ipc);
  2166. X
  2167. X        if (ret_code & TTY_READY)
  2168. X            tty_input();
  2169. X
  2170. X        if (ret_code & KEY_READY)
  2171. X            key_input();
  2172. X
  2173. X        /* 
  2174. X         * This is the reason for the 1 sec "timeout" of the
  2175. X         * poll/select call... to periodically check the status
  2176. X         * of the "script" for input.
  2177. X         */
  2178. X        if (status->dup_fd != -1)
  2179. X            is_active();
  2180. X                    /* do a command from a script */
  2181. X        if (ret_code & CMD_READY)
  2182. X            cmd_input();
  2183. X    }
  2184. X    /* NOTREACHED */
  2185. X}
  2186. X
  2187. X/*
  2188. X * There is something ready to be read from the keyboard.
  2189. X */
  2190. X
  2191. static void
  2192. key_input()
  2193. X{
  2194. X    extern int fd;
  2195. X    int i, k;
  2196. X    char c, lf=10, *str_rep(), *keymac, *script, *script_menu();
  2197. X    void help_screen(), line_set(), n_shell(), load_vs(), send_str();
  2198. X    void release_port(), list_dir(), pexit(), st_line(), chg_dir();
  2199. X    void screen_dump(), info(), term_mode(), macro(), stop_script();
  2200. X    void setup_menu(), xfer_menu(), data_logging(), pass_thru();
  2201. X    void half_duplex(), do_script(), vs_clear(), tty_restart();
  2202. X    void log_toggle(), lpr_toggle();
  2203. X
  2204. X    read(0, &c, 1);
  2205. X    c &= 0x7f;
  2206. X                    /* stop the script? */
  2207. X    if (status->dup_fd != -1 && c == ESC) {
  2208. X        stop_script();
  2209. X        return;
  2210. X    }
  2211. X                    /* is it the hot key? */
  2212. X    if (c == param->hot_key) {
  2213. X
  2214. X        script = NULL;
  2215. X        /*
  2216. X         * Put the terminal in the curses mode, load the
  2217. X         * virtual screen and add the status line at the bottom.
  2218. X         */
  2219. X        fixterm();
  2220. X        load_vs();
  2221. X        st_line("");
  2222. X#ifndef OLDCURSES
  2223. X        keypad(stdscr, TRUE);
  2224. X#endif /* OLDCURSES */
  2225. X        i = wgetch(stdscr);
  2226. X                    /* map an additional hot key to -1 */
  2227. X        if (i == param->hot_key)
  2228. X            i = -1;
  2229. X
  2230. X        keymac = "";
  2231. X                    /* look for options */
  2232. X        k = -1;
  2233. X        switch (i) {
  2234. X            case -1:    /* 2 "hots" means send 1 */
  2235. X                k = param->hot_key;
  2236. X                break;
  2237. X            case '0':    /* help screen */
  2238. X                help_screen(param->ascii_hot);
  2239. X                break;
  2240. X            case 'd':
  2241. X            case 'D':    /* dialing directory */
  2242. X                if (dial_menu()) {
  2243. X                    if (!dial_win(25))
  2244. X                        script = dir->aux[0];
  2245. X                }
  2246. X                break;
  2247. X            case 'r':
  2248. X            case 'R':    /* redial */
  2249. X                if (redial()) {
  2250. X                    if (!dial_win(25))
  2251. X                        script = dir->aux[0];
  2252. X                }
  2253. X                break;
  2254. X            case 'm':
  2255. X            case 'M':    /* keyboard macros */
  2256. X                macro();
  2257. X                break;
  2258. X            case 'p':
  2259. X            case 'P':    /* line settings */
  2260. X                if (ls_menu())
  2261. X                    line_set();
  2262. X                break;
  2263. X            case 'x':
  2264. X            case 'X':    /* exit */
  2265. X                pexit();
  2266. X                break;
  2267. X            case '4':    /* Unix gateway */
  2268. X                n_shell();
  2269. X                break;
  2270. X            case '5':    /* Command files */
  2271. X                script = script_menu();
  2272. X                break;
  2273. X            case 'i':
  2274. X            case 'I':    /* program info screen */
  2275. X                info(MANUAL_CLEAR);
  2276. X                break;
  2277. X            case 's':    /* setup menu */
  2278. X            case 'S':
  2279. X                setup_menu();
  2280. X                break;
  2281. X            case 'c':    /* clear the screen */
  2282. X            case 'C':
  2283. X                erase();
  2284. X                vs_clear(0);
  2285. X                break;
  2286. X            case 'b':
  2287. X            case 'B':    /* change directory */
  2288. X                chg_dir();
  2289. X                break;
  2290. X            case 'e':
  2291. X            case 'E':    /* toggle duplex */
  2292. X                if (dir->duplex[0] == 'F')
  2293. X                    dir->duplex[0] = 'H';
  2294. X                else
  2295. X                    dir->duplex[0] = 'F';
  2296. X
  2297. X                    /* show changes */
  2298. X                st_line("");
  2299. X                k = wait_key(stdscr, 2);
  2300. X                break;
  2301. X            case 'h':
  2302. X            case 'H':    /* hang up phone */
  2303. X                release_port(VERBOSE);
  2304. X                break;
  2305. X            case 'l':
  2306. X            case 'L':    /* print toggle */
  2307. X                lpr_toggle();
  2308. X                    /* show changes */
  2309. X                st_line("");
  2310. X                k = wait_key(stdscr, 2);
  2311. X                break;
  2312. X            case '3':    /* toggle CR - CR/LF */
  2313. X                if (!strcmp(param->cr_in, "CR"))
  2314. X                    param->cr_in = str_rep(param->cr_in, "CR/LF");
  2315. X                else 
  2316. X                    param->cr_in = str_rep(param->cr_in, "CR");
  2317. X                    /* show changes */
  2318. X                st_line("");
  2319. X                k = wait_key(stdscr, 2);
  2320. X                break;
  2321. X            case '7':    /* break key */
  2322. X                if (fd != -1)
  2323. X                    tty_break(fd);
  2324. X
  2325. X                st_line("   break");
  2326. X                break;
  2327. X#ifndef    OLDCURSES
  2328. X            case KEY_UP:
  2329. X#endif /* OLDCURSES */
  2330. X            case 'u':
  2331. X            case 'U':    /* send files */
  2332. X                xfer_menu(UP_LOAD);
  2333. X                break;
  2334. X#ifndef OLDCURSES
  2335. X            case KEY_DOWN:
  2336. X            case '\n':
  2337. X#endif /* OLDCURSES */
  2338. X            case 'n':
  2339. X            case 'N':    /* receive files */
  2340. X                xfer_menu(DOWN_LOAD);
  2341. X                break;
  2342. X            case 't':
  2343. X            case 'T':
  2344. X                pass_thru();
  2345. X                break;
  2346. X            case 'f':
  2347. X            case 'F':    /* list directory */
  2348. X                list_dir();
  2349. X                break;
  2350. X            case 'g':    /* screen dump */
  2351. X            case 'G':
  2352. X                screen_dump();
  2353. X                st_line(" screen dump");
  2354. X                k = wait_key(stdscr, 2);
  2355. X                break;
  2356. X            case '1':    /* data logging */
  2357. X                data_logging();
  2358. X                break;
  2359. X            case '2':    /* toggle log */
  2360. X                if (!strcmp(status->log_path, "NOT_DEFINED")) {
  2361. X                    beep();
  2362. X                    st_line(" no log file");
  2363. X                    k = wait_key(stdscr, 2);
  2364. X                    break;
  2365. X                }
  2366. X                log_toggle();
  2367. X                    /* show changes */
  2368. X                st_line("");
  2369. X                k = wait_key(stdscr, 2);
  2370. X                break;
  2371. X            /*
  2372. X             * The following are the keyboard macros
  2373. X             * corresponding to the shifted number keys.
  2374. X             * (Too many keys... [control] [A] [shift] [1]
  2375. X             * is hardly a shortcut!)
  2376. X             */
  2377. X            case '!':
  2378. X                keymac = param->mac_1;
  2379. X                break;
  2380. X            case '@':
  2381. X                keymac = param->mac_2;
  2382. X                break;
  2383. X            case '#':
  2384. X                keymac = param->mac_3;
  2385. X                break;
  2386. X            case '$':
  2387. X                keymac = param->mac_4;
  2388. X                break;
  2389. X            case '%':
  2390. X                keymac = param->mac_5;
  2391. X                break;
  2392. X            case '^':
  2393. X                keymac = param->mac_6;
  2394. X                break;
  2395. X            case '&':
  2396. X                keymac = param->mac_7;
  2397. X                break;
  2398. X            case '*':
  2399. X                keymac = param->mac_8;
  2400. X                break;
  2401. X            case '(':
  2402. X                keymac = param->mac_9;
  2403. X                break;
  2404. X            case ')':
  2405. X                keymac = param->mac_0;
  2406. X                break;
  2407. X            default:
  2408. X                fputc(BEL, stderr);
  2409. X                break;
  2410. X        }
  2411. X
  2412. X        /*
  2413. X         * Repaint the stdscr (if we are already talking),
  2414. X         * get the stdin/stdout out of the curses mode and
  2415. X         * into the terminal mode.
  2416. X         */
  2417. X        if (fd != -1) {
  2418. X            touchwin(stdscr);
  2419. X            refresh();
  2420. X        }
  2421. X        resetterm();
  2422. X        term_mode();
  2423. X                    /* restart stopped flow control */
  2424. X        tty_restart();
  2425. X
  2426. X        /*
  2427. X         * Some of the output processing options have to be
  2428. X         * faked...  Unfortunately, adding a LF to CR on
  2429. X         * output is one of them.
  2430. X         */
  2431. X        cr_lf = !strcmp(param->cr_out, "CR/LF");
  2432. X
  2433. X                    /* play the script */
  2434. X        if (script != NULL && *script != '\0')
  2435. X            do_script(script);
  2436. X
  2437. X                    /* send the macro */
  2438. X        if (*keymac != '\0')
  2439. X            send_str(keymac, FAST);
  2440. X
  2441. X        /*
  2442. X         * If you pressed a key during one of the sleeping
  2443. X         * periods (typically the delay to see the status
  2444. X         * line change), let the keyboard value fall thru
  2445. X         * to the write() below.
  2446. X         */
  2447. X        if (k == -1)
  2448. X            return;
  2449. X        c = (char) k;
  2450. X    }        
  2451. X                    /* ignore errors if fd == -1 */
  2452. X    write(fd, &c, 1);
  2453. X
  2454. X    /*
  2455. X     * If you're using the half duplex mode, characters don't get
  2456. X     * echoed by the driver (cause you don't type them!)
  2457. X     */
  2458. X    if (dir->duplex[0] == 'H')
  2459. X        half_duplex(c);
  2460. X                    /* map cr to cr_lf? */
  2461. X    if (c == '\r' && cr_lf) {
  2462. X        write(fd, &lf, 1);
  2463. X
  2464. X        if (dir->duplex[0] == 'H') {
  2465. X            write(1, &lf, 1);
  2466. X            half_duplex(lf);
  2467. X        }
  2468. X    }
  2469. X    return;
  2470. X}
  2471. X
  2472. X/*
  2473. X * Hang up the phone but remain in the Pcomm command state.  Uses the
  2474. X * hang_up string only, does *not* drop the DTR!
  2475. X */
  2476. X
  2477. void
  2478. hang_up(verbose)
  2479. int verbose;
  2480. X{
  2481. X    extern int fd;
  2482. X    void send_str(), st_line(), tty_restart();
  2483. X    unsigned int sleep();
  2484. X                    /* sanity checking */
  2485. X    if (modem == NULL)
  2486. X        return;
  2487. X                    /* anything to hang up? */
  2488. X    if (modem->m_cur == -1 || fd == -1)
  2489. X        return;
  2490. X
  2491. X    if (verbose)
  2492. X        st_line("disconnecting");
  2493. X                    /* special case for OBM */
  2494. X    if (!strcmp(modem->mname[modem->m_cur], "OBM")) /* EMPTY */ {
  2495. X#ifdef UNIXPC
  2496. X        char buf[80];
  2497. X        void line_set();
  2498. X
  2499. X        ioctl(fd, PIOCDISC);
  2500. X        /*
  2501. X         * The PIOCDISC ioctl screws up the file descriptor!!!
  2502. X         * No other phone(7) ioctl can fix it.  Whatever it does,
  2503. X         * it seems to escape detection with PIOCGETA and TCGETA.
  2504. X         * The best I can do is close the port and start over.
  2505. X         */
  2506. X        sprintf(buf, "/dev/%s", modem->tty[modem->t_cur]);
  2507. X        close(fd);
  2508. X        fd = open(buf, O_RDWR|O_NDELAY);
  2509. X        line_set();
  2510. X        tty_noblock(fd, FALSE);
  2511. X#endif /* UNIXPC */
  2512. X    }
  2513. X    else {
  2514. X        tty_restart();
  2515. X        send_str(modem->hang_up[modem->m_cur], SLOW);
  2516. X        sleep(1);
  2517. X    }
  2518. X
  2519. X    if (verbose)
  2520. X        st_line("");
  2521. X
  2522. X    status->connected = 0;
  2523. X    return;
  2524. X}
  2525. END_OF_FILE
  2526. if test 8778 -ne `wc -c <'terminal.c'`; then
  2527.     echo shar: \"'terminal.c'\" unpacked with wrong size!
  2528. fi
  2529. # end of 'terminal.c'
  2530. fi
  2531. if test -f 'x_ascii.c' -a "${1}" != "-c" ; then 
  2532.   echo shar: Will not clobber existing file \"'x_ascii.c'\"
  2533. else
  2534. echo shar: Extracting \"'x_ascii.c'\" \(6560 characters\)
  2535. sed "s/^X//" >'x_ascii.c' <<'END_OF_FILE'
  2536. X/*
  2537. X * Transfer a file using just XON/XOFF flow control.  Currently limited to
  2538. X * 7 bit ASCII codes.  (If this causes too much trouble, I'll change it).
  2539. X */
  2540. X
  2541. X#include <stdio.h>
  2542. X#include <curses.h>
  2543. X#include <signal.h>
  2544. X#include "config.h"
  2545. X#include "misc.h"
  2546. X#include "param.h"
  2547. X
  2548. X#ifdef BSD
  2549. X#include <setjmp.h>
  2550. jmp_buf bl_buf;
  2551. X#endif /* BSD */
  2552. X
  2553. static void send_ascii(), rcv_ascii(), putc_ascii();
  2554. static int bgetc_line(), buf_read();
  2555. X
  2556. void
  2557. xfer_ascii(list, up)
  2558. char *list;
  2559. int up;
  2560. X{
  2561. X    int cr_lf;
  2562. X    char *file, *strtok();
  2563. X    void line_set(), st_line();
  2564. X    void ascii_mode(), term_mode();
  2565. X    unsigned int sleep();
  2566. X
  2567. X    touchwin(stdscr);
  2568. X    refresh();
  2569. X                    /* only one file from list */
  2570. X    file = strtok(list, " \t");
  2571. X
  2572. X    cr_lf = !strcmp(param->cr_out, "CR/LF");
  2573. X    ascii_mode(up);
  2574. X                    /* out of curses mode */
  2575. X    resetterm();
  2576. X    term_mode();
  2577. X    tty_noblock(0, TRUE);
  2578. X
  2579. X    if (up)
  2580. X        send_ascii(file, cr_lf);
  2581. X    else
  2582. X        rcv_ascii(file, cr_lf);
  2583. X
  2584. X    /*
  2585. X     * Restoring the TTY modes is easier than setting them... The
  2586. X     * fixterm() and line_set() routines fix most of the damage.
  2587. X     */
  2588. X    line_set();
  2589. X    fixterm();
  2590. X    tty_noblock(0, FALSE);
  2591. X
  2592. X    beep();
  2593. X    st_line("xfer complete");
  2594. X
  2595. X    sleep(2);
  2596. X    return;
  2597. X}
  2598. X
  2599. X/*
  2600. X * Send a file.  The local echo option is independent of the duplex option,
  2601. X * and would very rarely be used since the characters are most likely
  2602. X * being echoed on the screen anyway.
  2603. X */
  2604. X
  2605. static void
  2606. send_ascii(file, cr_lf)
  2607. char *file;
  2608. int cr_lf;
  2609. X{
  2610. X    extern int fd;
  2611. X    FILE *fp, *uid_fopen();
  2612. X    int i, j, strip_cr, strip_lf, add_cr, add_lf, expand, local_echo, pace;
  2613. X    char buf[80], c, last;
  2614. X    unsigned int sleep();
  2615. X    void error_win();
  2616. X                    /* permission already checked */
  2617. X    if (!(fp = uid_fopen(file, "r"))) {
  2618. X        sprintf(buf, "\"%s\"", file);
  2619. X        error_win(0, "Can't open file for read", buf);
  2620. X        return;
  2621. X    }
  2622. X                    /* ASCII transfer options */
  2623. X    strip_cr = !strcmp(param->cr_up, "STRIP");
  2624. X    add_lf = !strcmp(param->cr_up, "ADD LF");
  2625. X    strip_lf = !strcmp(param->lf_up, "STRIP");
  2626. X    add_cr = !strcmp(param->lf_up, "ADD CR");
  2627. X    expand = !strcmp(param->expand, "YES");
  2628. X    local_echo = !strcmp(param->local_echo, "YES");
  2629. X    pace = !strcmp(param->pace, "YES");
  2630. X
  2631. X    last = 0;
  2632. X    while ((i = fgetc(fp)) != EOF) {
  2633. X                    /* any keyboard activity? */
  2634. X        switch (j = getchar()) {
  2635. X            case -1:    /* no key was pressed */
  2636. X                break;
  2637. X            case ESC:    /* <ESC> key for abort */
  2638. X                fclose(fp);
  2639. X                sleep(2);
  2640. X                tty_drain(fd);
  2641. X                return;
  2642. X            default:    /* send the char */
  2643. X                c = (char) j & 0x7f;
  2644. X                putc_ascii(c, local_echo);
  2645. X                if (c == '\r' && cr_lf)
  2646. X                    putc_ascii('\n', local_echo);
  2647. X                break;
  2648. X        }
  2649. X        c = (char) i & 0x7f;
  2650. X                    /* expand blank lines */
  2651. X        if (expand && last == '\n' && c == '\n')
  2652. X            putc_ascii(' ', local_echo);
  2653. X        last = c;
  2654. X
  2655. X                    /* CR translations */
  2656. X        if (c == '\r' && strip_cr)
  2657. X            continue;
  2658. X        if (c == '\r' && add_lf) {
  2659. X            putc_ascii(c, local_echo);
  2660. X            putc_ascii('\n', local_echo);
  2661. X            continue;
  2662. X        }
  2663. X                    /* LF translations */
  2664. X        if (c == '\n' && strip_lf)
  2665. X            continue;
  2666. X        if (c == '\n' && add_cr)
  2667. X            putc_ascii('\r', local_echo);
  2668. X
  2669. X        putc_ascii(c, local_echo);
  2670. X        /*
  2671. X         * There's really no mechanism for delaying characters
  2672. X         * going to the output, so we fake it by waiting for
  2673. X         * each character to clear the I/O buffer.
  2674. X         */
  2675. X        if (pace)
  2676. X            tty_drain(fd);
  2677. X    }
  2678. X    fclose(fp);
  2679. X    sleep(2);
  2680. X    tty_drain(fd);
  2681. X    return;
  2682. X}
  2683. X
  2684. X/* Put a character on the line, echo it too, if required */
  2685. X
  2686. static void
  2687. putc_ascii(c, local_echo)
  2688. char c;
  2689. int local_echo;
  2690. X{
  2691. X    extern int fd;
  2692. X    void vs_putchar();
  2693. X
  2694. X    write(fd, &c, 1);
  2695. X    if (local_echo) {
  2696. X        write(1, &c, 1);
  2697. X        vs_putchar(c);
  2698. X    }
  2699. X    return;
  2700. X}
  2701. X
  2702. X/*
  2703. X * Receive a file.  The timer is used to end the transfer.  This is not
  2704. X * that much different from the data logging option.  The use of bgetc_line()
  2705. X * and non-blocking input makes it seem like full duplex, but it's not.
  2706. X * Be aware that while the timer is active the keyboard is deaf.
  2707. X */
  2708. X
  2709. static void
  2710. rcv_ascii(file, cr_lf)
  2711. char *file;
  2712. int cr_lf;
  2713. X{
  2714. X    FILE *fp, *uid_fopen();
  2715. X    int i, strip_cr, strip_lf, add_cr, add_lf, got_first;
  2716. X    unsigned int delay;
  2717. X    char c, buf[80];
  2718. X    void error_win(), vs_putchar();
  2719. X                    /* permission already checked */
  2720. X    if (!(fp = uid_fopen(file, "w"))) {
  2721. X        sprintf(buf, "\"%s\"", file);
  2722. X        error_win(0, "Can't open file for write", buf);
  2723. X        return;
  2724. X    }
  2725. X                    /* ASCII transfer options */
  2726. X    strip_cr = !strcmp(param->cr_dn, "STRIP");
  2727. X    add_lf = !strcmp(param->cr_dn, "ADD LF");
  2728. X    strip_lf = !strcmp(param->lf_dn, "STRIP");
  2729. X    add_cr = !strcmp(param->lf_dn, "ADD CR");
  2730. X
  2731. X    got_first = 0;
  2732. X    delay = 1;
  2733. X    /* CONSTCOND */
  2734. X    while (1) {
  2735. X                    /* keyboard activity */
  2736. X        switch (i = getchar()) {
  2737. X            case -1:    /* no key was pressed */
  2738. X                break;
  2739. X            case ESC:    /* <ESC> key */
  2740. X                fclose(fp);
  2741. X                return;
  2742. X            default:    /* send it */
  2743. X                c = (unsigned int) i;
  2744. X                putc_line((unsigned char) c);
  2745. X                if (c == '\r' && cr_lf)
  2746. X                    putc_line('\n');
  2747. X                break;
  2748. X        }
  2749. X                    /* read a character */
  2750. X        if ((i = bgetc_line(delay)) == -1) {
  2751. X            /*
  2752. X             * The transfer timeout is not activated until the
  2753. X             * first character is received.  Until then, it polls
  2754. X             * the line for one second and loops backs for
  2755. X             * keyboard input.
  2756. X             */
  2757. X            if (got_first) {
  2758. X                fclose(fp);
  2759. X                return;
  2760. X            }
  2761. X            continue;
  2762. X        }
  2763. X        got_first = 1;
  2764. X        delay = param->timer;
  2765. X        c = i & 0x7f;
  2766. X                    /* display it on the screen */
  2767. X        write(1, &c, 1);
  2768. X        vs_putchar(c);
  2769. X                    /* CR translations */
  2770. X        if (c == '\r' && strip_cr)
  2771. X            continue;
  2772. X        if (c == '\r' && add_lf) {
  2773. X            fputc(c, fp);
  2774. X            fputc('\n', fp);
  2775. X            continue;
  2776. X        }
  2777. X                    /* LF translations */
  2778. X        if (c == '\n' && strip_lf)
  2779. X            continue;
  2780. X        if (c == '\n' && add_cr) {
  2781. X            fputc('\r', fp);
  2782. X            fputc(c, fp);
  2783. X            continue;
  2784. X        }
  2785. X        fputc(c, fp);
  2786. X    }
  2787. X}
  2788. X
  2789. X/*
  2790. X * Get a character from the line (using buffered I/O) with a specified
  2791. X * time-out period in seconds.  If the function times-out, it returns a -1.
  2792. X */
  2793. X
  2794. static int bl_flag;
  2795. static int bl_force();
  2796. X
  2797. static int
  2798. bgetc_line(sec)
  2799. unsigned int sec;
  2800. X{
  2801. X    int c;
  2802. X    unsigned int alarm();
  2803. X
  2804. X    signal(SIGALRM, (SIG_TYPE(*) ()) bl_force);
  2805. X    bl_flag = 0;
  2806. X
  2807. X    alarm(sec);
  2808. X
  2809. X#ifdef BSD
  2810. X    if (setjmp(bl_buf))
  2811. X        return(-1);
  2812. X#endif /* BSD */
  2813. X
  2814. X    if ((c = buf_read()) < 0) {
  2815. X        alarm(0);
  2816. X        return(-1);
  2817. X    }
  2818. X    if (bl_flag)
  2819. X        return(-1);
  2820. X    alarm(0);
  2821. X    return(c);
  2822. X}
  2823. X
  2824. X/* ARGSUSED */
  2825. static int
  2826. bl_force(dummy)
  2827. int dummy;
  2828. X{
  2829. X#ifdef BSD
  2830. X    longjmp(bl_buf, 1);
  2831. X#else /* BSD */
  2832. X    signal(SIGALRM, (SIG_TYPE(*) ()) bl_force);
  2833. X    bl_flag = 1;
  2834. X    return(0);
  2835. X#endif /* BSD */
  2836. X}
  2837. X
  2838. X/*
  2839. X * Do a single character buffered read from the serial port.
  2840. X */
  2841. X
  2842. static int
  2843. buf_read()
  2844. X{
  2845. X    extern int fd;
  2846. X    static char buf[CLIST_SIZ];
  2847. X    static char *bufp = buf;
  2848. X    static int n = 0;
  2849. X
  2850. X    if (n <= 0) {
  2851. X        n = read(fd, buf, CLIST_SIZ);
  2852. X        bufp = buf;
  2853. X    }
  2854. X    if (--n >= 0)
  2855. X        return(*bufp++ & 0xff);
  2856. X    return(-1);
  2857. X}
  2858. END_OF_FILE
  2859. if test 6560 -ne `wc -c <'x_ascii.c'`; then
  2860.     echo shar: \"'x_ascii.c'\" unpacked with wrong size!
  2861. fi
  2862. # end of 'x_ascii.c'
  2863. fi
  2864. if test -f 'x_batch.c' -a "${1}" != "-c" ; then 
  2865.   echo shar: Will not clobber existing file \"'x_batch.c'\"
  2866. else
  2867. echo shar: Extracting \"'x_batch.c'\" \(8917 characters\)
  2868. sed "s/^X//" >'x_batch.c' <<'END_OF_FILE'
  2869. X/*
  2870. X * Routines to support the batch protocols.
  2871. X */
  2872. X
  2873. X#include <stdio.h>
  2874. X#include <ctype.h>
  2875. X#include <curses.h>
  2876. X#include "config.h"
  2877. X#include "misc.h"
  2878. X#include "xmodem.h"
  2879. X
  2880. static char *fix_name();
  2881. static void change_name(), unfix_name(), change_name();
  2882. X
  2883. X/*
  2884. X * Send the file name for the modem7 batch.  Only uses 11 characters
  2885. X * of the filename.  Returns zero on success or the standard error codes.
  2886. X */
  2887. X
  2888. int
  2889. send_modem7(win, name)
  2890. WINDOW *win;
  2891. char *name;
  2892. X{
  2893. X    char *new_name;
  2894. X    unsigned char sum, calc_sum();
  2895. X
  2896. X                    /* convert to 11 character name */
  2897. X    new_name = fix_name(name);
  2898. X    sum = calc_sum((unsigned char *) new_name, 12);
  2899. X
  2900. X    putc_line(ACK);
  2901. X                    /* for each character in the name */
  2902. X    while (*new_name != CTRLZ) {
  2903. X        putc_line((unsigned char) *new_name);
  2904. X
  2905. X        switch (getc_line(3)) {
  2906. X            case -1:    /* timed out */
  2907. X                clear_line(win, 12, 24, TRUE);
  2908. X                waddstr(win, "NO RESPONSE");
  2909. X                wrefresh(win);
  2910. X                return(ERROR);
  2911. X            case ACK:    /* got it! */
  2912. X                break;
  2913. X            case CAN:    /* cancel transmission */
  2914. X                if (getc_line(2) == CAN) {
  2915. X                    beep();
  2916. X                    clear_line(win, 12, 24, TRUE);
  2917. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  2918. X                    wrefresh(win);
  2919. X                    return(CANCEL);
  2920. X                }
  2921. X                /* FALLTHRU */
  2922. X            default:
  2923. X                clear_line(win, 12, 24, TRUE);
  2924. X                waddstr(win, "NAME FAILED");
  2925. X                wrefresh(win);
  2926. X                return(ERROR);
  2927. X        }
  2928. X        new_name++;
  2929. X    }
  2930. X    putc_line(CTRLZ);
  2931. X                    /* verify the checksum */
  2932. X    if (getc_line(10) != sum) {
  2933. X        putc_line('u');
  2934. X        clear_line(win, 12, 24, TRUE);
  2935. X        waddstr(win, "CHECKSUM FAILED");
  2936. X        wrefresh(win);
  2937. X        return(ERROR);
  2938. X    }
  2939. X    putc_line(ACK);
  2940. X    return(0);
  2941. X}
  2942. X
  2943. X/*
  2944. X * Receive a modem7 file name.  Returns zero on success, the standard error
  2945. X * codes, or a -1 on the end-of-batch.  (Oddly enough, the end-of-batch code
  2946. X * is the same as the code for a user abort)
  2947. X */
  2948. X
  2949. int
  2950. rcv_modem7(win, default_err)
  2951. WINDOW *win;
  2952. int default_err;
  2953. X{
  2954. X    extern char file_name[15];
  2955. X    int i, j, err_method, err_count, got_it;
  2956. X    unsigned char sum, calc_sum();
  2957. X    char temp_name[13];
  2958. X
  2959. X    err_method = default_err;
  2960. X    if (default_err == CRC_CHECKSUM)
  2961. X        err_method = CRC;
  2962. X
  2963. X    err_count = 0;
  2964. X    got_it = 0;
  2965. X    while (err_count < MAX_ERRORS) {
  2966. X                    /* switch to checksum? */
  2967. X        if (default_err == CRC_CHECKSUM && err_count > MAX_ERRORS/2)
  2968. X            err_method = CHECKSUM;
  2969. X
  2970. X        if (err_method == CRC)
  2971. X            putc_line('C');
  2972. X        else
  2973. X            putc_line(NAK);
  2974. X                    /* what'd we get? */
  2975. X        switch (getc_line(10)) {
  2976. X            case -1:    /* timed out */
  2977. X                clear_line(win, 12, 24, TRUE);
  2978. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  2979. X                wrefresh(win);
  2980. X                err_count++;
  2981. X                break;
  2982. X            case ACK:    /* ready to go... */
  2983. X                got_it++;
  2984. X                break;
  2985. X            default:    /* huh? */
  2986. X                clear_line(win, 12, 24, TRUE);
  2987. X                wattrstr(win, A_BOLD, "BAD HEADER");
  2988. X                wrefresh(win);
  2989. X                err_count++;
  2990. X        }
  2991. X        if (got_it)
  2992. X            break;
  2993. X    }
  2994. X    if (!got_it)
  2995. X        return(ERROR);
  2996. X                    /* get the name */
  2997. X    for (i=0; i<12; i++) {
  2998. X        j = getc_line(3);
  2999. X
  3000. X        switch (j) {
  3001. X            case -1:    /* timed out */
  3002. X                clear_line(win, 12, 24, TRUE);
  3003. X                wattrstr(win, A_BOLD, "NO RESPONSE");
  3004. X                wrefresh(win);
  3005. X                return(ERROR);
  3006. X            case EOT:    /* end of batch? */
  3007. X                return(-1);
  3008. X            case CAN:    /* cancel transmission */
  3009. X                if (getc_line(2) == CAN) {
  3010. X                    beep();
  3011. X                    clear_line(win, 12, 24, TRUE);
  3012. X                    wattrstr(win, A_BOLD, "REMOTE ABORTED");
  3013. X                    wrefresh(win);
  3014. X                    return(CANCEL);
  3015. X                }
  3016. X                /* FALLTHRU */
  3017. X            case 'u':    /* bad name character */
  3018. X                beep();
  3019. X                clear_line(win, 12, 24, TRUE);
  3020. X                wattrstr(win, A_BOLD, "BAD NAME");
  3021. X                wrefresh(win);
  3022. X                return(ERROR);
  3023. X            default:    /* the name... */
  3024. X                temp_name[i] = j & 0xff;
  3025. X                if (j != CTRLZ)
  3026. X                    putc_line(ACK);
  3027. X                break;
  3028. X        }
  3029. X    }
  3030. X    temp_name[12] = '\0';
  3031. X                    /* send our checksum */
  3032. X    sum = calc_sum((unsigned char *) temp_name, 12);
  3033. X    putc_line(sum);
  3034. X                    /* do they agree? */
  3035. X    if (getc_line(10) != ACK) {
  3036. X        beep();
  3037. X        clear_line(win, 12, 24, TRUE);
  3038. X        wattrstr(win, A_BOLD, "BAD NAME");
  3039. X        wrefresh(win);
  3040. X        return(ERROR);
  3041. X    }
  3042. X                    /* load the file_name array */
  3043. X    unfix_name(temp_name);
  3044. X                    /* any name collisions? */
  3045. X    change_name(win, file_name);
  3046. X    return(0);
  3047. X}
  3048. X
  3049. X/*
  3050. X * Send the block 0 information for a ymodem batch transfer.  Uses only
  3051. X * the name component of the path and the file size.
  3052. X */
  3053. X
  3054. int
  3055. send_ymodem(win, file, size)
  3056. WINDOW *win;
  3057. char *file;
  3058. long size;
  3059. X{
  3060. X    unsigned short crc, calc_crc();
  3061. X    char *strcpy(), *memset();
  3062. X    unsigned char buf[133];
  3063. X                    /* start with a clean block */
  3064. X    memset((char *) buf, '\0', 133);
  3065. X                    /* the header */
  3066. X    buf[0] = SOH;
  3067. X    buf[1] = 0;
  3068. X    buf[2] = 255;
  3069. X
  3070. X    /*
  3071. X     * The block zero consists of the file name (no path component),
  3072. X     * a NULL, and the file length (as a string).  The end of batch
  3073. X     * marker is an empty block.
  3074. X     */
  3075. X    if (*file != '\0') {
  3076. X        strcpy((char *) &buf[3], file);
  3077. X        sprintf((char *) &buf[strlen(file)+4], "%ld", size);
  3078. X    }
  3079. X                    /* the crc */
  3080. X    crc = calc_crc(&buf[3], 128);
  3081. X    buf[131] = crc >> 8;
  3082. X    buf[132] = crc & 0xff;
  3083. X                    /* the block count */
  3084. X    mvwaddstr(win, 7, 24, "0   ");
  3085. X
  3086. X    return(send_block(win, buf, 133));
  3087. X}
  3088. X
  3089. X/*
  3090. X * Receive the block 0 information for a ymodem batch transfer.  We
  3091. X * only use the file name and the size (if present).  Currently doesn't
  3092. X * support full path names.
  3093. X */
  3094. X
  3095. int
  3096. rcv_ymodem(win)
  3097. WINDOW *win;
  3098. X{
  3099. X    extern unsigned char buf[1029];
  3100. X    extern long file_length;
  3101. X    extern char file_name[15];
  3102. X    int code, length_is_at;
  3103. X    long atol();
  3104. X
  3105. X    file_length = 0L;
  3106. X    file_name[0] = '\0';
  3107. X                    /* read the zero block */
  3108. X    if (code = rcv_block(win, 1, 1024, 0))
  3109. X        return(code);
  3110. X                    /* at end of batch */
  3111. X    if (buf[3] == '\0')
  3112. X        return(0);
  3113. X                    /* get the file name */
  3114. X    change_name(win, (char *) &buf[3]);
  3115. X                    /* any trouble? */
  3116. X    if (file_name[0] == '\0') {
  3117. X        putc_line(CAN);
  3118. X        return(0);
  3119. X    }
  3120. X    /*
  3121. X     * The file length is placed after the NULL of the file name
  3122. X     * and is terminated by another NULL.  If the length is missing,
  3123. X     * atol() will see a NULL and return 0.
  3124. X     */
  3125. X    length_is_at = strlen((char *) &buf[3]) + 4;
  3126. X    file_length = atol((char *) &buf[length_is_at]);
  3127. X    return(0);
  3128. X}
  3129. X
  3130. X/*
  3131. X * Handle file name collisions.  Prepend an "X" to the name until you find
  3132. X * a name that doesn't already exist.  Creates a NULL name on error.
  3133. X * Loads the global character array "file_name".
  3134. X */
  3135. X
  3136. static void
  3137. change_name(win, str)
  3138. WINDOW *win;
  3139. char *str;
  3140. X{
  3141. X    extern char file_name[15];
  3142. X    register int i;
  3143. X    int modified;
  3144. X    char temp[15], ans[15], *s, *strrchr(), *strcpy(), *strncat();
  3145. X    char *strncpy();
  3146. X    unsigned int sleep();
  3147. X                    /* dissect the name component */
  3148. X    if ((s = strrchr(str, '/')))
  3149. X        strncpy(temp, ++s, 15);
  3150. X    else
  3151. X        strncpy(temp, str, 15);
  3152. X    temp[14] = '\0';
  3153. X
  3154. X    strcpy(ans, temp);
  3155. X    file_name[0] = '\0';
  3156. X                    /* write permission on directory? */
  3157. X    if (access(".", 2)) {
  3158. X        beep();
  3159. X        clear_line(win, 12, 24, TRUE);
  3160. X        wattrstr(win, A_BOLD, "NO WRITE ON DIRECTORY");
  3161. X        wrefresh(win);
  3162. X        return;
  3163. X    }
  3164. X                    /* prepend up to 13 "X"s */
  3165. X    modified = 0;
  3166. X    for (i=1; i<14; i++) {
  3167. X        if (access(ans, 0)) {
  3168. X            if (modified) {
  3169. X                beep();
  3170. X                clear_line(win, 12, 24, TRUE);
  3171. X                waddstr(win, "NAME COLLISION");
  3172. X                wrefresh(win);
  3173. X                sleep(1);
  3174. X            }
  3175. X            strcpy(file_name, ans);
  3176. X            return;
  3177. X        }
  3178. X
  3179. X        modified++;
  3180. X        strcpy(temp, "X");
  3181. X        strncat(temp, ans, 13);
  3182. X        temp[14] = '\0';
  3183. X        strcpy(ans, temp);
  3184. X    }
  3185. X    beep();
  3186. X    clear_line(win, 12, 24, TRUE);
  3187. X    waddstr(win, "BAD NAME");
  3188. X    wrefresh(win);
  3189. X    return;
  3190. X}
  3191. X
  3192. X/*
  3193. X * Convert a perfectly good Unix file name to fit the CP/M file name
  3194. X * rules.  Used for the modem7 batch file transfer.  Returns a pointer
  3195. X * to a static area containing the new name.
  3196. X */
  3197. X
  3198. static char *
  3199. fix_name(path)
  3200. char *path;
  3201. X{
  3202. X    int i, dot;
  3203. X    char *s, *name, temp[15], *ext, *strncpy(), *strrchr();
  3204. X    static char ans[13];
  3205. X                    /* ignore the path component */
  3206. X    if (s = strrchr(path, '/'))
  3207. X        strncpy(temp, ++s, 15);
  3208. X    else
  3209. X        strncpy(temp, path, 15);
  3210. X    temp[14] = '\0';
  3211. X    name = temp;
  3212. X
  3213. X    ext = "";
  3214. X    dot = 0;
  3215. X    for (i=strlen(temp)-1; i>=0; i--) {
  3216. X        if (temp[i] == '.' && !dot) {
  3217. X            dot = 1;
  3218. X            temp[i] = '\0';
  3219. X            ext = &temp[i+1];
  3220. X        }
  3221. X        if (islower(temp[i]))
  3222. X            temp[i] = toupper(temp[i]);
  3223. X    }
  3224. X                    /* if null name component */
  3225. X    if (*name == '\0')
  3226. X        name = "X";
  3227. X                    /* if name too long */
  3228. X    if (strlen(name) > 8)
  3229. X        *(name+8) = '\0';
  3230. X                    /* if extension too long */
  3231. X    if (strlen(ext) > 3)
  3232. X        *(ext+3) = '\0';
  3233. X
  3234. X    sprintf(ans, "%-8.8s%-3.3s%c", temp, ext, CTRLZ);
  3235. X    return(ans);
  3236. X}
  3237. X
  3238. X/*
  3239. X * Convert a CP/M style filename into a legal Unix file name.  Loads the
  3240. X * global character array "file_name".
  3241. X */
  3242. X
  3243. static void
  3244. unfix_name(cpm_name)
  3245. char *cpm_name;
  3246. X{
  3247. X    extern char file_name[15];
  3248. X    register int i, n;
  3249. X    int dot;
  3250. X    char temp[15], *strcpy();
  3251. X
  3252. X    file_name[0] = '\0';
  3253. X    if (*cpm_name == '\0')
  3254. X        return;
  3255. X
  3256. X    strcpy(temp, cpm_name);
  3257. X                    /* 8 character of the name */
  3258. X    n = 0;
  3259. X    for (i=0; i<8; i++) {
  3260. X        if (temp[i] != ' ') {
  3261. X            if (isupper(temp[i]))
  3262. X                file_name[n++] = tolower(temp[i]);
  3263. X            else
  3264. X                file_name[n++] = temp[i];
  3265. X        }
  3266. X    }
  3267. X                    /* 3 character extension */
  3268. X    dot = 0;
  3269. X    for (i=8; i<11; i++) {
  3270. X        if (temp[i] != ' ') {
  3271. X            if (!dot) {
  3272. X                dot++;
  3273. X                file_name[n++] = '.';
  3274. X            }
  3275. X            if (isupper(temp[i]))
  3276. X                file_name[n++] = tolower(temp[i]);
  3277. X            else
  3278. X                file_name[n++] = temp[i];
  3279. X        }
  3280. X    }
  3281. X    file_name[n] = '\0';
  3282. X    return;
  3283. X}
  3284. END_OF_FILE
  3285. if test 8917 -ne `wc -c <'x_batch.c'`; then
  3286.     echo shar: \"'x_batch.c'\" unpacked with wrong size!
  3287. fi
  3288. # end of 'x_batch.c'
  3289. fi
  3290. if test -f 'x_menu.c' -a "${1}" != "-c" ; then 
  3291.   echo shar: Will not clobber existing file \"'x_menu.c'\"
  3292. else
  3293. echo shar: Extracting \"'x_menu.c'\" \(7412 characters\)
  3294. sed "s/^X//" >'x_menu.c' <<'END_OF_FILE'
  3295. X/*
  3296. X * Open a window to display the choices of file transfer protocols and
  3297. X * prompt for the file name(s).
  3298. X */
  3299. X
  3300. X#include <stdio.h>
  3301. X#include <sys/types.h>
  3302. X#include <sys/stat.h>
  3303. X#include <curses.h>
  3304. X#include "extrnl.h"
  3305. X#include "misc.h"
  3306. X#include "xmodem.h"
  3307. X
  3308. static char *get_names(), *get_extrnl();
  3309. X
  3310. void
  3311. xfer_menu(up)
  3312. int up;
  3313. X{
  3314. X    extern int fd;
  3315. X    extern char *null_ptr;
  3316. X    WINDOW *xm_win, *newwin();
  3317. X    char buf[2048], *list, *strcat(), *strcpy();
  3318. X    int type, is_batch, i, ans, num_extrnl, n;
  3319. X    void xfer_win(), xfer_ascii(), do_extrnl(), error_win();
  3320. X
  3321. X    num_extrnl = (up) ? extrnl->up_entries : extrnl->dn_entries;
  3322. X    xm_win = newwin(14+num_extrnl, 20, 2, 45);
  3323. X
  3324. X    mvwaddstr(xm_win, 2, 3, "1) xmodem");
  3325. X    mvwaddstr(xm_win, 3, 3, "2) xmodem-1k");
  3326. X    mvwaddstr(xm_win, 4, 3, "3) modem7");
  3327. X    mvwaddstr(xm_win, 5, 3, "4) ymodem");
  3328. X    mvwaddstr(xm_win, 6, 3, "5) ymodem-g");
  3329. X    mvwaddstr(xm_win, 7, 3, "6) ASCII");
  3330. X
  3331. X    for (i=0; i<num_extrnl; i++)
  3332. X        mvwprintw(xm_win, i+8, 3, "%d) %-12.12s", i+7, extrnl->name[up][i]);
  3333. X    mvwaddstr(xm_win, i+8, 3, "E) (external)");
  3334. X    mvwaddstr(xm_win, i+10, 3, "<ESC> to Abort");
  3335. X    mvwaddstr(xm_win, i+11, 3, "Protocol:");
  3336. X    box(xm_win, VERT, HORZ);
  3337. X    if (up)
  3338. X        mvwattrstr(xm_win, 0, 6, A_BOLD, " Upload ");
  3339. X    else
  3340. X        mvwattrstr(xm_win, 0, 5, A_BOLD, " Download ");
  3341. X
  3342. X    wmove(xm_win, i+11, 13);
  3343. X    wrefresh(xm_win);
  3344. X                    /* get the protocol */
  3345. X    type = -1;
  3346. X    while ((ans = wgetch(xm_win)) != ESC) {
  3347. X        switch (ans) {
  3348. X            case '1':
  3349. X                type = XMODEM;
  3350. X                break;
  3351. X            case '2':
  3352. X                type = XMODEM_1k;
  3353. X                break;
  3354. X            case '3':
  3355. X                type = MODEM7;
  3356. X                break;
  3357. X            case '4':
  3358. X                type = YMODEM;
  3359. X                break;
  3360. X            case '5':
  3361. X                type = YMODEM_G;
  3362. X                break;
  3363. X            case '6':
  3364. X                type = XASCII;
  3365. X                break;
  3366. X            case '7':
  3367. X                if (num_extrnl >= 1)
  3368. X                    type = EXT_1;
  3369. X                else
  3370. X                    beep();
  3371. X                break;
  3372. X            case '8':
  3373. X                if (num_extrnl >= 2)
  3374. X                    type = EXT_2;
  3375. X                else
  3376. X                    beep();
  3377. X                break;
  3378. X            case '9':
  3379. X                if (num_extrnl >= 3)
  3380. X                    type = EXT_3;
  3381. X                else
  3382. X                    beep();
  3383. X                break;
  3384. X            case 'e':
  3385. X            case 'E':
  3386. X                type = EXT_MANUAL;
  3387. X                break;
  3388. X            default:
  3389. X                beep();
  3390. X        }
  3391. X        if (type != -1)
  3392. X            break;
  3393. X    }
  3394. X    werase(xm_win);
  3395. X    wrefresh(xm_win);
  3396. X    delwin(xm_win);
  3397. X                    /* chicken'd out */
  3398. X    if (type == -1)
  3399. X        return;
  3400. X
  3401. X    if (fd == -1) {
  3402. X        error_win(0, "Not currently connected to any host", "");
  3403. X        return;
  3404. X    }
  3405. X                    /* which protocol? */
  3406. X    is_batch = 0;
  3407. X    switch(type) {
  3408. X        case MODEM7:
  3409. X        case YMODEM:
  3410. X        case YMODEM_G:        /* built-in protocols */
  3411. X            is_batch++;
  3412. X            /* FALLTHRU */
  3413. X        case XMODEM:
  3414. X        case XMODEM_1k:        /* non-batch built-ins */
  3415. X            list = null_ptr;
  3416. X            /*
  3417. X             * When receiving in a batch mode, don't prompt
  3418. X             * for file names.
  3419. X             */
  3420. X            if (up || !is_batch) {
  3421. X                if (!(list = get_names(up, type, is_batch)))
  3422. X                    break;
  3423. X            }
  3424. X            xfer_win(list, up, type);
  3425. X            break;
  3426. X        case XASCII:        /* ascii xfer, yuck! */
  3427. X            if (list = get_names(up, type, FALSE))
  3428. X                xfer_ascii(list, up);
  3429. X            break;
  3430. X        case EXT_1:
  3431. X        case EXT_2:
  3432. X        case EXT_3:        /* one of the externals */
  3433. X            n = type -NUM_INTERNAL -1;
  3434. X            strcpy(buf, extrnl->command[up][n]);
  3435. X                    /* see if we need to prompt for files */
  3436. X            if (extrnl->prompt[up][n] == 'Y') {
  3437. X                if (list = get_names(up, type, TRUE)) {
  3438. X                    strcat(buf, " ");
  3439. X                    strcat(buf, list);
  3440. X                }
  3441. X                else
  3442. X                    break;
  3443. X            }
  3444. X            do_extrnl(buf);
  3445. X            break;
  3446. X        case EXT_MANUAL:    /* the manual external protocol */
  3447. X            if (list = get_extrnl(up))
  3448. X                do_extrnl(list);
  3449. X            break;
  3450. X    }
  3451. X    return;
  3452. X}
  3453. X
  3454. char *protocol[NUM_INTERNAL] = {"xmodem", "xmodem-1k", "modem7", "ymodem",
  3455. X    "ymodem-g", "ASCII"};
  3456. X
  3457. X/*
  3458. X * Prompt for a list of files for the transfer programs.  Since expand()
  3459. X * is used, it returns a pointer to a static area.  Returns a NULL if 
  3460. X * you chicken'd out.
  3461. X */
  3462. X
  3463. static char *
  3464. get_names(up, type, is_batch)
  3465. int up, type, is_batch;
  3466. X{
  3467. X    int got_it, n;
  3468. X    WINDOW *gn_win, *newwin();
  3469. X    char *ans, *file, *list, buf[40], *expand(), *get_str(), *strtok();
  3470. X    void st_line();
  3471. X    struct stat stbuf;
  3472. X
  3473. X    touchwin(stdscr);
  3474. X    refresh();
  3475. X    st_line("");
  3476. X
  3477. X    n = type -NUM_INTERNAL -1;
  3478. X
  3479. X    gn_win = newwin(7, 70, 5, 5);
  3480. X    mvwaddstr(gn_win, 3, 4, "Enter filename: ");
  3481. X    box(gn_win, VERT, HORZ);
  3482. X    if (up) {
  3483. X        if (type <= NUM_INTERNAL)
  3484. X            sprintf(buf, " Send %s ", protocol[type -1]);
  3485. X        else
  3486. X            sprintf(buf, " Send %s ", extrnl->name[up][n]);
  3487. X    }
  3488. X    else {
  3489. X        if (type <= NUM_INTERNAL)
  3490. X            sprintf(buf, " Receive %s ", protocol[type -1]);
  3491. X        else
  3492. X            sprintf(buf, " Receive %s ", extrnl->name[up][n]);
  3493. X    }
  3494. X    mvwattrstr(gn_win, 0, 3, A_BOLD, buf);
  3495. X
  3496. X    /* CONSTCOND */
  3497. X    while (1) {
  3498. X        wmove(gn_win, 3, 20);
  3499. X        wrefresh(gn_win);
  3500. X                    /* get the answers */
  3501. X        if (is_batch)
  3502. X            ans = get_str(gn_win, 60, "", "\n");
  3503. X        else
  3504. X            ans = get_str(gn_win, 60, "", " \t\n");
  3505. X
  3506. X        if (ans == NULL || *ans == '\0') {
  3507. X            list = NULL;
  3508. X            break;
  3509. X        }
  3510. X        list = expand(ans);
  3511. X                    /* batches are checked on-the-fly */
  3512. X        if (is_batch)
  3513. X            break;
  3514. X        /*
  3515. X         * Here we have the opportunity to determine the read and
  3516. X         * write permissions before things get started.  Much nicer
  3517. X         * than finding out later when there's no way to fix it.
  3518. X         * Only checks the first file.
  3519. X         */
  3520. X        file = strtok(list, " \t");
  3521. X                    /* sanity checking */
  3522. X        if (!stat(file, &stbuf)) {
  3523. X            if ((stbuf.st_mode & S_IFREG) != S_IFREG) {
  3524. X                beep();
  3525. X                clear_line(gn_win, 4, 15, TRUE);
  3526. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "Not a regular file");
  3527. X                wrefresh(gn_win);
  3528. X                wait_key(gn_win, 3);
  3529. X                clear_line(gn_win, 4, 15, TRUE);
  3530. X                clear_line(gn_win, 3, 20, TRUE);
  3531. X                continue;
  3532. X            }
  3533. X        }
  3534. X                    /* check read permission */
  3535. X        if (up) {
  3536. X            if (access(file, 0)) {
  3537. X                beep();
  3538. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "Can't find file");
  3539. X                wrefresh(gn_win);
  3540. X                wait_key(gn_win, 3);
  3541. X                clear_line(gn_win, 4, 15, TRUE);
  3542. X                clear_line(gn_win, 3, 20, TRUE);
  3543. X                continue;
  3544. X            }
  3545. X            if (access(file, 4)) {
  3546. X                beep();
  3547. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "No read permission");
  3548. X                wrefresh(gn_win);
  3549. X                wait_key(gn_win, 3);
  3550. X                clear_line(gn_win, 4, 15, TRUE);
  3551. X                clear_line(gn_win, 3, 20, TRUE);
  3552. X                continue;
  3553. X            }
  3554. X            break;
  3555. X        }
  3556. X                    /* check write permission */
  3557. X        got_it = 0;
  3558. X        switch(can_write(file)) {
  3559. X            case DENIED:
  3560. X                beep();
  3561. X                clear_line(gn_win, 4, 15, TRUE);
  3562. X                mvwattrstr(gn_win, 4, 15, A_BOLD, "No write permission");
  3563. X                wrefresh(gn_win);
  3564. X                wait_key(gn_win, 3);
  3565. X                clear_line(gn_win, 4, 15, TRUE);
  3566. X                clear_line(gn_win, 3, 20, TRUE);
  3567. X                break;
  3568. X            case OK_BUT_EXISTS:
  3569. X                if (!yes_prompt(gn_win, 4, 15, A_BOLD, "File exists, overwrite")) {
  3570. X                    clear_line(gn_win, 4, 15, TRUE);
  3571. X                    clear_line(gn_win, 3, 20, TRUE);
  3572. X                    break;
  3573. X                }
  3574. X                /* FALLTHRU */
  3575. X            case WRITE_OK:
  3576. X                got_it++;
  3577. X                break;
  3578. X        }
  3579. X        if (got_it)
  3580. X            break;
  3581. X    }
  3582. X    werase(gn_win);
  3583. X    wrefresh(gn_win);
  3584. X    delwin(gn_win);
  3585. X
  3586. X    return(list);
  3587. X}
  3588. X
  3589. X/*
  3590. X * Prompt for the Unix command line to be used as an external file
  3591. X * transfer program.  Since expand() is used, it returns a pointer to
  3592. X * a static area.
  3593. X */
  3594. X
  3595. static char *
  3596. get_extrnl(up)
  3597. int up;
  3598. X{
  3599. X    WINDOW *ge_win, *newwin();
  3600. X    char *ans, *cmd, *get_str(), *expand();
  3601. X    void st_line();
  3602. X
  3603. X    touchwin(stdscr);
  3604. X    refresh();
  3605. X    st_line("");
  3606. X                    /* prompt for command line */
  3607. X    ge_win = newwin(7, 70, 5, 5);
  3608. X    mvwaddstr(ge_win, 3, 4, "Enter Unix command: ");
  3609. X    box(ge_win, VERT, HORZ);
  3610. X
  3611. X    if (up)
  3612. X        mvwattrstr(ge_win, 0, 3, A_BOLD, " Send (external) ");
  3613. X    else
  3614. X        mvwattrstr(ge_win, 0, 3, A_BOLD, " Receive (external) ");
  3615. X
  3616. X    wmove(ge_win, 3, 24);
  3617. X    wrefresh(ge_win);
  3618. X                    /* get the line */
  3619. X    ans = get_str(ge_win, 60, "", "\n");
  3620. X    if (ans == NULL || *ans == '\0')
  3621. X        cmd = NULL;
  3622. X    else
  3623. X        cmd = expand(ans);
  3624. X
  3625. X    werase(ge_win);
  3626. X    wrefresh(ge_win);
  3627. X    delwin(ge_win);
  3628. X    return(cmd);
  3629. X}
  3630. END_OF_FILE
  3631. if test 7412 -ne `wc -c <'x_menu.c'`; then
  3632.     echo shar: \"'x_menu.c'\" unpacked with wrong size!
  3633. fi
  3634. # end of 'x_menu.c'
  3635. fi
  3636. if test -f 'xmodem.c' -a "${1}" != "-c" ; then 
  3637.   echo shar: Will not clobber existing file \"'xmodem.c'\"
  3638. else
  3639. echo shar: Extracting \"'xmodem.c'\" \(8800 characters\)
  3640. sed "s/^X//" >'xmodem.c' <<'END_OF_FILE'
  3641. X/*
  3642. X * Miscellaneous routines to support the xmodem file transfer protocols.
  3643. X */
  3644. X
  3645. X#define TMP_FILE    "trunXXXXXX"
  3646. X
  3647. X#include <stdio.h>
  3648. X#include <signal.h>
  3649. X#include <sys/types.h>
  3650. X#include <sys/stat.h>
  3651. X#include "config.h"
  3652. X#include "misc.h"
  3653. X#include "param.h"
  3654. X#include "xmodem.h"
  3655. X
  3656. X#ifdef BSD
  3657. X#include <setjmp.h>
  3658. jmp_buf gl_buf, rl_buf;
  3659. X#endif /* BSD */
  3660. X
  3661. static int uid_link(), uid_unlink();
  3662. X
  3663. X/*
  3664. X * Calculate the CRC for the given buffer
  3665. X */
  3666. X
  3667. unsigned short
  3668. calc_crc(buf, len)
  3669. unsigned char *buf;
  3670. int len;
  3671. X{
  3672. X    register int i;
  3673. X    unsigned short crc;
  3674. X    static unsigned short crctab[256] = {
  3675. X    0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
  3676. X    0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
  3677. X    0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
  3678. X    0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
  3679. X    0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
  3680. X    0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
  3681. X    0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
  3682. X    0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
  3683. X    0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
  3684. X    0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
  3685. X    0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
  3686. X    0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
  3687. X    0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
  3688. X    0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
  3689. X    0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
  3690. X    0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
  3691. X    0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
  3692. X    0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
  3693. X    0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
  3694. X    0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
  3695. X    0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
  3696. X    0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
  3697. X    0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
  3698. X    0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
  3699. X    0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
  3700. X    0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
  3701. X    0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
  3702. X    0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
  3703. X    0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
  3704. X    0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
  3705. X    0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
  3706. X    0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
  3707. X
  3708. X    crc = 0;
  3709. X    for (i=0; i<len; i++)
  3710. X        crc = (crc<<8) ^ crctab[(crc>>8) ^ *buf++];
  3711. X
  3712. X    return(crc);
  3713. X}
  3714. X
  3715. X/*
  3716. X * Calculate the checksum for the given buffer.
  3717. X */
  3718. X
  3719. unsigned char
  3720. calc_sum(buf, len)
  3721. unsigned char *buf;
  3722. int len;
  3723. X{
  3724. X    unsigned char sum;
  3725. X
  3726. X    sum = 0;
  3727. X    while (--len >= 0)
  3728. X        sum += *buf++;
  3729. X
  3730. X    return(sum);
  3731. X}
  3732. X
  3733. X/*
  3734. X * Get a single character from the line with a specified time-out period
  3735. X * in seconds.  If the function times-out, it returns a -1.
  3736. X */
  3737. X
  3738. static int gl_flag;
  3739. static int gl_force();
  3740. X
  3741. int
  3742. getc_line(sec)
  3743. unsigned int sec;
  3744. X{
  3745. X    extern int fd;
  3746. X    char c;
  3747. X    unsigned int alarm();
  3748. X
  3749. X    signal(SIGALRM, (SIG_TYPE(*) ()) gl_force);
  3750. X    gl_flag = 0;
  3751. X
  3752. X    alarm(sec);
  3753. X
  3754. X#ifdef BSD
  3755. X    if (setjmp(gl_buf))
  3756. X        return(-1);
  3757. X#endif /* BSD */
  3758. X
  3759. X    if (read(fd, &c, 1) <= 0) {
  3760. X        alarm(0);
  3761. X        return(-1);
  3762. X    }
  3763. X    if (gl_flag)
  3764. X        return(-1);
  3765. X    alarm(0);
  3766. X    return(c & 0xff);
  3767. X}
  3768. X
  3769. X/* ARGSUSED */
  3770. static int
  3771. gl_force(dummy)
  3772. int dummy;
  3773. X{
  3774. X#ifdef BSD
  3775. X    longjmp(gl_buf, 1);
  3776. X#else /* BSD */
  3777. X    signal(SIGALRM, (SIG_TYPE(*) ()) gl_force);
  3778. X    gl_flag = 1;
  3779. X    return(0);
  3780. X#endif /* BSD */
  3781. X}
  3782. X
  3783. X/*
  3784. X * Same as above, but reads a bunch of characters.  The return code is
  3785. X * now just a success/fail indicator.
  3786. X */
  3787. X
  3788. static int rl_flag;
  3789. static int rl_force();
  3790. X
  3791. int
  3792. fread_line(buf, len, sec)
  3793. unsigned char *buf;
  3794. unsigned int len, sec;
  3795. X{
  3796. X    extern int fd;
  3797. X    int n;
  3798. X    unsigned int try, alarm();
  3799. X
  3800. X    signal(SIGALRM, (SIG_TYPE(*) ()) rl_force);
  3801. X    rl_flag = 0;
  3802. X
  3803. X    alarm(sec);
  3804. X    while (len) {
  3805. X                    /* read at most CLIST_SIZ chars */
  3806. X        try = (len > CLIST_SIZ) ? CLIST_SIZ : len;
  3807. X#ifdef BSD
  3808. X        if (setjmp(rl_buf))
  3809. X            return(-1);
  3810. X#endif /* BSD */
  3811. X        if ((n = read(fd, (char *) buf, try)) <= 0) {
  3812. X            alarm(0);
  3813. X            return(-1);
  3814. X        }
  3815. X        if (rl_flag)
  3816. X            return(-1);
  3817. X        len -= n;
  3818. X        buf = buf + n;
  3819. X    }
  3820. X    alarm(0);
  3821. X    return(0);
  3822. X}
  3823. X
  3824. X/* ARGSUSED */
  3825. static int
  3826. rl_force(dummy)
  3827. int dummy;
  3828. X{
  3829. X#ifdef BSD
  3830. X    longjmp(rl_buf, 1);
  3831. X#else /* BSD */
  3832. X    signal(SIGALRM, (SIG_TYPE(*) ()) rl_force);
  3833. X    rl_flag = 1;
  3834. X    return(0);
  3835. X#endif /* BSD */
  3836. X}
  3837. X
  3838. X/*
  3839. X * Put a character on the TTY line.  This serves no useful purpose other
  3840. X * than making the code look pretty.
  3841. X */
  3842. X
  3843. int
  3844. putc_line(c)
  3845. unsigned char c;
  3846. X{
  3847. X    extern int fd;
  3848. X
  3849. X    return(write(fd, (char *) &c, 1));
  3850. X}
  3851. X
  3852. X/*
  3853. X * Cancel the file transfer.  Send several ^X's to the remote, followed
  3854. X * by an equal number of backspaces (in case they have already aborted and
  3855. X * we're really at the command line).
  3856. X */
  3857. X
  3858. void
  3859. cancel_xfer(up)
  3860. int up;
  3861. X{
  3862. X    extern char file_name[15];
  3863. X
  3864. X    if (!up && !strcmp(param->abort, "DELETE"))
  3865. X        unlink(file_name);
  3866. X
  3867. X    putc_line(CAN);
  3868. X    putc_line(CAN);
  3869. X    putc_line(CAN);
  3870. X    putc_line(BS);
  3871. X    putc_line(BS);
  3872. X    putc_line(BS);
  3873. X    return;
  3874. X}
  3875. X
  3876. X/*
  3877. X * Shorten a file to a predetermined length.  Used to remove the ^Z
  3878. X * padding from the end of files.  (Heaven help us, if one day a binary
  3879. X * file actually has ^Z's as part of the end of the file).
  3880. X */
  3881. X
  3882. int
  3883. fix_length(file, len)
  3884. char *file;
  3885. long len;
  3886. X{
  3887. X    FILE *fp, *tempfp, *uid_fopen();
  3888. X    register int num;
  3889. X    char *mktemp(), tempfile[128], buf[BUFSIZ], *strcpy();
  3890. X    char *s, *strrchr(), *strcat();
  3891. X    struct stat stbuf;
  3892. X
  3893. X    if (stat(file, &stbuf) < 0)
  3894. X        return(1);
  3895. X                    /* see if we have any work to do */
  3896. X    if (len >= stbuf.st_size)
  3897. X        return(0);
  3898. X
  3899. X#ifdef HAVE_TRUNCATE
  3900. X    return(uid_truncate(file, len));
  3901. X#else /* HAVE_TRUNCATE */
  3902. X
  3903. X    if (!(fp = uid_fopen(file, "r")))
  3904. X        return(1);
  3905. X
  3906. X    /*
  3907. X     * The temporary file should be in the same directory as the
  3908. X     * file being received because otherwise we'd have no way of
  3909. X     * guaranteeing they would be in the same file system.  (Hard
  3910. X     * links across different file systems aren't allowed).
  3911. X     */
  3912. X    strcpy(tempfile, file);
  3913. X    if (s = strrchr(tempfile, '/'))
  3914. X        *++s = '\0';
  3915. X    else
  3916. X        strcpy(tempfile, "./");
  3917. X
  3918. X    strcat(tempfile, TMP_FILE);
  3919. X    mktemp(tempfile);
  3920. X
  3921. X    if (!(tempfp = uid_fopen(tempfile, "w"))) {
  3922. X        fclose(fp);
  3923. X        return(1);
  3924. X    }
  3925. X
  3926. X    while (len != 0L) {
  3927. X        num = (len > BUFSIZ) ? BUFSIZ : (int) len;
  3928. X        fread(buf, sizeof(char), num, fp);
  3929. X        if (fwrite(buf, sizeof(char), num, tempfp) != num) {
  3930. X            fclose(fp);
  3931. X            fclose(tempfp);
  3932. X            return(1);
  3933. X        }
  3934. X        len -= (unsigned int) num;
  3935. X    }
  3936. X
  3937. X    fclose(fp);
  3938. X    fclose(tempfp);
  3939. X
  3940. X    if (uid_unlink(file) < 0)
  3941. X        return(1);
  3942. X
  3943. X    if (uid_link(tempfile, file) < 0)
  3944. X        return(1);
  3945. X
  3946. X    if (uid_unlink(tempfile) < 0)
  3947. X        return(1);
  3948. X
  3949. X    return(0);
  3950. X#endif /* HAVE_TRUNCATE */
  3951. X}
  3952. X
  3953. static int
  3954. uid_link(path1, path2)
  3955. char *path1, *path2;
  3956. X{
  3957. X    int ret;
  3958. X
  3959. X#ifdef SETUID_BROKE
  3960. X    int status;
  3961. X    void _exit();
  3962. X
  3963. X    switch(fork()) {
  3964. X        case 0:
  3965. X            setuid(getuid());
  3966. X            setgid(getgid());
  3967. X            _exit(link(path1, path2));
  3968. X        case -1:
  3969. X            fprintf(stderr, "uid_link: Can't fork\n");
  3970. X            return(-1);
  3971. X        default:
  3972. X            if (wait(&status) == -1) {
  3973. X                fprintf(stderr, "uid_link: wait failed\n");
  3974. X                return(-1);
  3975. X            }
  3976. X            ret = status >> 8;
  3977. X    }
  3978. X#else /* SETUID_BROKE */
  3979. X    int euid, egid;
  3980. X
  3981. X    euid = geteuid();
  3982. X    egid = getegid();
  3983. X
  3984. X    setuid(getuid());
  3985. X    setgid(getgid());
  3986. X
  3987. X    ret = link(path1, path2);
  3988. X
  3989. X    setuid(euid);
  3990. X    setgid(egid);
  3991. X#endif /* SETUID_BROKE */
  3992. X    return(ret);
  3993. X}
  3994. X
  3995. static int
  3996. uid_unlink(path)
  3997. char *path;
  3998. X{
  3999. X    int ret;
  4000. X
  4001. X#ifdef SETUID_BROKE
  4002. X    int status;
  4003. X    void _exit();
  4004. X
  4005. X    switch(fork()) {
  4006. X        case 0:
  4007. X            setuid(getuid());
  4008. X            setgid(getgid());
  4009. X            _exit(unlink(path));
  4010. X        case -1:
  4011. X            fprintf(stderr, "uid_unlink: Can't fork\n");
  4012. X            return(-1);
  4013. X        default:
  4014. X            if (wait(&status) == -1) {
  4015. X                fprintf(stderr, "uid_unlink: wait failed\n");
  4016. X                return(-1);
  4017. X            }
  4018. X            ret = status >> 8;
  4019. X    }
  4020. X#else /* SETUID_BROKE */
  4021. X    int euid, egid;
  4022. X
  4023. X    euid = geteuid();
  4024. X    egid = getegid();
  4025. X
  4026. X    setuid(getuid());
  4027. X    setgid(getgid());
  4028. X
  4029. X    ret = unlink(path);
  4030. X
  4031. X    setuid(euid);
  4032. X    setgid(egid);
  4033. X#endif /* SETUID_BROKE */
  4034. X    return(ret);
  4035. X}
  4036. X
  4037. X#ifdef HAVE_TRUNCATE
  4038. static int
  4039. uid_truncate(path, len)
  4040. char *path;
  4041. long len;
  4042. X{
  4043. X    int ret;
  4044. X
  4045. X#ifdef SETUID_BROKE
  4046. X    int status;
  4047. X    void _exit();
  4048. X
  4049. X    switch(fork()) {
  4050. X        case 0:
  4051. X            setuid(getuid());
  4052. X            setgid(getgid());
  4053. X            _exit(truncate(path, len));
  4054. X        case -1:
  4055. X            fprintf(stderr, "uid_truncate: Can't fork\n");
  4056. X            return(-1);
  4057. X        default:
  4058. X            if (wait(&status) == -1) {
  4059. X                fprintf(stderr, "uid_truncate: wait failed\n");
  4060. X                return(-1);
  4061. X            }
  4062. X            ret = status >> 8;
  4063. X    }
  4064. X#else /* SETUID_BROKE */
  4065. X    int euid, egid;
  4066. X
  4067. X    euid = geteuid();
  4068. X    egid = getegid();
  4069. X
  4070. X    setuid(getuid());
  4071. X    setgid(getgid());
  4072. X
  4073. X    ret = truncate(path, len);
  4074. X
  4075. X    setuid(euid);
  4076. X    setgid(egid);
  4077. X#endif /* SETUID_BROKE */
  4078. X    return(ret);
  4079. X}
  4080. X#endif /* HAVE_TRUNCATE */
  4081. END_OF_FILE
  4082. if test 8800 -ne `wc -c <'xmodem.c'`; then
  4083.     echo shar: \"'xmodem.c'\" unpacked with wrong size!
  4084. fi
  4085. # end of 'xmodem.c'
  4086. fi
  4087. echo shar: End of archive 3 \(of 6\).
  4088. cp /dev/null ark3isdone
  4089. MISSING=""
  4090. for I in 1 2 3 4 5 6 ; do
  4091.     if test ! -f ark${I}isdone ; then
  4092.     MISSING="${MISSING} ${I}"
  4093.     fi
  4094. done
  4095. if test "${MISSING}" = "" ; then
  4096.     echo You have unpacked all 6 archives.
  4097.     rm -f ark[1-9]isdone
  4098. else
  4099.     echo You still need to unpack the following archives:
  4100.     echo "        " ${MISSING}
  4101. fi
  4102. ##  End of shell archive.
  4103. exit 0
  4104.