plchostd.c 17 KB

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