--- /dev/null
+/*
+ * at - at interface
+ *
+ * Copyright (C) 2009 Enrico Zini <enrico@enricozini.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+using GLib;
+
+namespace at {
+
+// Return the earliest ID in the queue, or -1 if none are found
+// Queue is null for all queues, otherwise a queue name
+public static int earliestID(string? queue = null)
+{
+ string argv[4];
+ argv[0] = "/usr/bin/atq";
+ if (queue == null)
+ argv[1] = null;
+ else
+ {
+ argv[1] = "-q";
+ argv[2] = queue;
+ argv[3] = null;
+ }
+
+ Pid pid;
+ int stdout;
+
+ if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdout, null))
+ return -1;
+
+ FileStream fs = FileStream.fdopen(stdout, "r");
+ if (fs == null)
+ return -1;
+
+ int first_id = -1;
+ time_t first_ts = 0;
+ char buf[200];
+ string? line;
+ while ((line = fs.gets(buf)) != null)
+ {
+ if (!line[0].isdigit()) continue;
+ weak string rest;
+ ulong id = line.to_ulong(out rest, 10);
+ Time t = new Time();
+ rest = t.strptime(rest.offset(1), "%a %b %d %H:%M:%S %Y");
+ if (rest == null) continue;
+ time_t tt = t.mktime();
+ if (first_ts == 0 || tt < first_ts)
+ {
+ first_ts = tt;
+ first_id = (int)id;
+ }
+ }
+ Process.close_pid(pid);
+ return first_id;
+}
+
+public delegate bool jobParser(int fd);
+
+// Get the contents of a job given its id
+public static bool jobContents(int id, jobParser parser)
+{
+ string argv[4];
+ argv[0] = "/usr/bin/at";
+ argv[1] = "-c";
+ argv[2] = id.to_string();
+ argv[3] = null;
+
+ Pid pid;
+ int stdoutfd;
+
+ if (!Process.spawn_async_with_pipes("/", argv, null, SpawnFlags.STDERR_TO_DEV_NULL, null, out pid, null, out stdoutfd, null))
+ return false;
+
+ bool res = parser(stdoutfd);
+
+ Process.close_pid(pid);
+
+ return res;
+}
+
+/*
+TODO: schedule alarms via at
+
+Uses the 'z' queue.
+
+atq -q z can be used to list the jobs (for example, at startup, or after a job has run)
+at -c id can be used to query a job, parsing its contents (which can have
+ comments or variables being set)
+zavai --notify ... can be used to notify the job (and start zavai if it's not running)
+
+Alarm needs to be able to serialize itself to an at invocation and to
+deserialize itself from the output of at -c
+
+Alarm needs to deserialize also a job with no special markers whatsoever: a
+generic at job.
+*/
+
+
+/*
+public class Alarm : Object
+{
+ // TODO: make a factory method to construct from an "at -c" output
+
+ // TODO: make a method that provides an at invocation
+
+ public signal void trigger(Alarm a);
+
+ public time_t deadline;
+ public string label;
+
+ public Alarm(time_t deadline, string label)
+ {
+ this.deadline = deadline;
+ this.label = label;
+ }
+}
+*/
+
+ // Schedule a task that notifies a string
+ // TODO public void schedule_label(const Alarm a);
+
+ // Return the next item in the queue due to be run
+ // TODO public Alarm? next_scheduled();
+
+}