Bug Summary

File:bozo/bnode.c
Location:line 155, column 5
Description:Value stored to 'code' is never read

Annotated Source Code

1/*
2 * Copyright 2000, International Business Machines Corporation and others.
3 * All Rights Reserved.
4 *
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
8 */
9
10#include <afsconfig.h>
11#include <afs/param.h>
12
13#include <afs/procmgmt.h>
14#include <roken.h>
15
16#include <stddef.h>
17
18#include <lwp.h>
19#include <rx/rx.h>
20#include <afs/audit.h>
21#include <afs/afsutil.h>
22#include <afs/fileutil.h>
23
24#include "bnode.h"
25#include "bosprototypes.h"
26
27#ifndef WCOREDUMP
28#define WCOREDUMP(x)((x) & 0200) ((x) & 0200)
29#endif
30
31#define BNODE_LWP_STACKSIZE(16 * 1024) (16 * 1024)
32
33int bnode_waiting = 0;
34static PROCESS bproc_pid; /* pid of waker-upper */
35static struct bnode *allBnodes = 0; /* list of all bnodes */
36static struct bnode_proc *allProcs = 0; /* list of all processes for which we're waiting */
37static struct bnode_type *allTypes = 0; /* list of registered type handlers */
38
39static struct bnode_stats {
40 int weirdPids;
41} bnode_stats;
42
43extern const char *DoCore;
44#ifndef AFS_NT40_ENV
45extern char **environ; /* env structure */
46#endif
47
48int hdl_notifier(struct bnode_proc *tp);
49
50/* Remember the name of the process, if any, that failed last */
51static void
52RememberProcName(struct bnode_proc *ap)
53{
54 struct bnode *tbnodep;
55
56 tbnodep = ap->bnode;
57 if (tbnodep->lastErrorName) {
58 free(tbnodep->lastErrorName);
59 tbnodep->lastErrorName = NULL((void *)0);
60 }
61 if (ap->coreName) {
62 tbnodep->lastErrorName = (char *)malloc(strlen(ap->coreName) + 1);
63 strcpy(tbnodep->lastErrorName, ap->coreName);
64 }
65}
66
67/* utility for use by BOP_HASCORE functions to determine where a core file might
68 * be stored.
69 */
70int
71bnode_CoreName(struct bnode *abnode, char *acoreName, char *abuffer)
72{
73 if (DoCore) {
74 strcpy(abuffer, DoCore);
75 strcat(abuffer, "/");
76 strcat(abuffer, AFSDIR_CORE_FILE"core");
77 } else
78 strcpy(abuffer, AFSDIR_SERVER_CORELOG_FILEPATHgetDirPath(AFSDIR_SERVER_CORELOG_FILEPATH_ID));
79 if (acoreName) {
80 strcat(abuffer, acoreName);
81 strcat(abuffer, ".");
82 }
83 strcat(abuffer, abnode->name);
84 return 0;
85}
86
87/* save core file, if any */
88static void
89SaveCore(struct bnode *abnode, struct bnode_proc
90 *aproc)
91{
92 char tbuffer[256];
93 struct stat tstat;
94 afs_int32 code = 0;
95 char *corefile = NULL((void *)0);
96#ifdef BOZO_SAVE_CORES
97 struct timeval Start;
98 struct tm *TimeFields;
99 char FileName[256];
100#endif
101
102 /* Linux always appends the PID to core dumps from threaded processes, so
103 * we have to scan the directory to find core files under another name. */
104 if (DoCore) {
105 strcpy(tbuffer, DoCore);
106 strcat(tbuffer, "/");
107 strcat(tbuffer, AFSDIR_CORE_FILE"core");
108 } else
109 code = stat(AFSDIR_SERVER_CORELOG_FILEPATHgetDirPath(AFSDIR_SERVER_CORELOG_FILEPATH_ID), &tstat);
110 if (code) {
111 DIR *logdir;
112 struct dirent *file;
113 size_t length;
114 unsigned long pid;
115 const char *coredir = AFSDIR_LOGS_DIR"/usr/local/var/openafs/logs";
116
117 if (DoCore)
118 coredir = DoCore;
119
120 logdir = opendir(coredir);
121 if (logdir == NULL((void *)0))
122 return;
123 while ((file = readdir(logdir)) != NULL((void *)0)) {
124 if (strncmp(file->d_name, "core.", 5) != 0)
125 continue;
126 pid = atol(file->d_name + 5);
127 if (pid == aproc->pid) {
128 length = strlen(coredir) + strlen(file->d_name) + 2;
129 corefile = malloc(length);
130 if (corefile == NULL((void *)0)) {
131 closedir(logdir);
132 return;
133 }
134 snprintf(corefile, length, "%s/%s", coredir, file->d_name);
135 code = 0;
136 break;
137 }
138 }
139 closedir(logdir);
140 } else {
141 corefile = strdup(tbuffer);
142 }
143 if (code)
144 return;
145
146 bnode_CoreName(abnode, aproc->coreName, tbuffer);
147#ifdef BOZO_SAVE_CORES
148 FT_GetTimeOfDay(&Start, 0);
149 TimeFields = localtime(&Start.tv_sec);
150 sprintf(FileName, "%s.%d%02d%02d%02d%02d%02d", tbuffer,
151 TimeFields->tm_year + 1900, TimeFields->tm_mon + 1, TimeFields->tm_mday,
152 TimeFields->tm_hour, TimeFields->tm_min, TimeFields->tm_sec);
153 strcpy(tbuffer, FileName);
154#endif
155 code = renamefile(corefile, tbuffer);
Value stored to 'code' is never read
156 free(corefile);
157}
158
159int
160bnode_GetString(struct bnode *abnode, char *abuffer,
161 afs_int32 alen)
162{
163 return BOP_GETSTRING(abnode, abuffer, alen)((*(abnode)->ops->getstring)((abnode),(abuffer), (alen)
))
;
164}
165
166int
167bnode_GetParm(struct bnode *abnode, afs_int32 aindex,
168 char *abuffer, afs_int32 alen)
169{
170 return BOP_GETPARM(abnode, aindex, abuffer, alen)((*(abnode)->ops->getparm)((abnode),(aindex),(abuffer),
(alen)))
;
171}
172
173int
174bnode_GetStat(struct bnode *abnode, afs_int32 * astatus)
175{
176 return BOP_GETSTAT(abnode, astatus)((*(abnode)->ops->getstat)((abnode),(astatus)));
177}
178
179int
180bnode_RestartP(struct bnode *abnode)
181{
182 return BOP_RESTARTP(abnode)((*(abnode)->ops->restartp)((abnode)));
183}
184
185static int
186bnode_Check(struct bnode *abnode)
187{
188 if (abnode->flags & BNODE_WAIT4) {
189 abnode->flags &= ~BNODE_WAIT4;
190 LWP_NoYieldSignal(abnode)LWP_INTERNALSIGNAL(abnode, 0);
191 }
192 return 0;
193}
194
195/* tell if an instance has a core file */
196int
197bnode_HasCore(struct bnode *abnode)
198{
199 return BOP_HASCORE(abnode)((*(abnode)->ops->hascore)((abnode)));
200}
201
202/* wait for all bnodes to stabilize */
203int
204bnode_WaitAll(void)
205{
206 struct bnode *tb;
207 afs_int32 code;
208 afs_int32 stat;
209
210 retry:
211 for (tb = allBnodes; tb; tb = tb->next) {
212 bnode_Hold(tb);
213 code = BOP_GETSTAT(tb, &stat)((*(tb)->ops->getstat)((tb),(&stat)));
214 if (code) {
215 bnode_Release(tb);
216 return code;
217 }
218 if (stat != tb->goal) {
219 tb->flags |= BNODE_WAIT4;
220 LWP_WaitProcess(tb);
221 bnode_Release(tb);
222 goto retry;
223 }
224 bnode_Release(tb);
225 }
226 return 0;
227}
228
229/* wait until bnode status is correct */
230int
231bnode_WaitStatus(struct bnode *abnode, int astatus)
232{
233 afs_int32 code;
234 afs_int32 stat;
235
236 bnode_Hold(abnode);
237 while (1) {
238 /* get the status */
239 code = BOP_GETSTAT(abnode, &stat)((*(abnode)->ops->getstat)((abnode),(&stat)));
240 if (code)
241 return code;
242
243 /* otherwise, check if we're done */
244 if (stat == astatus) {
245 bnode_Release(abnode);
246 return 0; /* done */
247 }
248 if (astatus != abnode->goal) {
249 bnode_Release(abnode);
250 return -1; /* no longer our goal, don't keep waiting */
251 }
252 /* otherwise, block */
253 abnode->flags |= BNODE_WAIT4;
254 LWP_WaitProcess(abnode);
255 }
256}
257
258int
259bnode_SetStat(struct bnode *abnode, int agoal)
260{
261 abnode->goal = agoal;
262 bnode_Check(abnode);
263 BOP_SETSTAT(abnode, agoal)((*(abnode)->ops->setstat)((abnode),(agoal)));
264 abnode->flags &= ~BNODE_ERRORSTOP0x10;
265 return 0;
266}
267
268int
269bnode_SetGoal(struct bnode *abnode, int agoal)
270{
271 abnode->goal = agoal;
272 bnode_Check(abnode);
273 return 0;
274}
275
276int
277bnode_SetFileGoal(struct bnode *abnode, int agoal)
278{
279 if (abnode->fileGoal == agoal)
280 return 0; /* already done */
281 abnode->fileGoal = agoal;
282 WriteBozoFile(0);
283 return 0;
284}
285
286/* apply a function to all bnodes in the system */
287int
288bnode_ApplyInstance(int (*aproc) (struct bnode *tb, void *), void *arock)
289{
290 struct bnode *tb, *nb;
291 afs_int32 code;
292
293 for (tb = allBnodes; tb; tb = nb) {
294 nb = tb->next;
295 code = (*aproc) (tb, arock);
296 if (code)
297 return code;
298 }
299 return 0;
300}
301
302struct bnode *
303bnode_FindInstance(char *aname)
304{
305 struct bnode *tb;
306
307 for (tb = allBnodes; tb; tb = tb->next) {
308 if (!strcmp(tb->name, aname))
309 return tb;
310 }
311 return NULL((void *)0);
312}
313
314static struct bnode_type *
315FindType(char *aname)
316{
317 struct bnode_type *tt;
318
319 for (tt = allTypes; tt; tt = tt->next) {
320 if (!strcmp(tt->name, aname))
321 return tt;
322 }
323 return (struct bnode_type *)0;
324}
325
326int
327bnode_Register(char *atype, struct bnode_ops *aprocs, int anparms)
328{
329 struct bnode_type *tt;
330
331 for (tt = allTypes; tt; tt = tt->next) {
332 if (!strcmp(tt->name, atype))
333 break;
334 }
335 if (!tt) {
336 tt = (struct bnode_type *)malloc(sizeof(struct bnode_type));
337 memset(tt, 0, sizeof(struct bnode_type));
338 tt->next = allTypes;
339 allTypes = tt;
340 tt->name = atype;
341 }
342 tt->ops = aprocs;
343 return 0;
344}
345
346afs_int32
347bnode_Create(char *atype, char *ainstance, struct bnode ** abp, char *ap1,
348 char *ap2, char *ap3, char *ap4, char *ap5, char *notifier,
349 int fileGoal, int rewritefile)
350{
351 struct bnode_type *type;
352 struct bnode *tb;
353 char *notifierpath = NULL((void *)0);
354 struct stat tstat;
355
356 if (bnode_FindInstance(ainstance))
357 return BZEXISTS(39427L);
358 type = FindType(atype);
359 if (!type)
360 return BZBADTYPE(39434L);
361
362 if (notifier && strcmp(notifier, NONOTIFIER"__NONOTIFIER__")) {
363 /* construct local path from canonical (wire-format) path */
364 if (ConstructLocalBinPath(notifier, &notifierpath)) {
365 bozo_Log("BNODE-Create: Notifier program path invalid '%s'\n",
366 notifier);
367 return BZNOCREATE(39428L);
368 }
369
370 if (stat(notifierpath, &tstat)) {
371 bozo_Log("BNODE-Create: Notifier program '%s' not found\n",
372 notifierpath);
373 free(notifierpath);
374 return BZNOCREATE(39428L);
375 }
376 }
377 tb = (*type->ops->create) (ainstance, ap1, ap2, ap3, ap4, ap5);
378 if (!tb) {
379 free(notifierpath);
380 return BZNOCREATE(39428L);
381 }
382 tb->notifier = notifierpath;
383 *abp = tb;
384 tb->type = type;
385
386 /* The fs_create above calls bnode_InitBnode() which always sets the
387 ** fileGoal to BSTAT_NORMAL .... overwrite it with whatever is passed into
388 ** this function as a parameter... */
389 tb->fileGoal = fileGoal;
390
391 bnode_SetStat(tb, tb->goal); /* nudge it once */
392
393 if (rewritefile != 0)
394 WriteBozoFile(0);
395
396 return 0;
397}
398
399int
400bnode_DeleteName(char *ainstance)
401{
402 struct bnode *tb;
403
404 tb = bnode_FindInstance(ainstance);
405 if (!tb)
406 return BZNOENT(39425L);
407
408 return bnode_Delete(tb);
409}
410
411int
412bnode_Hold(struct bnode *abnode)
413{
414 abnode->refCount++;
415 return 0;
416}
417
418int
419bnode_Release(struct bnode *abnode)
420{
421 abnode->refCount--;
422 if (abnode->refCount == 0 && abnode->flags & BNODE_DELETE8) {
423 abnode->flags &= ~BNODE_DELETE8; /* we're going for it */
424 bnode_Delete(abnode);
425 }
426 return 0;
427}
428
429int
430bnode_Delete(struct bnode *abnode)
431{
432 afs_int32 code;
433 struct bnode **lb, *ub;
434 afs_int32 temp;
435
436 if (abnode->refCount != 0) {
437 abnode->flags |= BNODE_DELETE8;
438 return 0;
439 }
440
441 /* make sure the bnode is idle before zapping */
442 bnode_Hold(abnode);
443 code = BOP_GETSTAT(abnode, &temp)((*(abnode)->ops->getstat)((abnode),(&temp)));
444 bnode_Release(abnode);
445 if (code)
446 return code;
447 if (temp != BSTAT_SHUTDOWN0)
448 return BZBUSY(39426L);
449
450 /* all clear to zap */
451 for (lb = &allBnodes, ub = *lb; ub; lb = &ub->next, ub = *lb) {
452 if (ub == abnode) {
453 /* unthread it from the list */
454 *lb = ub->next;
455 break;
456 }
457 }
458 free(abnode->name); /* do this first, since bnode fields may be bad after BOP_DELETE */
459 code = BOP_DELETE(abnode)((*(abnode)->ops->delete)((abnode))); /* don't play games like holding over this one */
460 WriteBozoFile(0);
461 return code;
462}
463
464/* function to tell if there's a timeout coming up */
465int
466bnode_PendingTimeout(struct bnode *abnode)
467{
468 return (abnode->flags & BNODE_NEEDTIMEOUT1);
469}
470
471/* function called to set / clear periodic bnode wakeup times */
472int
473bnode_SetTimeout(struct bnode *abnode, afs_int32 atimeout)
474{
475 if (atimeout != 0) {
476 abnode->nextTimeout = FT_ApproxTime() + atimeout;
477 abnode->flags |= BNODE_NEEDTIMEOUT1;
478 abnode->period = atimeout;
479 IOMGR_Cancel(bproc_pid);
480 } else {
481 abnode->flags &= ~BNODE_NEEDTIMEOUT1;
482 }
483 return 0;
484}
485
486/* used by new bnode creation code to format bnode header */
487int
488bnode_InitBnode(struct bnode *abnode, struct bnode_ops *abnodeops,
489 char *aname)
490{
491 struct bnode **lb, *nb;
492
493 /* format the bnode properly */
494 memset(abnode, 0, sizeof(struct bnode));
495 abnode->ops = abnodeops;
496 abnode->name = (char *)malloc(strlen(aname) + 1);
497 if (!abnode->name)
498 return ENOMEM12;
499 strcpy(abnode->name, aname);
500 abnode->flags = BNODE_ACTIVE2;
501 abnode->fileGoal = BSTAT_NORMAL1;
502 abnode->goal = BSTAT_SHUTDOWN0;
503
504 /* put the bnode at the end of the list so we write bnode file in same order */
505 for (lb = &allBnodes, nb = *lb; nb; lb = &nb->next, nb = *lb);
506 *lb = abnode;
507
508 return 0;
509}
510
511static int
512DeleteProc(struct bnode_proc *abproc)
513{
514 struct bnode_proc **pb, *tb;
515 struct bnode_proc *nb;
516
517 for (pb = &allProcs, tb = *pb; tb; pb = &tb->next, tb = nb) {
518 nb = tb->next;
519 if (tb == abproc) {
520 *pb = nb;
521 free(tb);
522 return 0;
523 }
524 }
525 return BZNOENT(39425L);
526}
527
528/* bnode lwp executes this code repeatedly */
529static void *
530bproc(void *unused)
531{
532 afs_int32 code;
533 struct bnode *tb;
534 afs_int32 temp;
535 struct bnode_proc *tp;
536 struct bnode *nb;
537 int options; /* must not be register */
538 struct timeval tv;
539 int setAny;
540 int status;
541
542 while (1) {
543 /* first figure out how long to sleep for */
544 temp = 0x7fffffff; /* afs_int32 time; maxint doesn't work in select */
545 setAny = 0;
546 for (tb = allBnodes; tb; tb = tb->next) {
547 if (tb->flags & BNODE_NEEDTIMEOUT1) {
548 if (tb->nextTimeout < temp) {
549 setAny = 1;
550 temp = tb->nextTimeout;
551 }
552 }
553 }
554 /* now temp has the time at which we should wakeup next */
555
556 /* sleep */
557 if (setAny)
558 temp -= FT_ApproxTime(); /* how many seconds until next event */
559 else
560 temp = 999999;
561 if (temp > 0) {
562 tv.tv_sec = temp;
563 tv.tv_usec = 0;
564 code = IOMGR_Select(0, 0, 0, 0, &tv);
565 } else
566 code = 0; /* fake timeout code */
567
568 /* figure out why we woke up; child exit or timeouts */
569 FT_GetTimeOfDay(&tv, 0); /* must do the real gettimeofday once and a while */
570 temp = tv.tv_sec;
571
572 /* check all bnodes to see which ones need timeout events */
573 for (tb = allBnodes; tb; tb = nb) {
574 if ((tb->flags & BNODE_NEEDTIMEOUT1) && temp > tb->nextTimeout) {
575 bnode_Hold(tb);
576 BOP_TIMEOUT(tb)((*(tb)->ops->timeout)((tb)));
577 bnode_Check(tb);
578 if (tb->flags & BNODE_NEEDTIMEOUT1) { /* check again, BOP_TIMEOUT could change */
579 tb->nextTimeout = FT_ApproxTime() + tb->period;
580 }
581 nb = tb->next;
582 bnode_Release(tb); /* delete may occur here */
583 } else
584 nb = tb->next;
585 }
586
587 if (code < 0) {
588 /* signalled, probably by incoming signal */
589 while (1) {
590 options = WNOHANG1;
591 bnode_waiting = options | 0x800000;
592 code = waitpid((pid_t) - 1, &status, options);
593 bnode_waiting = 0;
594 if (code == 0 || code == -1)
595 break; /* all done */
596 /* otherwise code has a process id, which we now search for */
597 for (tp = allProcs; tp; tp = tp->next)
598 if (tp->pid == code)
599 break;
600 if (tp) {
601 /* found the pid */
602 tb = tp->bnode;
603 bnode_Hold(tb);
604
605 /* count restarts in last 10 seconds */
606 if (temp > tb->rsTime + 30) {
607 /* it's been 10 seconds we've been counting */
608 tb->rsTime = temp;
609 tb->rsCount = 0;
610 }
611
612 if (WIFSIGNALED(status)(((status) & 0177) != 0177 && ((status) & 0177
) != 0)
== 0) {
613 /* exited, not signalled */
614 tp->lastExit = WEXITSTATUS(status)((status) >> 8);
615 tp->lastSignal = 0;
616 if (tp->lastExit) {
617 tb->errorCode = tp->lastExit;
618 tb->lastErrorExit = FT_ApproxTime();
619 RememberProcName(tp);
620 tb->errorSignal = 0;
621 }
622 if (tp->coreName)
623 bozo_Log("%s:%s exited with code %d\n", tb->name,
624 tp->coreName, tp->lastExit);
625 else
626 bozo_Log("%s exited with code %d\n", tb->name,
627 tp->lastExit);
628 } else {
629 /* Signal occurred, perhaps spurious due to shutdown request.
630 * If due to a shutdown request, don't overwrite last error
631 * information.
632 */
633 tp->lastSignal = WTERMSIG(status)(((status) & 0177));
634 tp->lastExit = 0;
635 if (tp->lastSignal != SIGQUIT3
636 && tp->lastSignal != SIGTERM15
637 && tp->lastSignal != SIGKILL9) {
638 tb->errorSignal = tp->lastSignal;
639 tb->lastErrorExit = FT_ApproxTime();
640 RememberProcName(tp);
641 }
642 if (tp->coreName)
643 bozo_Log("%s:%s exited on signal %d%s\n",
644 tb->name, tp->coreName, tp->lastSignal,
645 WCOREDUMP(status)((status) & 0200) ? " (core dumped)" :
646 "");
647 else
648 bozo_Log("%s exited on signal %d%s\n", tb->name,
649 tp->lastSignal,
650 WCOREDUMP(status)((status) & 0200) ? " (core dumped)" :
651 "");
652 SaveCore(tb, tp);
653 }
654 tb->lastAnyExit = FT_ApproxTime();
655
656 if (tb->notifier) {
657 bozo_Log("BNODE: Notifier %s will be called\n",
658 tb->notifier);
659 hdl_notifier(tp);
660 }
661 BOP_PROCEXIT(tb, tp)((*(tb)->ops->procexit)((tb),(tp)));
662
663 bnode_Check(tb);
664 if (tb->rsCount++ > 10) {
665 /* 10 in 10 seconds */
666 tb->flags |= BNODE_ERRORSTOP0x10;
667 bnode_SetGoal(tb, BSTAT_SHUTDOWN0);
668 bozo_Log
669 ("BNODE '%s' repeatedly failed to start, perhaps missing executable.\n",
670 tb->name);
671 }
672 bnode_Release(tb); /* bnode delete can happen here */
673 DeleteProc(tp);
674 } else
675 bnode_stats.weirdPids++;
676 }
677 }
678 }
679 return NULL((void *)0);
680}
681
682static afs_int32
683SendNotifierData(int fd, struct bnode_proc *tp)
684{
685 struct bnode *tb = tp->bnode;
686 char buffer[1000], *bufp = buffer, *buf1;
687 int len;
688
689 /*
690 * First sent out the bnode_proc struct
691 */
692 (void)sprintf(bufp, "BEGIN bnode_proc\n");
693 bufp += strlen(bufp);
694 (void)sprintf(bufp, "comLine: %s\n", tp->comLine);
695 bufp += strlen(bufp);
696 if (!(buf1 = tp->coreName))
697 buf1 = "(null)";
698 (void)sprintf(bufp, "coreName: %s\n", buf1);
699 bufp += strlen(bufp);
700 (void)sprintf(bufp, "pid: %ld\n", afs_printable_int32_ld(tp->pid));
701 bufp += strlen(bufp);
702 (void)sprintf(bufp, "lastExit: %ld\n", afs_printable_int32_ld(tp->lastExit));
703 bufp += strlen(bufp);
704#ifdef notdef
705 (void)sprintf(bufp, "lastSignal: %ld\n", afs_printable_int32_ld(tp->lastSignal));
706 bufp += strlen(bufp);
707#endif
708 (void)sprintf(bufp, "flags: %ld\n", afs_printable_int32_ld(tp->flags));
709 bufp += strlen(bufp);
710 (void)sprintf(bufp, "END bnode_proc\n");
711 bufp += strlen(bufp);
712 len = (int)(bufp - buffer);
713 if (write(fd, buffer, len) < 0) {
714 return -1;
715 }
716
717 /*
718 * Now sent out the bnode struct
719 */
720 bufp = buffer;
721 (void)sprintf(bufp, "BEGIN bnode\n");
722 bufp += strlen(bufp);
723 (void)sprintf(bufp, "name: %s\n", tb->name);
724 bufp += strlen(bufp);
725 (void)sprintf(bufp, "rsTime: %ld\n", afs_printable_int32_ld(tb->rsTime));
726 bufp += strlen(bufp);
727 (void)sprintf(bufp, "rsCount: %ld\n", afs_printable_int32_ld(tb->rsCount));
728 bufp += strlen(bufp);
729 (void)sprintf(bufp, "procStartTime: %ld\n", afs_printable_int32_ld(tb->procStartTime));
730 bufp += strlen(bufp);
731 (void)sprintf(bufp, "procStarts: %ld\n", afs_printable_int32_ld(tb->procStarts));
732 bufp += strlen(bufp);
733 (void)sprintf(bufp, "lastAnyExit: %ld\n", afs_printable_int32_ld(tb->lastAnyExit));
734 bufp += strlen(bufp);
735 (void)sprintf(bufp, "lastErrorExit: %ld\n", afs_printable_int32_ld(tb->lastErrorExit));
736 bufp += strlen(bufp);
737 (void)sprintf(bufp, "errorCode: %ld\n", afs_printable_int32_ld(tb->errorCode));
738 bufp += strlen(bufp);
739 (void)sprintf(bufp, "errorSignal: %ld\n", afs_printable_int32_ld(tb->errorSignal));
740 bufp += strlen(bufp);
741/*
742 (void) sprintf(bufp, "lastErrorName: %s\n", tb->lastErrorName);
743 bufp += strlen(bufp);
744*/
745 (void)sprintf(bufp, "goal: %d\n", tb->goal);
746 bufp += strlen(bufp);
747 (void)sprintf(bufp, "END bnode\n");
748 bufp += strlen(bufp);
749 len = (int)(bufp - buffer);
750 if (write(fd, buffer, len) < 0) {
751 return -1;
752 }
753 return 0;
754}
755
756int
757hdl_notifier(struct bnode_proc *tp)
758{
759#ifndef AFS_NT40_ENV /* NT notifier callout not yet implemented */
760 int pid;
761 struct stat tstat;
762
763 if (stat(tp->bnode->notifier, &tstat)) {
764 bozo_Log("BNODE: Failed to find notifier '%s'; ignored\n",
765 tp->bnode->notifier);
766 return (1);
767 }
768 if ((pid = fork()) == 0) {
769 FILE *fout;
770 struct bnode *tb = tp->bnode;
771
772#if defined(AFS_HPUX_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_SGI51_ENV)
773 setsid();
774#elif defined(AFS_DARWIN90_ENV)
775 setpgid(0, 0);
776#elif defined(AFS_LINUX20_ENV) || defined(AFS_AIX_ENV)
777 setpgrp();
778#else
779 setpgrp(0, 0);
780#endif
781 fout = popen(tb->notifier, "w");
782 if (fout == NULL((void *)0)) {
783 bozo_Log("BNODE: Failed to find notifier '%s'; ignored\n",
784 tb->notifier);
785 perror(tb->notifier);
786 exit(1);
787 }
788 SendNotifierData(fileno(fout)(!__isthreaded ? ((fout)->_file) : (fileno)(fout)), tp);
789 pclose(fout);
790 exit(0);
791 } else if (pid < 0) {
792 bozo_Log("Failed to fork creating process to handle notifier '%s'\n",
793 tp->bnode->notifier);
794 return -1;
795 }
796#endif /* AFS_NT40_ENV */
797 return (0);
798}
799
800/* Called by IOMGR at low priority on IOMGR's stack shortly after a SIGCHLD
801 * occurs. Wakes up bproc do redo things */
802void *
803bnode_SoftInt(void *param)
804{
805 /* int asignal = (int) param; */
806
807 IOMGR_Cancel(bproc_pid);
808 return 0;
809}
810
811/* Called at signal interrupt level; queues function to be called
812 * when IOMGR runs again.
813 */
814void
815bnode_Int(int asignal)
816{
817 if (asignal == SIGQUIT3 || asignal == SIGTERM15) {
818 IOMGR_SoftSig(bozo_ShutdownAndExit, (void *)(intptr_t)asignal);
819 } else {
820 IOMGR_SoftSig(bnode_SoftInt, (void *)(intptr_t)asignal);
821 }
822}
823
824
825/* intialize the whole system */
826int
827bnode_Init(void)
828{
829 PROCESS junk;
830 afs_int32 code;
831 struct sigaction newaction;
832 static int initDone = 0;
833
834 if (initDone)
835 return 0;
836 initDone = 1;
837 memset(&bnode_stats, 0, sizeof(bnode_stats));
838 LWP_InitializeProcessSupport(1, &junk); /* just in case */
839 IOMGR_Initialize();
840 code = LWP_CreateProcess(bproc, BNODE_LWP_STACKSIZE(16 * 1024),
841 /* priority */ 1, (void *) /* parm */ 0,
842 "bnode-manager", &bproc_pid);
843 if (code)
844 return code;
845 memset(&newaction, 0, sizeof(newaction));
846 newaction.sa_handler__sigaction_u.__sa_handler = bnode_Int;
847 code = sigaction(SIGCHLD20, &newaction, NULL((void *)0));
848 if (code)
849 return errno(* __error());
850 code = sigaction(SIGQUIT3, &newaction, NULL((void *)0));
851 if (code)
852 return errno(* __error());
853 code = sigaction(SIGTERM15, &newaction, NULL((void *)0));
854 if (code)
855 return errno(* __error());
856 return code;
857}
858
859/* free token list returned by parseLine */
860int
861bnode_FreeTokens(struct bnode_token *alist)
862{
863 struct bnode_token *nlist;
864 for (; alist; alist = nlist) {
865 nlist = alist->next;
866 free(alist->key);
867 free(alist);
868 }
869 return 0;
870}
871
872static int
873space(int x)
874{
875 if (x == 0 || x == ' ' || x == '\t' || x == '\n')
876 return 1;
877 else
878 return 0;
879}
880
881int
882bnode_ParseLine(char *aline, struct bnode_token **alist)
883{
884 char tbuffer[256];
885 char *tptr = NULL((void *)0);
886 int inToken;
887 struct bnode_token *first, *last;
888 struct bnode_token *ttok;
889 int tc;
890
891 inToken = 0; /* not copying token chars at start */
892 first = (struct bnode_token *)0;
893 last = (struct bnode_token *)0;
894 while (1) {
895 tc = *aline++;
896 if (tc == 0 || space(tc)) { /* terminating null gets us in here, too */
897 if (inToken) {
898 inToken = 0; /* end of this token */
899 *tptr++ = 0;
900 ttok =
901 (struct bnode_token *)malloc(sizeof(struct bnode_token));
902 ttok->next = (struct bnode_token *)0;
903 ttok->key = (char *)malloc(strlen(tbuffer) + 1);
904 strcpy(ttok->key, tbuffer);
905 if (last) {
906 last->next = ttok;
907 last = ttok;
908 } else
909 last = ttok;
910 if (!first)
911 first = ttok;
912 }
913 } else {
914 /* an alpha character */
915 if (!inToken) {
916 tptr = tbuffer;
917 inToken = 1;
918 }
919 if (tptr - tbuffer >= sizeof(tbuffer))
920 return -1; /* token too long */
921 *tptr++ = tc;
922 }
923 if (tc == 0) {
924 /* last token flushed 'cause space(0) --> true */
925 if (last)
926 last->next = (struct bnode_token *)0;
927 *alist = first;
928 return 0;
929 }
930 }
931}
932
933#define MAXVARGS128 128
934int
935bnode_NewProc(struct bnode *abnode, char *aexecString, char *coreName,
936 struct bnode_proc **aproc)
937{
938 struct bnode_token *tlist, *tt;
939 afs_int32 code;
940 struct bnode_proc *tp;
941 pid_t cpid;
942 char *argv[MAXVARGS128];
943 int i;
944
945 code = bnode_ParseLine(aexecString, &tlist); /* try parsing first */
946 if (code)
947 return code;
948 tp = (struct bnode_proc *)malloc(sizeof(struct bnode_proc));
949 memset(tp, 0, sizeof(struct bnode_proc));
950 tp->next = allProcs;
951 tp->bnode = abnode;
952 tp->comLine = aexecString;
953 tp->coreName = coreName; /* may be null */
954 abnode->procStartTime = FT_ApproxTime();
955 abnode->procStarts++;
956
957 /* convert linked list of tokens into argv structure */
958 for (tt = tlist, i = 0; i < (MAXVARGS128 - 1) && tt; tt = tt->next, i++) {
959 argv[i] = tt->key;
960 }
961 argv[i] = NULL((void *)0); /* null-terminated */
962
963 cpid = spawnprocve(argv[0], argv, environ, -1)pmgt_ProcessSpawnVE(argv[0], argv, environ, -1);
964 osi_audit(BOSSpawnProcEvent"AFS_BOS_SpawnProc", 0, AUD_STR1, aexecString, AUD_END0);
965
966 if (cpid == (pid_t) - 1) {
967 bozo_Log("Failed to spawn process for bnode '%s'\n", abnode->name);
968 bnode_FreeTokens(tlist);
969 free(tp);
970 return errno(* __error());
971 }
972
973 bnode_FreeTokens(tlist);
974 allProcs = tp;
975 *aproc = tp;
976 tp->pid = cpid;
977 tp->flags = BPROC_STARTED1;
978 tp->flags &= ~BPROC_EXITED2;
979 bnode_Check(abnode);
980 return 0;
981}
982
983int
984bnode_StopProc(struct bnode_proc *aproc, int asignal)
985{
986 int code;
987 if (!(aproc->flags & BPROC_STARTED1) || (aproc->flags & BPROC_EXITED2))
988 return BZNOTACTIVE(39424L);
989
990 osi_audit(BOSStopProcEvent"AFS_BOS_StpProc", 0, AUD_STR1, (aproc ? aproc->comLine : NULL((void *)0)),
991 AUD_END0);
992
993 code = kill(aproc->pid, asignal);
994 bnode_Check(aproc->bnode);
995 return code;
996}
997
998int
999bnode_Deactivate(struct bnode *abnode)
1000{
1001 struct bnode **pb, *tb;
1002 struct bnode *nb;
1003 if (!(abnode->flags & BNODE_ACTIVE2))
1004 return BZNOTACTIVE(39424L);
1005 for (pb = &allBnodes, tb = *pb; tb; tb = nb) {
1006 nb = tb->next;
1007 if (tb == abnode) {
1008 *pb = nb;
1009 tb->flags &= ~BNODE_ACTIVE2;
1010 return 0;
1011 }
1012 }
1013 return BZNOENT(39425L);
1014}