1*8ac837e5Snicm /* $OpenBSD: worklist.c,v 1.4 2015/06/13 20:15:21 nicm Exp $ */
22dc36bedSjoris /*
32dc36bedSjoris * Copyright (c) 2006 Joris Vink <joris@openbsd.org>
42dc36bedSjoris * All rights reserved.
52dc36bedSjoris *
62dc36bedSjoris * Redistribution and use in source and binary forms, with or without
72dc36bedSjoris * modification, are permitted provided that the following conditions
82dc36bedSjoris * are met:
92dc36bedSjoris *
102dc36bedSjoris * 1. Redistributions of source code must retain the above copyright
112dc36bedSjoris * notice, this list of conditions and the following disclaimer.
122dc36bedSjoris * 2. The name of the author may not be used to endorse or promote products
132dc36bedSjoris * derived from this software without specific prior written permission.
142dc36bedSjoris *
152dc36bedSjoris * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
162dc36bedSjoris * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
172dc36bedSjoris * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
182dc36bedSjoris * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
192dc36bedSjoris * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
202dc36bedSjoris * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
212dc36bedSjoris * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
222dc36bedSjoris * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
232dc36bedSjoris * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
242dc36bedSjoris * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
252dc36bedSjoris */
262dc36bedSjoris
274781e2faSxsa #include <sys/queue.h>
284781e2faSxsa
294781e2faSxsa #include <err.h>
304781e2faSxsa #include <signal.h>
31*8ac837e5Snicm #include <stdlib.h>
324781e2faSxsa #include <string.h>
334781e2faSxsa #include <unistd.h>
342dc36bedSjoris
352dc36bedSjoris #include "worklist.h"
362dc36bedSjoris #include "xmalloc.h"
372dc36bedSjoris
382dc36bedSjoris /*
392dc36bedSjoris * adds a path to a worklist.
402dc36bedSjoris */
412dc36bedSjoris void
worklist_add(const char * path,struct wklhead * worklist)427a9e6d11Sray worklist_add(const char *path, struct wklhead *worklist)
432dc36bedSjoris {
442dc36bedSjoris size_t len;
457a9e6d11Sray struct worklist *wkl;
462dc36bedSjoris sigset_t old, new;
472dc36bedSjoris
482dc36bedSjoris wkl = xcalloc(1, sizeof(*wkl));
492dc36bedSjoris
502dc36bedSjoris len = strlcpy(wkl->wkl_path, path, sizeof(wkl->wkl_path));
512dc36bedSjoris if (len >= sizeof(wkl->wkl_path))
527a9e6d11Sray errx(1, "path truncation in worklist_add");
532dc36bedSjoris
542dc36bedSjoris sigfillset(&new);
552dc36bedSjoris sigprocmask(SIG_BLOCK, &new, &old);
562dc36bedSjoris SLIST_INSERT_HEAD(worklist, wkl, wkl_list);
572dc36bedSjoris sigprocmask(SIG_SETMASK, &old, NULL);
582dc36bedSjoris }
592dc36bedSjoris
602dc36bedSjoris /*
612dc36bedSjoris * run over the given worklist, calling cb for each element.
627a9e6d11Sray * this is just like worklist_clean(), except we block signals first.
632dc36bedSjoris */
642dc36bedSjoris void
worklist_run(struct wklhead * list,void (* cb)(struct worklist *))657a9e6d11Sray worklist_run(struct wklhead *list, void (*cb)(struct worklist *))
662dc36bedSjoris {
672dc36bedSjoris sigset_t old, new;
687a9e6d11Sray struct worklist *wkl;
692dc36bedSjoris
702dc36bedSjoris sigfillset(&new);
712dc36bedSjoris sigprocmask(SIG_BLOCK, &new, &old);
722dc36bedSjoris
737a9e6d11Sray worklist_clean(list, cb);
742dc36bedSjoris
752dc36bedSjoris while ((wkl = SLIST_FIRST(list)) != NULL) {
762dc36bedSjoris SLIST_REMOVE_HEAD(list, wkl_list);
77*8ac837e5Snicm free(wkl);
782dc36bedSjoris }
792dc36bedSjoris
802dc36bedSjoris sigprocmask(SIG_SETMASK, &old, NULL);
812dc36bedSjoris }
822dc36bedSjoris
832dc36bedSjoris /*
842dc36bedSjoris * pass elements to the specified callback, which has to be signal safe.
852dc36bedSjoris */
862dc36bedSjoris void
worklist_clean(struct wklhead * list,void (* cb)(struct worklist *))877a9e6d11Sray worklist_clean(struct wklhead *list, void (*cb)(struct worklist *))
882dc36bedSjoris {
897a9e6d11Sray struct worklist *wkl;
902dc36bedSjoris
912dc36bedSjoris SLIST_FOREACH(wkl, list, wkl_list)
922dc36bedSjoris cb(wkl);
932dc36bedSjoris }
942dc36bedSjoris
952dc36bedSjoris void
worklist_unlink(struct worklist * wkl)967a9e6d11Sray worklist_unlink(struct worklist *wkl)
972dc36bedSjoris {
982dc36bedSjoris (void)unlink(wkl->wkl_path);
992dc36bedSjoris }
100