Sync usage with man page.
[netbsd-mini2440.git] / usr.sbin / sup / source / supcmisc.c
blob6881b9d643e5619e81ea118ee70937c3f543d373
1 /* $NetBSD: supcmisc.c,v 1.19 2009/01/15 15:58:42 christos Exp $ */
3 /*
4 * Copyright (c) 1992 Carnegie Mellon University
5 * All Rights Reserved.
7 * Permission to use, copy, modify and distribute this software and its
8 * documentation is hereby granted, provided that both the copyright
9 * notice and this permission notice appear in all copies of the
10 * software, derivative works or modified versions, and any portions
11 * thereof, and that both notices appear in supporting documentation.
13 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
14 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
15 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 * Carnegie Mellon requests users of this software to return to
19 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
20 * School of Computer Science
21 * Carnegie Mellon University
22 * Pittsburgh PA 15213-3890
24 * any improvements or extensions that they make and grant Carnegie Mellon
25 * the rights to redistribute these changes.
28 * sup misc. routines, include list processing.
29 **********************************************************************
30 * HISTORY
31 * Revision 1.5 92/08/11 12:07:22 mrt
32 * Added release to FILEWHEN name.
33 * Brad's changes: delinted and updated variable argument usage.
34 * [92/07/26 mrt]
36 * Revision 1.3 89/08/15 15:31:28 bww
37 * Updated to use v*printf() in place of _doprnt().
38 * From "[89/04/19 mja]" at CMU.
39 * [89/08/15 bww]
41 * 27-Dec-87 Glenn Marcy (gm0w) at Carnegie-Mellon University
42 * Fixed bug in ugconvert() which left pw uninitialized.
44 * 25-May-87 Doug Philips (dwp) at Carnegie-Mellon University
45 * Split off from sup.c and changed goaway to use printf
46 * instead of notify if thisC is NULL.
48 **********************************************************************
51 #include "supcdefs.h"
52 #include "supextern.h"
54 struct liststruct { /* uid and gid lists */
55 char *Lname; /* name */
56 int Lnumber; /* uid or gid */
57 struct liststruct *Lnext;
59 typedef struct liststruct LIST;
61 #define HASHBITS 4
62 #define HASHSIZE (1<<HASHBITS)
63 #define HASHMASK (HASHSIZE-1)
64 #define LISTSIZE (HASHSIZE*HASHSIZE)
66 static LIST *uidL[LISTSIZE]; /* uid and gid lists */
67 static LIST *gidL[LISTSIZE];
69 extern COLLECTION *thisC; /* collection list pointer */
70 extern int silent;
72 static int Lhash(char *);
73 static void Linsert(LIST **, char *, int);
74 static LIST *Llookup(LIST **, char *);
76 /*************************************************
77 *** P R I N T U P D A T E T I M E S ***
78 *************************************************/
80 void
81 prtime(void)
83 char buf[STRINGLENGTH];
84 char relsufix[STRINGLENGTH];
85 time_t twhen;
87 if ((thisC->Cflags & CFURELSUF) && thisC->Crelease)
88 (void) sprintf(relsufix, ".%s", thisC->Crelease);
89 else
90 relsufix[0] = '\0';
91 if (chdir(thisC->Cbase) < 0)
92 logerr("Can't change to base directory %s for collection %s",
93 thisC->Cbase, thisC->Cname);
94 twhen = getwhen(thisC->Cname, relsufix);
95 (void) strcpy(buf, ctime(&twhen));
96 buf[strlen(buf) - 1] = '\0';
97 loginfo("Last update occurred at %s for collection %s%s",
98 buf, thisC->Cname, relsufix);
101 int
102 establishdir(char *fname)
104 char dpart[STRINGLENGTH], fpart[STRINGLENGTH];
105 path(fname, dpart, fpart);
106 return (estabd(fname, dpart));
109 int
110 makedir(char *fname, unsigned int mode, struct stat * statp)
112 int en, rv;
114 if (lstat(fname, statp) != -1 && !S_ISDIR(statp->st_mode)) {
115 if (unlink(fname) == -1) {
116 notify("SUP: Can't delete %s (%s)\n", fname,
117 strerror(errno));
118 return -1;
121 if (mkdir(fname, mode) == -1)
122 en = errno;
123 else
124 en = -1;
126 rv = stat(fname, statp);
128 if (en != -1)
129 errno = en;
131 return rv;
134 int
135 estabd(char *fname, char *dname)
137 char dpart[STRINGLENGTH], fpart[STRINGLENGTH];
138 struct stat sbuf;
139 int x;
141 if (stat(dname, &sbuf) >= 0)
142 return (FALSE); /* exists */
143 path(dname, dpart, fpart);
144 if (strcmp(fpart, ".") == 0) { /* dname is / or . */
145 notify("SUP: Can't create directory %s for %s (Invalid name)\n",
146 dname, fname);
147 return (TRUE);
149 x = estabd(fname, dpart);
150 if (x)
151 return (TRUE);
152 if (makedir(dname, 0755, &sbuf) < 0) {
153 notify("SUP: Can't create directory %s for %s (%s)\n", dname,
154 fname, strerror(errno));
155 return TRUE;
157 vnotify("SUP Created directory %s for %s\n", dname, fname);
158 return (FALSE);
160 /***************************************
161 *** L I S T R O U T I N E S ***
162 ***************************************/
164 static int
165 Lhash(char *name)
167 /* Hash function is: HASHSIZE * (strlen mod HASHSIZE) +
168 * (char mod HASHSIZE) where "char" is last character of name (if
169 * name is non-null). */
171 int len;
172 char c;
174 len = strlen(name);
175 if (len > 0)
176 c = name[len - 1];
177 else
178 c = 0;
179 return (((len & HASHMASK) << HASHBITS) | (((int) c) & HASHMASK));
182 static void
183 Linsert(LIST ** table, char *name, int number)
185 LIST *l;
186 int lno;
187 lno = Lhash(name);
188 l = (LIST *) malloc(sizeof(LIST));
189 if (l == NULL)
190 goaway("Cannot allocate memory");
191 l->Lname = name;
192 l->Lnumber = number;
193 l->Lnext = table[lno];
194 table[lno] = l;
197 static LIST *
198 Llookup(LIST ** table, char *name)
200 int lno;
201 LIST *l;
202 lno = Lhash(name);
203 for (l = table[lno]; l && strcmp(l->Lname, name) != 0; l = l->Lnext);
204 return (l);
207 void
208 ugconvert(char *uname, char *gname, int *uid, int *gid, int *mode)
210 LIST *u, *g;
211 struct passwd *pw;
212 struct group *gr;
213 struct stat sbuf;
214 static int defuid = -1;
215 static int defgid;
216 static int first = TRUE;
218 if (first) {
219 bzero(uidL, sizeof(uidL));
220 bzero(gidL, sizeof(gidL));
221 first = FALSE;
223 pw = NULL;
224 if ((u = Llookup(uidL, uname)) != NULL)
225 *uid = u->Lnumber;
226 else if ((pw = getpwnam(uname)) != NULL) {
227 Linsert(uidL, estrdup(uname), pw->pw_uid);
228 *uid = pw->pw_uid;
230 if (u || pw) {
231 if ((g = Llookup(gidL, gname)) != NULL) {
232 *gid = g->Lnumber;
233 return;
235 if ((gr = getgrnam(gname)) != NULL) {
236 Linsert(gidL, estrdup(gname), gr->gr_gid);
237 *gid = gr->gr_gid;
238 return;
240 if (pw == NULL)
241 pw = getpwnam(uname);
242 *mode &= ~S_ISGID;
243 *gid = pw->pw_gid;
244 return;
246 *mode &= ~(S_ISUID | S_ISGID);
247 if (defuid >= 0) {
248 *uid = defuid;
249 *gid = defgid;
250 return;
252 if (stat(".", &sbuf) < 0) {
253 *uid = defuid = getuid();
254 *gid = defgid = getgid();
255 return;
257 *uid = defuid = sbuf.st_uid;
258 *gid = defgid = sbuf.st_gid;
262 /*********************************************
263 *** U T I L I T Y R O U T I N E S ***
264 *********************************************/
266 void
267 notify(const char *fmt, ...)
268 { /* record error message */
269 char buf[STRINGLENGTH];
270 char collrelname[STRINGLENGTH];
271 char hostname[STRINGLENGTH];
272 time_t tloc;
273 static FILE *noteF = NULL; /* mail program on pipe */
274 va_list ap;
275 int shouldMail = (thisC->Cflags & CFMAIL) && thisC->Cnotify;
276 int needFile = shouldMail || silent;
278 va_start(ap, fmt);
280 if ((thisC->Cflags & CFURELSUF) && thisC->Crelease)
281 (void) sprintf(collrelname, "%s-%s", collname, thisC->Crelease);
282 else
283 (void) strcpy(collrelname, collname);
285 if (fmt == NULL) {
286 if (noteF && noteF != stdout && (!silent || thisC->Cnogood)) {
287 int nr;
288 FILE *outF;
290 if (shouldMail) {
291 (void)gethostname(hostname, sizeof(hostname));
292 (void) snprintf(buf, sizeof(buf),
293 "mail -s \"SUP Upgrade of %s on %s\" %s >"
294 " /dev/null", collrelname, hostname,
295 thisC->Cnotify);
296 outF = popen(buf, "w");
297 if (outF == NULL) {
298 logerr("Can't send mail to %s for %s",
299 thisC->Cnotify, collrelname);
300 outF = stdout;
302 } else
303 outF = stdout;
305 (void)rewind(noteF);
306 while ((nr = fread(buf, 1, sizeof(buf), noteF)) > 0)
307 (void)fwrite(buf, 1, nr, outF);
308 (void)fflush(outF);
309 if (outF != stdout)
310 (void)pclose(outF);
311 (void)fclose(noteF);
313 noteF = NULL;
314 va_end(ap);
315 return;
318 if (noteF == NULL) {
319 if (needFile) {
320 char template[] = "/tmp/sup.XXXXXX";
321 int fd = mkstemp(template);
322 if (fd == -1 || (noteF = fdopen(fd, "r+")) == NULL) {
323 logerr("Can't open temporary file for %s",
324 collrelname);
325 silent = 0;
326 noteF = stdout;
328 (void)unlink(template);
329 } else
330 noteF = stdout;
331 tloc = time((time_t *) NULL);
332 fprintf(noteF, "SUP Upgrade of %s at %s",
333 collrelname, ctime(&tloc));
334 (void) fflush(noteF);
336 vfprintf(noteF, fmt, ap);
337 va_end(ap);
338 (void) fflush(noteF);
341 void
342 lockout(int on)
343 { /* lock out interrupts */
344 static sigset_t oset;
345 sigset_t nset;
347 if (on) {
348 sigemptyset(&nset);
349 sigaddset(&nset, SIGHUP);
350 sigaddset(&nset, SIGINT);
351 sigaddset(&nset, SIGTERM);
352 sigaddset(&nset, SIGQUIT);
353 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
354 } else {
355 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
359 char *
360 fmttime(time_t time)
362 static char buf[STRINGLENGTH];
363 unsigned int len;
365 (void) strcpy(buf, ctime(&time));
366 len = strlen(buf + 4) - 6;
367 buf[len] = '\0';
368 return buf + 4;