1 /* $NetBSD: supcmisc.c,v 1.19 2009/01/15 15:58:42 christos Exp $ */
4 * Copyright (c) 1992 Carnegie Mellon University
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 **********************************************************************
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.
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.
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 **********************************************************************
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
;
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 */
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 *************************************************/
83 char buf
[STRINGLENGTH
];
84 char relsufix
[STRINGLENGTH
];
87 if ((thisC
->Cflags
& CFURELSUF
) && thisC
->Crelease
)
88 (void) sprintf(relsufix
, ".%s", thisC
->Crelease
);
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
);
102 establishdir(char *fname
)
104 char dpart
[STRINGLENGTH
], fpart
[STRINGLENGTH
];
105 path(fname
, dpart
, fpart
);
106 return (estabd(fname
, dpart
));
110 makedir(char *fname
, unsigned int mode
, struct stat
* statp
)
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
,
121 if (mkdir(fname
, mode
) == -1)
126 rv
= stat(fname
, statp
);
135 estabd(char *fname
, char *dname
)
137 char dpart
[STRINGLENGTH
], fpart
[STRINGLENGTH
];
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",
149 x
= estabd(fname
, dpart
);
152 if (makedir(dname
, 0755, &sbuf
) < 0) {
153 notify("SUP: Can't create directory %s for %s (%s)\n", dname
,
154 fname
, strerror(errno
));
157 vnotify("SUP Created directory %s for %s\n", dname
, fname
);
160 /***************************************
161 *** L I S T R O U T I N E S ***
162 ***************************************/
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). */
179 return (((len
& HASHMASK
) << HASHBITS
) | (((int) c
) & HASHMASK
));
183 Linsert(LIST
** table
, char *name
, int number
)
188 l
= (LIST
*) malloc(sizeof(LIST
));
190 goaway("Cannot allocate memory");
193 l
->Lnext
= table
[lno
];
198 Llookup(LIST
** table
, char *name
)
203 for (l
= table
[lno
]; l
&& strcmp(l
->Lname
, name
) != 0; l
= l
->Lnext
);
208 ugconvert(char *uname
, char *gname
, int *uid
, int *gid
, int *mode
)
214 static int defuid
= -1;
216 static int first
= TRUE
;
219 bzero(uidL
, sizeof(uidL
));
220 bzero(gidL
, sizeof(gidL
));
224 if ((u
= Llookup(uidL
, uname
)) != NULL
)
226 else if ((pw
= getpwnam(uname
)) != NULL
) {
227 Linsert(uidL
, estrdup(uname
), pw
->pw_uid
);
231 if ((g
= Llookup(gidL
, gname
)) != NULL
) {
235 if ((gr
= getgrnam(gname
)) != NULL
) {
236 Linsert(gidL
, estrdup(gname
), gr
->gr_gid
);
241 pw
= getpwnam(uname
);
246 *mode
&= ~(S_ISUID
| S_ISGID
);
252 if (stat(".", &sbuf
) < 0) {
253 *uid
= defuid
= getuid();
254 *gid
= defgid
= getgid();
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 *********************************************/
267 notify(const char *fmt
, ...)
268 { /* record error message */
269 char buf
[STRINGLENGTH
];
270 char collrelname
[STRINGLENGTH
];
271 char hostname
[STRINGLENGTH
];
273 static FILE *noteF
= NULL
; /* mail program on pipe */
275 int shouldMail
= (thisC
->Cflags
& CFMAIL
) && thisC
->Cnotify
;
276 int needFile
= shouldMail
|| silent
;
280 if ((thisC
->Cflags
& CFURELSUF
) && thisC
->Crelease
)
281 (void) sprintf(collrelname
, "%s-%s", collname
, thisC
->Crelease
);
283 (void) strcpy(collrelname
, collname
);
286 if (noteF
&& noteF
!= stdout
&& (!silent
|| thisC
->Cnogood
)) {
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
,
296 outF
= popen(buf
, "w");
298 logerr("Can't send mail to %s for %s",
299 thisC
->Cnotify
, collrelname
);
306 while ((nr
= fread(buf
, 1, sizeof(buf
), noteF
)) > 0)
307 (void)fwrite(buf
, 1, nr
, outF
);
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",
328 (void)unlink(template);
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
);
338 (void) fflush(noteF
);
343 { /* lock out interrupts */
344 static sigset_t oset
;
349 sigaddset(&nset
, SIGHUP
);
350 sigaddset(&nset
, SIGINT
);
351 sigaddset(&nset
, SIGTERM
);
352 sigaddset(&nset
, SIGQUIT
);
353 (void) sigprocmask(SIG_BLOCK
, &nset
, &oset
);
355 (void) sigprocmask(SIG_SETMASK
, &oset
, NULL
);
362 static char buf
[STRINGLENGTH
];
365 (void) strcpy(buf
, ctime(&time
));
366 len
= strlen(buf
+ 4) - 6;