Skip to content

Instantly share code, notes, and snippets.

@oelmekki
Created July 4, 2026 14:00
Show Gist options
  • Select an option

  • Save oelmekki/9ce9e8589b2dab78df1b67f8002d5dea to your computer and use it in GitHub Desktop.

Select an option

Save oelmekki/9ce9e8589b2dab78df1b67f8002d5dea to your computer and use it in GitHub Desktop.
Patch for FreeBSD's /bin/sh to show jobs count, and date of prompt display (see comment)
diff --git a/bin/sh/jobs.c b/bin/sh/jobs.c
index a4cd76473921..4f68608b5b9a 100644
--- a/bin/sh/jobs.c
+++ b/bin/sh/jobs.c
@@ -499,6 +499,43 @@ showjobs(int change, int mode)
}
}
+void
+jobs_notification(void)
+{
+ int jobno;
+ struct job *jp;
+ size_t bg_jobs_count = 0;
+ char s[64] = {0};
+
+ for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
+ if (! jp->used)
+ continue;
+
+ if (jp->nprocs == 0)
+ continue;
+
+ if (!jp->foreground || jp->state == JOBSTOPPED)
+ bg_jobs_count++;
+ }
+
+ char date_time[100];
+ time_t now = time (NULL);
+ struct tm *local_time = localtime (&now);
+ strftime (date_time, sizeof (date_time), "[%H:%M:%S]", local_time);
+
+ if (bg_jobs_count)
+ {
+ if (bg_jobs_count == 1)
+ fmtstr(s, 64, "\n%s (%zu job)\n", date_time, bg_jobs_count);
+ else
+ fmtstr(s, 64, "\n%s(%zu jobs)\n", date_time, bg_jobs_count);
+ }
+ else
+ fmtstr(s, 64, "\n%s\n", date_time);
+
+ out1str(s);
+}
+
/*
* Mark a job structure as unused.
diff --git a/bin/sh/jobs.h b/bin/sh/jobs.h
index 149b85d7df80..3f1fcaba3702 100644
--- a/bin/sh/jobs.h
+++ b/bin/sh/jobs.h
@@ -50,6 +50,7 @@ extern int job_warning; /* user was warned about stopped jobs */
void setjobctl(int);
void showjobs(int, int);
+void jobs_notification(void);
struct job *makejob(union node *, int);
pid_t forkshell(struct job *, union node *, int);
pid_t vforkexecshell(struct job *, char **, char **, const char *, int, int [2]);
diff --git a/bin/sh/main.c b/bin/sh/main.c
index 94e8da6b4921..58048e01c6cb 100644
--- a/bin/sh/main.c
+++ b/bin/sh/main.c
@@ -201,6 +201,7 @@ cmdloop(int top)
if (iflag && top) {
inter++;
showjobs(1, SHOWJOBS_DEFAULT);
+ jobs_notification();
chkmail(0);
flushout(&output);
}
@oelmekki

oelmekki commented Jul 4, 2026

Copy link
Copy Markdown
Author

Jobs count

Lately, I've been working a lot with POSIX jobs as my main mean to edit multiple files. The big problem with that is that it's all too easy to forget you had paused jobs and close a terminal, since there is no indication for it.

With Bash, the solution was easy: put the output of jobs | wc -l in your prompt.

With FreeBSD's sh, if you do that, it's rendered once, when the shell is started, and then the same value is carried over the various prompts on subsequent commands.

This patch fixes this, by implementing the showing of the jobs count directly in the prompt rendering, at source code level.

Date

An other thing I loved to do in Bash was to print the time when rendering the prompt. It's not that I wanted to know what time it was (I already have way enough sources for that), it's that I wanted to know when the previous command had finished executing. It's a cheap way to measure how much time it took to execute a command when you didn't think about running it through time.

But FreeBSD has the same issue here than for jobs count: if you put a subcommand in your prompt to display the time, it will execute it once when shell initialize, and then display the same value for each prompt. There is actually a workaround for that, as sh's PS1 recognizes a special syntax, \D{fmt}. But now, it's updated at each redraw! Press a key, and the information about when the last command finished is gone (but you now know when you last pressed a key, rejoice).

So this patch also add this: a simple time information just before the prompt. Now you know.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment