ecushm.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438
  1. /*+-------------------------------------------------------------------------
  2. ecushm.c - shared memory handler for ecu xmtr/rcvr comm
  3. wht@wht.net
  4. Signal handler purists will surely get aneurisms from looking
  5. at what we do in here, but any OS that doesn't properly push
  6. a stack frame for a signal event just won't play here. We even
  7. fork() in a signal handler. That ought to make some of the
  8. brethren gag.
  9. Defined functions:
  10. shm_done()
  11. shm_init()
  12. shmr_notify_termecu()
  13. shmr_notify_xmtr_of_DCD_loss()
  14. shmr_notify_xmtr_of_telnet_close()
  15. shmr_notify_zmodem_frame()
  16. shmr_process_rcvr_SIGUSR2()
  17. shmx_make_rcvr_sleep(seconds)
  18. shmx_process_xmtr_SIGUSR2()
  19. shmx_set_rcvr_log(logfilename, append_flag, raw_flag, flush_each)
  20. shmx_unpause_rcvr()
  21. Sforzando (It., sfohr-tsahn'-doh). A direction to perform the
  22. tone or chord with special stress, or marked and sudden emphasis.
  23. -- Schirmer Pronouncing POCKET-MANUAL of Musical Terms, 1936.
  24. --------------------------------------------------------------------------*/
  25. /*+:EDITS:*/
  26. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  27. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  28. /*:09-28-1996-23:57-wht@yuriatin-SHMR_NOTIFY_TELNET */
  29. /*:09-28-1996-23:52-wht@yuriatin-add shmr_notify_xmtr_of_telnet_close */
  30. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  31. /*:12-06-1995-13:30-wht@n4hgf-termecu w/errno -1 consideration */
  32. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  33. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  34. /*:11-12-1995-01:57-wht@gyro-eliminate peurile shmx_connect */
  35. /*:11-12-1995-01:49-wht@gyro-add SHMR_NOTIFY_TERMECU code */
  36. /*:11-12-1995-00:33-wht@gyro-init new rcvr_ansi_filter */
  37. /*:10-14-1995-17:08-wht@kepler-'struct termio' to 'struct TERMIO' */
  38. /*:08-27-1995-06:35-wht@n4hgf-init shm->Lrtscts_val */
  39. /*:05-04-1994-04:39-wht@n4hgf-ECU release 3.30 */
  40. /*:11-25-1993-14:43-wht@n4hgf-3.281-fix typo in shm_done shmctl statement */
  41. /*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  42. /*:09-10-1992-04:34-wht@n4hgf-add rcvrdisp semaphore */
  43. /*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  44. /*:12-15-1991-14:22-wht@n4hgf-autorz initialized */
  45. /*:12-13-1991-04:16-wht@n4hgf-move bell_notify_state to shm */
  46. /*:11-12-1991-18:02-wht@n4hgf-remove obsolete shmx_rc_report */
  47. /*:11-11-1991-14:59-wht@n4hgf-shmr_notify_xmtr_of_DCD_loss */
  48. /*:07-25-1991-12:56-wht@n4hgf-ECU release 3.10 */
  49. /*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  50. #include "ecu.h"
  51. #if defined(CFG_MmapSHM)
  52. #include <sys/mman.h>
  53. #else
  54. #include <sys/ipc.h>
  55. #include <sys/shm.h>
  56. #ifdef CFG_SemWithShm
  57. #include <sys/sem.h>
  58. union semun
  59. {
  60. int val;
  61. struct semid_ds *buf;
  62. UINT16 *array;
  63. } semctl_arg;
  64. #endif /* CFG_SemWithShm */
  65. #endif /* CFG_MmapSHM */
  66. /* xmtr to rcvr cmds */
  67. #define SHMX_MAKE_RCVR_SLEEP 1 /* sleep xi1=#seconds */
  68. #define SHMX_UNPAUSE 2 /* no-op to un-pause() rcvr */
  69. #define SHMX_SET_RCVR_LOG 3 /* log file manipulations
  70. * xi1=append,xi2=raw,xs1=n ame */
  71. /* rcvr to xmtr cmds */
  72. #define SHMR_NOTIFY_DCD_LOSS 1 /* rcvr detected DCD loss */
  73. #define SHMR_NOTIFY_ZMODEM 2 /* rcvr detected ZMODEM frame */
  74. #define SHMR_NOTIFY_TERMECU 3 /* rcvr go bye-bye */
  75. #define SHMR_NOTIFY_TELNET 4 /* rcvr detected telnet close */
  76. extern char rcvr_log_file[]; /* if rcvr_log!= 0,log filename */
  77. extern int rcvr_log; /* rcvr log active if != 0 */
  78. extern FILE *rcvr_log_fp; /* rcvr log file */
  79. extern int rcvr_log_raw; /* if true, log all, else filter ctl chrs */
  80. extern int rcvr_log_flusheach;
  81. extern int rcvr_log_append; /* if true, append, else scratch */
  82. extern int rcvr_log_gen_title;
  83. ECU_SDS FAR *shm; /* shared segment pointer */
  84. #if !defined(CFG_MmapSHM)
  85. key_t shm_key;
  86. int shm_shmid;
  87. #endif
  88. /*+-------------------------------------------------------------------------
  89. shm_init()
  90. Called by parent process (xmtr) to initialize environment
  91. --------------------------------------------------------------------------*/
  92. void
  93. shm_init()
  94. {
  95. UINT save_LINESxCOLS;
  96. extern UINT LINESxCOLS;
  97. /*
  98. * see the comments in ecu.h titled "Communication line variables" for
  99. * an explanation of the following
  100. */
  101. if (sizeof(shm->Ltiobuf) < sizeof(struct TERMIO))
  102. {
  103. pprintf("ecushm.h LTIOBUF_SIZE needs to be increased to %d.\n",
  104. sizeof(struct TERMIO));
  105. pputs("Please change it, remake and notify wht@wht.net.\n");
  106. errno = -1;
  107. termecu(TERMECU_CONFIG_ERROR);
  108. }
  109. #if defined(CFG_MmapSHM)
  110. shm = (ECU_SDS *) mmap(0, sizeof(ECU_SDS), PROT_READ | PROT_WRITE,
  111. MAP_ANON | MAP_INHERIT | MAP_SHARED, -1, 0);
  112. if (shm == (ECU_SDS *) - 1)
  113. {
  114. perror("mmap");
  115. termecu(TERMECU_IPC_ERROR);
  116. }
  117. #else
  118. shm_key = 0xEC000000L | getpid();
  119. if ((shm_shmid = shmget(shm_key, sizeof(ECU_SDS), IPC_CREAT | 0600)) < 0)
  120. {
  121. perror("shmget");
  122. termecu(TERMECU_IPC_ERROR);
  123. }
  124. if ((shm = (ECU_SDS FAR *) shmat(shm_shmid, (char FAR *)0, 0)) ==
  125. (ECU_SDS FAR *) - 1)
  126. {
  127. perror("shmat");
  128. termecu(TERMECU_IPC_ERROR);
  129. }
  130. #ifdef CFG_SemWithShm
  131. if ((shm->rcvrdisp_semid = semget(shm_key, 1, IPC_CREAT | 0600)) < 0)
  132. {
  133. perror("semget");
  134. termecu(TERMECU_IPC_ERROR);
  135. }
  136. rcvrdisp_v(); /* first unlock */
  137. #endif /* CFG_SemWithShm */
  138. #endif /* CFG_MmapSHM */
  139. /*
  140. * see the comments in ecu.h titled "Communication line variables" for
  141. * an explanation of the following
  142. */
  143. Ltermio = (struct TERMIO *)shm->Ltiobuf; /* cover termio buffer */
  144. shm->xcmd = 0; /* signal from xmtr to rcvr SIGUSR2 */
  145. shm->xi1 = 0; /* parameters */
  146. shm->xi2 = 0;
  147. shm->xs1[0] = 0;
  148. shm->rcmd = 0; /* signal from rcvr to xmtr SIGUSR2 */
  149. shm->ri1 = 0; /* parameters */
  150. shm->ri2 = 0;
  151. shm->rs1[0] = 0;
  152. shm->rcvd_chars = 0L;
  153. shm->rcvd_chars_this_connect = 0L;
  154. shm->bell_notify_state = 1; /* default to want bell notify */
  155. shm->Ldcdwatch = 0; /* default DCD watcher to off */
  156. shm->Lrtscts_val = 0; /* default no hw flow control */
  157. shm->autorz = 1; /* default automatic rz to on */
  158. shm->cursor_y = 0;
  159. shm->cursor_x = 0;
  160. shm->friend_space[0] = 0;
  161. save_LINESxCOLS = LINESxCOLS;
  162. LINESxCOLS = sizeof(shm->screen); /* avoid trap */
  163. spaces((char *)shm->screen, sizeof(shm->screen));
  164. LINESxCOLS = save_LINESxCOLS;
  165. shm->rcvrdisp_ptr = shm->rcvrdisp_buffer;
  166. shm->rcvrdisp_count = 0;
  167. #if defined(CFG_NoAnsiEmulation)
  168. shm->rcvr_ansi_filter = 0;
  169. #else
  170. shm->rcvr_ansi_filter = 1;
  171. #endif
  172. } /* end of shm_init */
  173. /*+-------------------------------------------------------------------------
  174. shm_done() -- finished with shm/sem -- clean up
  175. We might make a trip thru here with the xmtr and rcvr, so
  176. ignore EINVAL
  177. --------------------------------------------------------------------------*/
  178. void
  179. shm_done()
  180. {
  181. #if defined(CFG_MmapSHM)
  182. munmap(shm, sizeof(ECU_SDS));
  183. #else
  184. #ifdef CFG_SemWithShm
  185. union semun semctl_arg;
  186. if (semctl(shm->rcvrdisp_semid, 0, IPC_RMID, &semctl_arg) &&
  187. (errno != EINVAL))
  188. {
  189. pperror("semctl IPC_RMID");
  190. }
  191. #endif /* CFG_SemWithShm */
  192. if (shmctl(shm_shmid, IPC_RMID, (struct shmid_ds *)0) && (errno != EINVAL))
  193. pperror("shmctl IPC_RMID");
  194. #endif
  195. } /* end of shm_done */
  196. /*+-------------------------------------------------------------------------
  197. shmx_make_rcvr_sleep(seconds)
  198. --------------------------------------------------------------------------*/
  199. void
  200. shmx_make_rcvr_sleep(seconds)
  201. int seconds;
  202. {
  203. shm->xcmd = SHMX_MAKE_RCVR_SLEEP;
  204. shm->xi1 = seconds;
  205. kill_rcvr_process(SIGUSR2);
  206. } /* end of shmx_make_rcvr_sleep */
  207. /*+-------------------------------------------------------------------------
  208. shmx_unpause_rcvr() - no-op SIGUSR2 to unpause receiver
  209. --------------------------------------------------------------------------*/
  210. void
  211. shmx_unpause_rcvr()
  212. {
  213. shm->xcmd = SHMX_UNPAUSE;
  214. kill_rcvr_process(SIGUSR2);
  215. } /* end of shmx_unpause_rcvr */
  216. /*+-------------------------------------------------------------------------
  217. shmx_set_rcvr_log(logfilename,append_flag,raw_flag,flush_each)
  218. null logfilename stops logging
  219. append_flag says whether to open for write or append
  220. raw_flag says whether or not to filter non-printable chars or not
  221. (NL not filtered)
  222. --------------------------------------------------------------------------*/
  223. void
  224. shmx_set_rcvr_log(logfilename, append_flag, raw_flag, flush_each)
  225. char *logfilename;
  226. int append_flag;
  227. int raw_flag;
  228. int flush_each;
  229. {
  230. shm->xcmd = SHMX_SET_RCVR_LOG;
  231. shm->xi1 = append_flag;
  232. shm->xi2 = raw_flag;
  233. shm->xi3 = flush_each;
  234. strcpy(shm->xs1, logfilename);
  235. kill_rcvr_process(SIGUSR2);
  236. } /* end of shmx_set_rcvr_log */
  237. /*+-------------------------------------------------------------------------
  238. shmr_notify_xmtr_of_telnet_close()
  239. --------------------------------------------------------------------------*/
  240. void
  241. shmr_notify_xmtr_of_telnet_close()
  242. {
  243. shm->rcmd = SHMR_NOTIFY_TELNET;
  244. kill(shm->xmtr_pid, SIGUSR2);
  245. while (1)
  246. pause(); /* wait for xmtr to kill */
  247. } /* end of shmr_notify_xmtr_of_telnet_close */
  248. /*+-------------------------------------------------------------------------
  249. shmr_notify_xmtr_of_DCD_loss()
  250. --------------------------------------------------------------------------*/
  251. void
  252. shmr_notify_xmtr_of_DCD_loss()
  253. {
  254. shm->rcmd = SHMR_NOTIFY_DCD_LOSS;
  255. kill(shm->xmtr_pid, SIGUSR2);
  256. } /* end of shmr_notify_xmtr_of_DCD_loss */
  257. /*+-------------------------------------------------------------------------
  258. shmr_notify_zmodem_frame()
  259. --------------------------------------------------------------------------*/
  260. void
  261. shmr_notify_zmodem_frame()
  262. {
  263. shm->rcmd = SHMR_NOTIFY_ZMODEM; /* rcvr detected ZMODEM frame */
  264. kill(shm->xmtr_pid, SIGUSR2);
  265. } /* end of shmr_notify_zmodem_frame */
  266. /*+-------------------------------------------------------------------------
  267. shmr_notify_termecu()
  268. --------------------------------------------------------------------------*/
  269. void
  270. shmr_notify_termecu()
  271. {
  272. shm->rcmd = SHMR_NOTIFY_TERMECU; /* rcvr go bye-bye */
  273. kill(shm->xmtr_pid, SIGUSR2);
  274. } /* end of shmr_notify_termecu */
  275. /*+-------------------------------------------------------------------------
  276. shmx_process_xmtr_SIGUSR2()
  277. --------------------------------------------------------------------------*/
  278. void
  279. shmx_process_xmtr_SIGUSR2()
  280. {
  281. int rcmd;
  282. int ri1, ri2;
  283. int argc;
  284. char *cp;
  285. char **argv;
  286. UINT32 colors_save;
  287. int lchar;
  288. int success_flag;
  289. rcmd = shm->rcmd;
  290. shm->rcmd = 0;
  291. ri1 = shm->ri1;
  292. ri2 = shm->ri2;
  293. switch (rcmd)
  294. {
  295. case SHMR_NOTIFY_DCD_LOSS:
  296. lzero_length_read_detected();
  297. break;
  298. case SHMR_NOTIFY_TELNET:
  299. {
  300. extern UINT32 colors_current;
  301. UINT32 colors_at_entry = colors_current;
  302. kill_rcvr_process(SIGKILL);
  303. fputs("\r\n", se);
  304. setcolor(colors_notify);
  305. fputs("[session terminated by remote host]", se);
  306. setcolor(colors_at_entry);
  307. fputs("\r\n", se);
  308. DCE_now_on_hook(); /* does a lclose */
  309. }
  310. break;
  311. case SHMR_NOTIFY_ZMODEM:
  312. kill_rcvr_process(SIGUSR1);
  313. success_flag = 0;
  314. while ((lchar = lgetc_timeout(100L)) >= 0)
  315. {
  316. fputc(lchar, se);
  317. if (lchar == '\n')
  318. {
  319. success_flag = 1;
  320. break;
  321. }
  322. }
  323. if (!success_flag)
  324. fputs("\r\n", se);
  325. colors_save = colors_current;
  326. setcolor(colors_notify);
  327. fputs("[automatic rz]", se);
  328. setcolor(colors_save);
  329. fputs("\r\n", se);
  330. argc = 1;
  331. cp = "rz";
  332. argv = &cp;
  333. receive_files_from_remote(argc, argv);
  334. start_rcvr_process(1);
  335. break;
  336. case SHMR_NOTIFY_TERMECU:
  337. termecu(TERMECU_RCVR_FATAL_ERROR);
  338. break;
  339. }
  340. } /* end of shmx_process_xmtr_SIGUSR2 */
  341. /*+-------------------------------------------------------------------------
  342. shmr_process_rcvr_SIGUSR2()
  343. --------------------------------------------------------------------------*/
  344. void
  345. shmr_process_rcvr_SIGUSR2()
  346. {
  347. int xcmd;
  348. int xi1, xi2, xi3;
  349. char xs1[SHM_STRLEN];
  350. xcmd = shm->xcmd;
  351. shm->xcmd = 0;
  352. xi1 = shm->xi1;
  353. xi2 = shm->xi2;
  354. xi3 = shm->xi3;
  355. strcpy(xs1, shm->xs1);
  356. switch (xcmd)
  357. {
  358. case SHMX_MAKE_RCVR_SLEEP:
  359. sleep(xi1);
  360. break;
  361. case SHMX_SET_RCVR_LOG:
  362. if (rcvr_log) /* if already logging */
  363. {
  364. if (!rcvr_log_raw)
  365. LOGPUTC('\n', rcvr_log_fp);
  366. fclose(rcvr_log_fp);
  367. rcvr_log = 0;
  368. }
  369. if (strlen(xs1) == 0) /* if all we wanted was to stop log
  370. * ... */
  371. break; /* ... then quit */
  372. rcvr_log_gen_title = 1;
  373. rcvr_log = 1;
  374. rcvr_log_append = xi1;
  375. rcvr_log_raw = xi2;
  376. rcvr_log_flusheach = xi3;
  377. strcpy(rcvr_log_file, xs1);
  378. rcvr_log_open();
  379. break;
  380. case SHMX_UNPAUSE:
  381. break;
  382. }
  383. } /* end of shmr_process_rcvr_SIGUSR2 */
  384. /* end of ecushm.c */
  385. /* vi: set tabstop=4 shiftwidth=4: */