plchostd2.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. * Copyright (c) 2014 I2SE GmbH
  5. *
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or
  9. * without modification, are permitted (subject to the limitations
  10. * in the disclaimer below) provided that the following conditions
  11. * are met:
  12. *
  13. * * Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. *
  16. * * Redistributions in binary form must reproduce the above
  17. * copyright notice, this list of conditions and the following
  18. * disclaimer in the documentation and/or other materials
  19. * provided with the distribution.
  20. *
  21. * * Neither the name of Qualcomm Atheros nor the names of
  22. * its contributors may be used to endorse or promote products
  23. * derived from this software without specific prior written
  24. * permission.
  25. *
  26. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  27. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  28. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  29. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  30. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  31. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  32. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  33. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  34. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  35. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  36. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  37. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  38. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  39. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40. *
  41. *--------------------------------------------------------------------*/
  42. /*====================================================================*"
  43. *
  44. * plchostd2.c -
  45. *
  46. *
  47. * Contributor(s):
  48. * Charles Maier
  49. * Nathaniel Houghton
  50. * Stefan Wahren
  51. *
  52. *--------------------------------------------------------------------*/
  53. /*====================================================================*"
  54. * system header files;
  55. *--------------------------------------------------------------------*/
  56. #include <unistd.h>
  57. #include <stdlib.h>
  58. #include <limits.h>
  59. #include <string.h>
  60. #include <ctype.h>
  61. #include <memory.h>
  62. #include <signal.h>
  63. #include <errno.h>
  64. #include <sys/socket.h>
  65. #include <sys/un.h>
  66. /*====================================================================*
  67. * custom header files;
  68. *--------------------------------------------------------------------*/
  69. #include "../ether/channel.h"
  70. #include "../tools/getoptv.h"
  71. #include "../tools/putoptv.h"
  72. #include "../tools/memory.h"
  73. #include "../tools/number.h"
  74. #include "../tools/types.h"
  75. #include "../tools/flags.h"
  76. #include "../tools/files.h"
  77. #include "../tools/error.h"
  78. #include "../ram/nvram.h"
  79. #include "../ram/sdram.h"
  80. #include "../nvm/nvm.h"
  81. #include "../pib/pib.h"
  82. #include "../plc/plc.h"
  83. /*====================================================================*
  84. * custom source files;
  85. *--------------------------------------------------------------------*/
  86. #ifndef MAKEFILE
  87. #include "../plc/BootDevice2.c"
  88. #include "../plc/BootFirmware2.c"
  89. #include "../plc/BootParameters2.c"
  90. #include "../plc/chipset.c"
  91. #include "../plc/Confirm.c"
  92. #include "../plc/Devices.c"
  93. #include "../plc/Failure.c"
  94. #include "../plc/FlashDevice2.c"
  95. #include "../plc/FlashSoftloader.c"
  96. #include "../plc/FlashFirmware.c"
  97. #include "../plc/FlashParameters.c"
  98. #include "../plc/FlashNVM.c"
  99. #include "../plc/HostActionResponse.c"
  100. #include "../plc/InitDevice2.c"
  101. #include "../plc/ModuleRead.c"
  102. #include "../plc/ModuleSpec.c"
  103. #include "../plc/ModuleSession.c"
  104. #include "../plc/ModuleWrite.c"
  105. #include "../plc/ModuleCommit.c"
  106. #include "../plc/LocalDevices.c"
  107. #include "../plc/NVMSelect.c"
  108. #include "../plc/ReadFirmware2.c"
  109. #include "../plc/ReadParameters2.c"
  110. #include "../plc/Request.c"
  111. #include "../plc/ResetDevice.c"
  112. #include "../plc/ReadMME.c"
  113. #include "../plc/SendMME.c"
  114. #include "../plc/WaitForReset.c"
  115. #include "../plc/WaitForStart.c"
  116. #include "../plc/WriteMEM.c"
  117. #include "../plc/WriteNVM.c"
  118. #include "../plc/WritePIB.c"
  119. #include "../plc/WriteExecuteFirmware2.c"
  120. #include "../plc/WriteExecuteParameters2.c"
  121. #include "../plc/WriteExecuteApplet2.c"
  122. #include "../plc/Platform.c"
  123. #include "../plc/WriteFirmware2.c"
  124. #include "../plc/PLCSelect.c"
  125. #endif
  126. #ifndef MAKEFILE
  127. #include "../tools/getoptv.c"
  128. #include "../tools/putoptv.c"
  129. #include "../tools/version.c"
  130. #include "../tools/uintspec.c"
  131. #include "../tools/checkfilename.c"
  132. #include "../tools/hexdecode.c"
  133. #include "../tools/hexstring.c"
  134. #include "../tools/todigit.c"
  135. #include "../tools/hexdump.c"
  136. #include "../tools/checksum32.c"
  137. #include "../tools/fdchecksum32.c"
  138. #include "../tools/error.c"
  139. #include "../tools/strfbits.c"
  140. #include "../tools/typename.c"
  141. #endif
  142. #ifndef MAKEFILE
  143. #include "../ether/openchannel.c"
  144. #include "../ether/closechannel.c"
  145. #include "../ether/readpacket.c"
  146. #include "../ether/sendpacket.c"
  147. #include "../ether/channel.c"
  148. #endif
  149. #ifndef MAKEFILE
  150. #include "../mme/EthernetHeader.c"
  151. #include "../mme/QualcommHeader.c"
  152. #include "../mme/UnwantedMessage.c"
  153. #include "../mme/MMECode.c"
  154. #ifdef AR7x00
  155. #include "../mme/QualcommHeader1.c"
  156. #endif
  157. #endif
  158. #ifndef MAKEFILE
  159. #include "../key/keys.c"
  160. #endif
  161. #ifndef MAKEFILE
  162. #include "../nvm/nvmfile2.c"
  163. #endif
  164. #ifndef MAKEFILE
  165. #include "../pib/pibfile2.c"
  166. #include "../pib/pibpeek2.c"
  167. #endif
  168. /*====================================================================*
  169. * program constants;
  170. *--------------------------------------------------------------------*/
  171. #define MESSAGE "Starting PLC Host Server\n"
  172. #define SOCKETNAME "/tmp/socket"
  173. #define NEWPIB "user.pib"
  174. #define NEWNVM "user.nvm"
  175. /*====================================================================*
  176. * program variables;
  177. *--------------------------------------------------------------------*/
  178. static bool done = false;
  179. /*====================================================================*
  180. *
  181. * void terminate (signo_t signal);
  182. *
  183. *
  184. *
  185. * Contributor(s):
  186. * Charles Maier
  187. *
  188. *--------------------------------------------------------------------*/
  189. static void terminate (signo_t signal)
  190. {
  191. done = true;
  192. return;
  193. }
  194. /*====================================================================*
  195. *
  196. * signed opensocket (char const * socketname);
  197. *
  198. *
  199. *
  200. * Contributor(s):
  201. * Charles Maier
  202. *
  203. *--------------------------------------------------------------------*/
  204. static signed opensocket (char const * socketname)
  205. {
  206. signed fd;
  207. struct sockaddr_un sockaddr_un =
  208. {
  209. #if defined (__OpenBSD__) || defined (__NetBSD__) || defined (__APPLE__) || defined (__FreeBSD__)
  210. 0,
  211. #endif
  212. AF_UNIX,
  213. "/tmp/socket"
  214. };
  215. strncpy (sockaddr_un.sun_path, socketname, sizeof (sockaddr_un.sun_path));
  216. #if defined (__OpenBSD__) || defined (__NetBSD__) || defined (__APPLE__) || defined (__FreeBSD__)
  217. sockaddr_un.sun_len = SUN_LEN (&sockaddr_un);
  218. #endif
  219. if (unlink (sockaddr_un.sun_path))
  220. {
  221. if (errno != ENOENT)
  222. {
  223. error (1, errno, "%s", sockaddr_un.sun_path);
  224. }
  225. }
  226. if ((fd = socket (AF_UNIX, SOCK_DGRAM, 0)) == -1)
  227. {
  228. error (1, errno, "%s", sockaddr_un.sun_path);
  229. }
  230. if (bind (fd, (struct sockaddr *)(&sockaddr_un), sizeof (sockaddr_un)) == -1)
  231. {
  232. error (1, errno, "%s", sockaddr_un.sun_path);
  233. }
  234. if (chmod (sockaddr_un.sun_path, 0666) == -1)
  235. {
  236. error (1, errno, "%s", sockaddr_un.sun_path);
  237. }
  238. return (fd);
  239. }
  240. /*====================================================================*
  241. *
  242. * signed function (struct plc * plc, char const * socket);
  243. *
  244. * wait indefinitely for VS_HOST_ACTION messages; service the device
  245. * only; it will stop dead - like a bug! - on error;
  246. *
  247. *
  248. * Contributor(s):
  249. * Charles Maier
  250. *
  251. *--------------------------------------------------------------------*/
  252. signed function (struct plc * plc, char const * socket)
  253. {
  254. struct channel * channel = (struct channel *)(plc->channel);
  255. struct message * message = (struct message *)(plc->message);
  256. static char const * actions [] =
  257. {
  258. "start device",
  259. "store firmware",
  260. "store parameters",
  261. "update host",
  262. "config memory",
  263. "restore defaults",
  264. "unknown"
  265. };
  266. #ifndef __GNUC__
  267. #pragma pack (push,1)
  268. #endif
  269. struct __packed vs_host_action_ind
  270. {
  271. struct ethernet_hdr ethernet;
  272. struct qualcomm_hdr qualcomm;
  273. uint8_t MACTION;
  274. uint8_t MAJOR_VERSION;
  275. uint8_t MINOR_VERSION;
  276. }
  277. * indicate = (struct vs_host_action_ind *) (message);
  278. #ifndef __GNUC__
  279. #pragma pack (pop)
  280. #endif
  281. signed fd = opensocket (socket);
  282. char firmware [PLC_VERSION_STRING];
  283. char const * FactoryNVM = plc->NVM.name;
  284. char const * FactoryPIB = plc->PIB.name;
  285. unsigned action;
  286. signed status;
  287. write (fd, MESSAGE, strlen (MESSAGE));
  288. while (!done)
  289. {
  290. status = ReadMME (plc, 0, (VS_HOST_ACTION | MMTYPE_IND));
  291. if (status < 0)
  292. {
  293. break;
  294. }
  295. if (status < 1)
  296. {
  297. continue;
  298. }
  299. action = indicate->MACTION;
  300. if (action < SIZEOF (actions))
  301. {
  302. fprintf(stderr, "plchostd2: action = %s\n", actions[action]);
  303. }
  304. else
  305. {
  306. fprintf(stderr, "plchostd2: action = %d\n", action);
  307. }
  308. memcpy (channel->peer, indicate->ethernet.OSA, sizeof (channel->peer));
  309. if (HostActionResponse (plc))
  310. {
  311. return (-1);
  312. }
  313. if (action == 0x00)
  314. {
  315. if (BootDevice2 (plc))
  316. {
  317. return (-1);
  318. }
  319. if (WaitForStart (plc, firmware, sizeof (firmware)))
  320. {
  321. return (-1);
  322. }
  323. if (_anyset (plc->flags, PLC_FLASH_DEVICE))
  324. {
  325. FlashDevice2 (plc, (PLC_COMMIT_FORCE | PLC_COMMIT_NORESET | PLC_COMMIT_FACTPIB));
  326. }
  327. continue;
  328. }
  329. if (action == 0x01)
  330. {
  331. close (plc->NVM.file);
  332. if (ReadFirmware2 (plc))
  333. {
  334. return (-1);
  335. }
  336. if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1)
  337. {
  338. error (1, errno, "%s", plc->NVM.name);
  339. }
  340. continue;
  341. }
  342. if (action == 0x02)
  343. {
  344. close (plc->PIB.file);
  345. if (ReadParameters2 (plc))
  346. {
  347. return (-1);
  348. }
  349. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  350. {
  351. error (1, errno, "%s", plc->PIB.name);
  352. }
  353. if (ResetDevice (plc))
  354. {
  355. return (-1);
  356. }
  357. continue;
  358. }
  359. if (action == 0x03)
  360. {
  361. close (plc->PIB.file);
  362. if (ReadParameters2 (plc))
  363. {
  364. return (-1);
  365. }
  366. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  367. {
  368. error (1, errno, "%s", plc->PIB.name);
  369. }
  370. close (plc->NVM.file);
  371. if (ReadFirmware2 (plc))
  372. {
  373. return (-1);
  374. }
  375. if ((plc->NVM.file = open (plc->NVM.name = plc->nvm.name, O_BINARY|O_RDONLY)) == -1)
  376. {
  377. error (1, errno, "%s", plc->NVM.name);
  378. }
  379. if (ResetDevice (plc))
  380. {
  381. return (-1);
  382. }
  383. continue;
  384. }
  385. if (action == 0x04)
  386. {
  387. if (InitDevice2 (plc))
  388. {
  389. return (-1);
  390. }
  391. continue;
  392. }
  393. if (action == 0x05)
  394. {
  395. close (plc->NVM.file);
  396. if ((plc->NVM.file = open (plc->NVM.name = FactoryNVM, O_BINARY|O_RDONLY)) == -1)
  397. {
  398. error (1, errno, "%s", plc->NVM.name);
  399. }
  400. close (plc->PIB.file);
  401. if ((plc->PIB.file = open (plc->PIB.name = FactoryPIB, O_BINARY|O_RDONLY)) == -1)
  402. {
  403. error (1, errno, "%s", plc->PIB.name);
  404. }
  405. if (ResetDevice (plc))
  406. {
  407. return (-1);
  408. }
  409. continue;
  410. }
  411. if (action == 0x06)
  412. {
  413. close (plc->PIB.file);
  414. if (ReadParameters2 (plc))
  415. {
  416. return (-1);
  417. }
  418. if ((plc->PIB.file = open (plc->PIB.name = plc->pib.name, O_BINARY|O_RDONLY)) == -1)
  419. {
  420. error (1, errno, "%s", plc->PIB.name);
  421. }
  422. continue;
  423. }
  424. error (0, ENOSYS, "Host Action 0x%02X", action);
  425. }
  426. close (fd);
  427. return (0);
  428. }
  429. /*====================================================================*
  430. *
  431. * int main (int argc, char const * argv[]);
  432. *
  433. * parse command line, populate plc structure and perform selected
  434. * operations; show help summary when asked; see getoptv and putoptv
  435. * to understand command line parsing and help summary display; see
  436. * plc.h for the definition of struct plc;
  437. *
  438. *
  439. *--------------------------------------------------------------------*/
  440. int main (int argc, char const * argv [])
  441. {
  442. extern struct channel channel;
  443. extern void terminate (signo_t);
  444. static char const * optv [] =
  445. {
  446. "dFi:n:N:p:P:qS:t:vw:x",
  447. "-N file -P file [-S file]",
  448. "Qualcomm Atheros Panther/Lynx PLC Host Daemon",
  449. "d\texecute in background as daemon",
  450. "F [F]\tflash [force] non-volatile memory",
  451. #if defined (WINPCAP) || defined (LIBPCAP)
  452. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  453. #else
  454. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  455. #endif
  456. "n f\tread firmware from device into file (f)",
  457. "N f\tfirmware file is (f)",
  458. "p f\tread parameters from device into file (f)",
  459. "P f\tparameter file is (f)",
  460. "q\tquiet mode",
  461. "S f\tsoftloader file is (f)",
  462. "t n\tread timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  463. "v\tverbose mode",
  464. "w n\twakeup every (n) seconds [" LITERAL (PLC_LONGTIME) "]",
  465. "x\texit on error",
  466. (char const *) (0)
  467. };
  468. #include "../plc/plc.c"
  469. struct sigaction sa;
  470. char const * socketname = SOCKETNAME;
  471. signed c;
  472. if (getenv (PLCDEVICE))
  473. {
  474. #if defined (WINPCAP) || defined (LIBPCAP)
  475. channel.ifindex = atoi (getenv (PLCDEVICE));
  476. #else
  477. channel.ifname = strdup (getenv (PLCDEVICE));
  478. #endif
  479. }
  480. optind = 1;
  481. plc.timer = PLC_LONGTIME;
  482. while ((c = getoptv (argc, argv, optv)) != -1)
  483. {
  484. switch (c)
  485. {
  486. case 'd':
  487. _setbits (plc.flags, PLC_DAEMON);
  488. break;
  489. case 'F':
  490. _setbits (plc.module, (VS_MODULE_MAC | VS_MODULE_PIB));
  491. if (_anyset (plc.flags, PLC_FLASH_DEVICE))
  492. {
  493. _setbits (plc.module, VS_MODULE_FORCE);
  494. }
  495. _setbits (plc.flags, PLC_FLASH_DEVICE);
  496. break;
  497. case 'i':
  498. #if defined (WINPCAP) || defined (LIBPCAP)
  499. channel.ifindex = atoi (optarg);
  500. #else
  501. channel.ifname = optarg;
  502. #endif
  503. break;
  504. case 'N':
  505. if (!checkfilename (optarg))
  506. {
  507. error (1, EINVAL, "%s", optarg);
  508. }
  509. if ((plc.NVM.file = open (plc.NVM.name = optarg, O_BINARY|O_RDONLY)) == -1)
  510. {
  511. error (1, errno, "%s", plc.NVM.name);
  512. }
  513. if (nvmfile2 (&plc.NVM))
  514. {
  515. error (1, errno, "Bad firmware file: %s", plc.NVM.name);
  516. }
  517. _setbits (plc.flags, PLC_WRITE_MAC);
  518. break;
  519. case 'n':
  520. if (!checkfilename (optarg))
  521. {
  522. error (1, EINVAL, "%s", optarg);
  523. }
  524. if ((plc.nvm.file = open (plc.nvm.name = optarg, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  525. {
  526. error (1, errno, "%s", plc.nvm.name);
  527. }
  528. break;
  529. case 'P':
  530. if (!checkfilename (optarg))
  531. {
  532. error (1, EINVAL, "%s", optarg);
  533. }
  534. if ((plc.PIB.file = open (plc.PIB.name = optarg, O_BINARY|O_RDONLY)) == -1)
  535. {
  536. error (1, errno, "%s", plc.PIB.name);
  537. }
  538. if (pibfile2 (&plc.PIB))
  539. {
  540. error (1, errno, "Bad parameter file: %s", plc.PIB.name);
  541. }
  542. _setbits (plc.flags, PLC_WRITE_PIB);
  543. break;
  544. case 'p':
  545. if (!checkfilename (optarg))
  546. {
  547. error (1, EINVAL, "%s", optarg);
  548. }
  549. if ((plc.pib.file = open (plc.pib.name = optarg, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  550. {
  551. error (1, errno, "%s", plc.pib.name);
  552. }
  553. break;
  554. case 'q':
  555. _setbits (channel.flags, CHANNEL_SILENCE);
  556. _setbits (plc.flags, PLC_SILENCE);
  557. break;
  558. case 'S':
  559. if (!checkfilename (optarg))
  560. {
  561. error (1, EINVAL, "%s", optarg);
  562. }
  563. if ((plc.SFT.file = open (plc.SFT.name = optarg, O_BINARY|O_RDONLY)) == -1)
  564. {
  565. error (1, errno, "%s", plc.SFT.name);
  566. }
  567. if (nvmfile2 (&plc.SFT))
  568. {
  569. error (1, errno, "Bad firmware file: %s", plc.SFT.name);
  570. }
  571. break;
  572. case 't':
  573. channel.timeout = (signed)(uintspec (optarg, 0, UINT_MAX));
  574. break;
  575. case 'v':
  576. _setbits (channel.flags, CHANNEL_VERBOSE);
  577. _setbits (plc.flags, PLC_VERBOSE);
  578. break;
  579. case 'w':
  580. plc.timer = (unsigned)(uintspec (optarg, 1, 3600));
  581. break;
  582. case 'x':
  583. _setbits (plc.flags, PLC_BAILOUT);
  584. break;
  585. default:
  586. break;
  587. }
  588. }
  589. argc -= optind;
  590. argv += optind;
  591. if (argc)
  592. {
  593. error (1, ENOTSUP, ERROR_TOOMANY);
  594. }
  595. if (plc.NVM.file == -1)
  596. {
  597. error (1, ECANCELED, "No host NVM file named");
  598. }
  599. if (plc.PIB.file == -1)
  600. {
  601. error (1, ECANCELED, "No host PIB file named");
  602. }
  603. if (plc.SFT.file == -1)
  604. {
  605. if (_anyset (plc.flags, PLC_FLASH_DEVICE))
  606. {
  607. error (1, ECANCELED, "No Softloader file named");
  608. }
  609. }
  610. if (plc.nvm.file == -1)
  611. {
  612. if ((plc.nvm.file = open (plc.nvm.name = NEWNVM, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  613. {
  614. error (1, errno, "%s", plc.nvm.name);
  615. }
  616. }
  617. if (plc.pib.file == -1)
  618. {
  619. if ((plc.pib.file = open (plc.pib.name = NEWPIB, O_BINARY|O_CREAT|O_RDWR|O_TRUNC, FILE_FILEMODE)) == -1)
  620. {
  621. error (1, errno, "%s", plc.pib.name);
  622. }
  623. }
  624. #ifndef WIN32
  625. if (_anyset (plc.flags, PLC_DAEMON))
  626. {
  627. pid_t pid = fork ();
  628. if (pid < 0)
  629. {
  630. error (1, errno, "Can't start daemon");
  631. }
  632. if (pid > 0)
  633. {
  634. exit (0);
  635. }
  636. }
  637. memset (&sa, 0, sizeof (struct sigaction));
  638. sa.sa_handler = terminate;
  639. sigaction (SIGTERM, &sa, (struct sigaction *)(0));
  640. sigaction (SIGQUIT, &sa, (struct sigaction *)(0));
  641. sigaction (SIGTSTP, &sa, (struct sigaction *)(0));
  642. sigaction (SIGINT, &sa, (struct sigaction *)(0));
  643. sigaction (SIGHUP, &sa, (struct sigaction *)(0));
  644. #endif
  645. openchannel (&channel);
  646. if (!(plc.message = malloc (sizeof (* plc.message))))
  647. {
  648. error (1, errno, PLC_NOMEMORY);
  649. }
  650. function (&plc, socketname);
  651. free (plc.message);
  652. closechannel (&channel);
  653. exit (0);
  654. }