summaryrefslogtreecommitdiffstats
path: root/debian/patches/82_session_creation_core.patch
blob: 72fa1f3cdbdb18368eb27f865899403476ea1617 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
Author: Jan Christoph Nordholz <hesso@pool.math.tu-berlin.de>
Description: Add lookup code for the creation time of each session.
 Requires digging in /proc/$pid and /proc/uptime, though, so it's
 definitely no candidate for the Beautiful C contest.
 .
 Affects screen's behaviour in the following situations:
 .
 * 'screen -ls' lists available sessions sorted chronologically
 * 'screen -RR' now picks the youngest session instead of an
   arbitrary one
 .
 Patch 3/3: implementation of actual new feature
Bug-Debian: https://bugs.debian.org/206572
Bug-Debian: https://bugs.debian.org/507817
Forwarded: not-yet

--- a/socket.c
+++ b/socket.c
@@ -137,16 +137,18 @@
   int sdirlen;
   int  matchlen = 0;
   char *name, *n;
-  int firsts = -1, sockfd;
-  char *firstn = NULL;
+  int sockfd;
   int nfound = 0, ngood = 0, ndead = 0, nwipe = 0, npriv = 0;
   int nperfect = 0;
+  time_t time_sysboot = time(NULL) - GetUptime();
   struct sent
     {
       struct sent *next;
       int mode;
+      int fd;
       char *name;
-    } *slist, **slisttail, *sent, *nsent;
+      time_t time_created;
+    } *slist, **slisttail, *sent, *nsent, *schosen;
 
   if (match)
     {
@@ -172,7 +174,7 @@
   if ((dirp = opendir(SockPath)) == 0)
     Panic(errno, "Cannot opendir %s", SockPath);
 
-  slist = 0;
+  slist = schosen = NULL;
   slisttail = &slist;
   while ((dp = readdir(dirp)))
     {
@@ -255,13 +257,16 @@
       debug("  store it.\n");
       if ((sent = (struct sent *)malloc(sizeof(struct sent))) == 0)
 	continue;
-      sent->next = 0;
       sent->name = SaveStr(name);
       sent->mode = mode;
+      sent->time_created = time_sysboot + SessionCreationTime(name);
+      for (slisttail = &slist; *slisttail; slisttail = &((*slisttail)->next)) {
+        if ((*slisttail)->time_created < sent->time_created) break;
+      }
+      sent->next = *slisttail;
       *slisttail = sent;
-      slisttail = &sent->next;
       nfound++;
-      sockfd = MakeClientSocket(0, *is_sock);
+      sent->fd = sockfd = MakeClientSocket(0, *is_sock);
 #ifdef USE_SETEUID
       /* MakeClientSocket sets ids back to eff */
       xseteuid(real_uid);
@@ -326,12 +331,17 @@
       ngood++;
       if (cmatch)
 	nperfect++;
-      if (fdp && (firsts == -1 || (cmatch && nperfect == 1)))
+      // prefer the current one if one of the following is true:
+      // - we had no previous hit
+      // - the current one has a later timestamp than our previous one, and we haven't found a perfect match yet
+      // - this one is the first perfect match
+      if (fdp && (!schosen ||
+		(schosen && schosen->time_created < sent->time_created && nperfect == 0) ||
+		(cmatch && nperfect == 1)))
 	{
-	  if (firsts != -1)
-	    close(firsts);
-	  firsts = sockfd;
-	  firstn = sent->name;
+	  if (schosen)
+	    close(schosen->fd);
+	  schosen = sent;
 	  debug("  taken.\n");
 	}
       else
@@ -359,36 +369,27 @@
 	}
       for (sent = slist; sent; sent = sent->next)
 	{
-	  switch (sent->mode)
+	  char timestr[64];
+	  if (sent->time_created == 0)
 	    {
-	    case 0700:
-	      printf("\t%s\t(Attached)\n", sent->name);
-	      break;
-	    case 0600:
-	      printf("\t%s\t(Detached)\n", sent->name);
-	      break;
+	      sprintf(timestr, "??" "?");
+	    }
+	  else
+	    {
+	      strftime(timestr, 64, "%x %X", localtime(&sent->time_created));
+	    }
+          printf("\t%s\t(%s)\t(%s)\n", sent->name, timestr,
+		(sent->mode == 0700) ? "Attached" :
+		(sent->mode == 0600) ? "Detached" :
 #ifdef MULTIUSER
-	    case 0701:
-	      printf("\t%s\t(Multi, attached)\n", sent->name);
-	      break;
-	    case 0601:
-	      printf("\t%s\t(Multi, detached)\n", sent->name);
-	      break;
+		(sent->mode == 0701) ? "Multi, attached" :
+		(sent->mode == 0601) ? "Multi, detached" :
 #endif
-	    case -1:
-	      /* No trigraphs here! */
-	      printf("\t%s\t(Dead ?%c?)\n", sent->name, '?');
-	      break;
-	    case -2:
-	      printf("\t%s\t(Removed)\n", sent->name);
-	      break;
-	    case -3:
-	      printf("\t%s\t(Remote or dead)\n", sent->name);
-	      break;
-	    case -4:
-	      printf("\t%s\t(Private)\n", sent->name);
-	      break;
-	    }
+		(sent->mode ==   -1) ? "Dead ??" "?" :
+		(sent->mode ==   -2) ? "Removed" :
+		(sent->mode ==   -3) ? "Remote or dead" :
+		(sent->mode ==   -4) ? "Private" :
+		"Unknown");
 	}
     }
   if (ndead && !quietflag)
@@ -399,10 +400,10 @@
       else
         Msg(0, m, ndead > 1 ? "s" : "", ndead > 1 ? "" : "es");	/* other args for nethack */
     }
-  if (firsts != -1)
+  if (schosen)
     {
-      sprintf(SockPath + sdirlen, "/%s", firstn);
-      *fdp = firsts;
+      sprintf(SockPath + sdirlen, "/%s", schosen->name);
+      *fdp = schosen->fd;
     }
   else
     SockPath[sdirlen] = 0;