From: Ben Gras Date: Fri, 25 Jun 2010 17:14:56 +0000 (+0000) Subject: commands: id from netbsd; touch from bsd-utils port X-Git-Tag: v3.1.8~356 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/addsub.png?a=commitdiff_plain;h=373aecf3cd1a830e2c2efb6030d7a3bdead4c67a;p=minix.git commands: id from netbsd; touch from bsd-utils port --- diff --git a/commands/Makefile b/commands/Makefile index 5f742a898..2eeae97b3 100644 --- a/commands/Makefile +++ b/commands/Makefile @@ -13,7 +13,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \ ed eject elle elvis env expand factor file \ find finger fingerd fix fold format fortune fsck \ fsck1 ftp101 ftpd200 getty grep gomoku head host \ - hostaddr ifconfig ifdef indent install \ + hostaddr id ifconfig ifdef indent install \ intr ipcrm ipcs irdpd isoread join kill last leave \ lex life loadkeys loadramdisk logger login look lp \ lpd ls lspci M m4 mail make MAKEDEV makewhatis man \ @@ -28,7 +28,7 @@ SUBDIR= aal add_route adduser advent arp ash at autil awk \ sleep slip sort spell split srccrc stat strings strip \ stty su sum svclog swapfs swifi sync synctree sysenv \ syslogd tail talk talkd tcpd tcpdp tcpstat tee telnet \ - telnetd term termcap tget time tinyhalt top tr \ + telnetd term termcap tget time tinyhalt top touch tr \ truncate tsort ttt tty udpstat umount uname unexpand \ uniq unstack update urlget uud uue version vol wc \ whatis whereis which who whoami write writeisofs \ diff --git a/commands/id/Makefile b/commands/id/Makefile new file mode 100644 index 000000000..90ed061e1 --- /dev/null +++ b/commands/id/Makefile @@ -0,0 +1,9 @@ +# $NetBSD: Makefile,v 1.11 2006/10/08 17:52:28 peter Exp $ +# from: @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= id +MAN= id.1 groups.1 whoami.1 +LINKS= ${BINDIR}/id ${BINDIR}/groups +LINKS+= ${BINDIR}/id ${BINDIR}/whoami + +.include diff --git a/commands/id/groups.1 b/commands/id/groups.1 new file mode 100644 index 000000000..f9154bb27 --- /dev/null +++ b/commands/id/groups.1 @@ -0,0 +1,62 @@ +.\" $NetBSD: groups.1,v 1.9 2003/08/07 11:14:06 agc Exp $ +.\" +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)groups.1 8.1 (Berkeley) 6/6/93 +.\" $NetBSD: groups.1,v 1.9 2003/08/07 11:14:06 agc Exp $ +.\" +.Dd June 6, 1993 +.Dt GROUPS 1 +.Os +.Sh NAME +.Nm groups +.Nd show group memberships +.Sh SYNOPSIS +.Nm +.Op Ar user +.Sh DESCRIPTION +The +.Nm +utility has been obsoleted by the +.Xr id 1 +utility, and is equivalent to +.Dq Nm id Fl Gn Op Ar user . +The command +.Dq Nm id Fl p +is suggested for normal interactive use. +.Pp +The +.Nm +utility displays the groups to which you (or the optionally specified user) +belong. +.Pp +The +.Nm +utility exits 0 on success, and \*[Gt]0 if an error occurs. +.Sh SEE ALSO +.Xr id 1 diff --git a/commands/id/id.1 b/commands/id/id.1 new file mode 100644 index 000000000..720c73ace --- /dev/null +++ b/commands/id/id.1 @@ -0,0 +1,138 @@ +.\" $NetBSD: id.1,v 1.12 2004/11/19 14:18:01 peter Exp $ +.\" +.\" Copyright (c) 1991, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)id.1 8.2 (Berkeley) 5/5/94 +.\" +.Dd May 5, 1994 +.Dt ID 1 +.Os +.Sh NAME +.Nm id +.Nd return user identity +.Sh SYNOPSIS +.Nm +.Op Ar user +.Nm +.Fl G Op Fl n +.Op Ar user +.Nm +.Fl g Op Fl nr +.Op Ar user +.Nm +.Fl p +.Op Ar user +.Nm +.Fl u Op Fl nr +.Op Ar user +.Sh DESCRIPTION +The +.Nm +utility displays the user and group names and numeric IDs, of the +calling process, to the standard output. +If the real and effective IDs are different, both are displayed, +otherwise only the real ID is displayed. +.Pp +If a +.Ar user +(login name or user ID) +is specified, the user and group IDs of that user are displayed. +In this case, the real and effective IDs are assumed to be the same. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl G +Display the different group IDs (effective, real and supplementary) +as white-space separated numbers, in no particular order. +.It Fl g +Display the effective group ID as a number. +.It Fl n +Display the name of the user or group ID for the +.Fl G , +.Fl g +and +.Fl u +options instead of the number. +If any of the ID numbers cannot be mapped into names, the number will be +displayed as usual. +.It Fl p +Make the output human-readable. +If the user name returned by +.Xr getlogin 2 +is different from the login name referenced by the user ID, the name +returned by +.Xr getlogin 2 +is displayed, preceded by the keyword ``login''. +The user ID as a name is displayed, preceded by the keyword ``uid''. +If the effective user ID is different from the real user ID, the real user +ID is displayed as a name, preceded by the keyword ``euid''. +If the effective group ID is different from the real group ID, the real group +ID is displayed as a name, preceded by the keyword ``rgid''. +The list of groups to which the user belongs is then displayed as names, +preceded by the keyword ``groups''. +Each display is on a separate line. +.It Fl r +Display the real ID for the +.Fl g +and +.Fl u +options instead of the effective ID. +.It Fl u +Display the effective user ID as a number. +.El +.Pp +The +.Nm +utility exits 0 on success, and \*[Gt]0 if an error occurs. +.Sh SEE ALSO +.Xr who 1 +.Sh STANDARDS +The +.Nm +function is expected to conform to +.St -p1003.2 . +.Sh HISTORY +The +historic +.Xr groups 1 +command is equivalent to +.Dq Nm id Fl Gn Op Ar user . +.Pp +The +historic +.Xr whoami 1 +command is equivalent to +.Dq Nm id Fl un . +.Pp +The +.Nm +command first appeared in +.Bx 4.4 . diff --git a/commands/id/id.c b/commands/id/id.c new file mode 100644 index 000000000..86797fb54 --- /dev/null +++ b/commands/id/id.c @@ -0,0 +1,364 @@ +/*- + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +static void current(void); +static void pretty(struct passwd *); +static void group(struct passwd *, int); +static void usage(void); +static void user(struct passwd *); +static struct passwd *who(char *); + +static int maxgroups; +static gid_t *groups; + +int +main(int argc, char *argv[]) +{ + struct group *gr; + struct passwd *pw; + int ch, id; + int Gflag, gflag, nflag, pflag, rflag, uflag; + const char *opts; + + Gflag = gflag = nflag = pflag = rflag = uflag = 0; + + if (strcmp(getprogname(), "groups") == 0) { + Gflag = 1; + nflag = 1; + opts = ""; + if (argc > 2) + usage(); + } else if (strcmp(getprogname(), "whoami") == 0) { + uflag = 1; + nflag = 1; + opts = ""; + if (argc > 1) + usage(); + } else + opts = "Ggnpru"; + + while ((ch = getopt(argc, argv, opts)) != -1) + switch (ch) { + case 'G': + Gflag = 1; + break; + case 'g': + gflag = 1; + break; + case 'n': + nflag = 1; + break; + case 'p': + pflag = 1; + break; + case 'r': + rflag = 1; + break; + case 'u': + uflag = 1; + break; + case '?': + default: + usage(); + } + argc -= optind; + argv += optind; + + switch (Gflag + gflag + pflag + uflag) { + case 1: + break; + case 0: + if (!nflag && !rflag) + break; + /* FALLTHROUGH */ + default: + usage(); + } + + if (strcmp(opts, "") != 0 && argc > 1) + usage(); + + pw = *argv ? who(*argv) : NULL; + + maxgroups = sysconf(_SC_NGROUPS_MAX); + if ((groups = malloc((maxgroups + 1) * sizeof(gid_t))) == NULL) + err(1, NULL); + + if (gflag) { + id = pw ? pw->pw_gid : rflag ? getgid() : getegid(); + if (nflag && (gr = getgrgid(id))) + (void)printf("%s\n", gr->gr_name); + else + (void)printf("%u\n", id); + goto done; + } + + if (uflag) { + id = pw ? pw->pw_uid : rflag ? getuid() : geteuid(); + if (nflag && (pw = getpwuid(id))) + (void)printf("%s\n", pw->pw_name); + else + (void)printf("%u\n", id); + goto done; + } + + if (Gflag) { + group(pw, nflag); + goto done; + } + + if (pflag) { + pretty(pw); + goto done; + } + + if (pw) + user(pw); + else + current(); +done: + free(groups); + + return 0; +} + +static void +pretty(struct passwd *pw) +{ + struct group *gr; + u_int eid, rid; + char *login; + + if (pw) { + (void)printf("uid\t%s\n", pw->pw_name); + (void)printf("groups\t"); + group(pw, 1); + } else { + if ((login = getlogin()) == NULL) + err(1, "getlogin"); + + pw = getpwuid(rid = getuid()); + if (pw == NULL || strcmp(login, pw->pw_name)) + (void)printf("login\t%s\n", login); + if (pw) + (void)printf("uid\t%s\n", pw->pw_name); + else + (void)printf("uid\t%u\n", rid); + + if ((eid = geteuid()) != rid) { + if ((pw = getpwuid(eid)) != NULL) + (void)printf("euid\t%s\n", pw->pw_name); + else + (void)printf("euid\t%u\n", eid); + } + if ((rid = getgid()) != (eid = getegid())) { + if ((gr = getgrgid(rid)) != NULL) + (void)printf("rgid\t%s\n", gr->gr_name); + else + (void)printf("rgid\t%u\n", rid); + } + (void)printf("groups\t"); + group(NULL, 1); + } +} + +static void +current(void) +{ + struct group *gr; + struct passwd *pw; + gid_t gid, egid, lastid; + uid_t uid, euid; + int cnt, ngroups; + const char *fmt; + + uid = getuid(); + (void)printf("uid=%ju", (uintmax_t)uid); + if ((pw = getpwuid(uid)) != NULL) + (void)printf("(%s)", pw->pw_name); + gid = getgid(); + (void)printf(" gid=%ju", (uintmax_t)gid); + if ((gr = getgrgid(gid)) != NULL) + (void)printf("(%s)", gr->gr_name); + if ((euid = geteuid()) != uid) { + (void)printf(" euid=%ju", (uintmax_t)euid); + if ((pw = getpwuid(euid)) != NULL) + (void)printf("(%s)", pw->pw_name); + } + if ((egid = getegid()) != gid) { + (void)printf(" egid=%ju", (uintmax_t)egid); + if ((gr = getgrgid(egid)) != NULL) + (void)printf("(%s)", gr->gr_name); + } +#ifndef __minix + if ((ngroups = getgroups(maxgroups, groups)) != 0) { + for (fmt = " groups=%ju", lastid = -1, cnt = 0; cnt < ngroups; + fmt = ",%ju", lastid = gid, cnt++) { + gid = groups[cnt]; + if (lastid == gid) + continue; + (void)printf(fmt, (uintmax_t)gid); + if ((gr = getgrgid(gid)) != NULL) + (void)printf("(%s)", gr->gr_name); + } + } +#endif + (void)printf("\n"); +} + +static void +user(struct passwd *pw) +{ + struct group *gr; + const char *fmt; + int cnt, id, lastid, ngroups; + gid_t *glist = groups; + + id = pw->pw_uid; + (void)printf("uid=%u(%s)", id, pw->pw_name); + (void)printf(" gid=%lu", (u_long)pw->pw_gid); + if ((gr = getgrgid(pw->pw_gid)) != NULL) + (void)printf("(%s)", gr->gr_name); + ngroups = maxgroups + 1; +#ifndef __minix + if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups) == -1) { + glist = malloc(ngroups * sizeof(gid_t)); + (void) getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups); + } +#endif + for (fmt = " groups=%u", lastid = -1, cnt = 0; cnt < ngroups; + fmt=",%u", lastid = id, cnt++) { + id = glist[cnt]; + if (lastid == id) + continue; + (void)printf(fmt, id); + if ((gr = getgrgid(id)) != NULL) + (void)printf("(%s)", gr->gr_name); + } + (void)printf("\n"); + if (glist != groups) + free(glist); +} + +static void +group(struct passwd *pw, int nflag) +{ + struct group *gr; + int cnt, id, lastid, ngroups; + const char *fmt; + gid_t *glist = groups; + + if (pw) { + ngroups = maxgroups; +#ifndef __minix + if (getgrouplist(pw->pw_name, pw->pw_gid, glist, &ngroups) + == -1) { + glist = malloc(ngroups * sizeof(gid_t)); + (void) getgrouplist(pw->pw_name, pw->pw_gid, glist, + &ngroups); + + } +#endif + } else { + glist[0] = getgid(); + ngroups = getgroups(maxgroups, glist + 1) + 1; + } + fmt = nflag ? "%s" : "%u"; + for (lastid = -1, cnt = 0; cnt < ngroups; ++cnt) { + if (lastid == (id = glist[cnt]) || (cnt && id == glist[0])) + continue; + if (nflag) { + if ((gr = getgrgid(id)) != NULL) + (void)printf(fmt, gr->gr_name); + else + (void)printf(*fmt == ' ' ? " %u" : "%u", + id); + fmt = " %s"; + } else { + (void)printf(fmt, id); + fmt = " %u"; + } + lastid = id; + } + (void)printf("\n"); + if (glist != groups) + free(glist); +} + +static struct passwd * +who(char *u) +{ + struct passwd *pw; + long id; + char *ep; + + /* + * Translate user argument into a pw pointer. First, try to + * get it as specified. If that fails, try it as a number. + */ + if ((pw = getpwnam(u)) != NULL) + return pw; + id = strtol(u, &ep, 10); + if (*u && !*ep && (pw = getpwuid(id))) + return pw; + errx(1, "%s: No such user", u); + /* NOTREACHED */ + return NULL; +} + +static void +usage(void) +{ + + if (strcmp(getprogname(), "groups") == 0) { + (void)fprintf(stderr, "usage: groups [user]\n"); + } else if (strcmp(getprogname(), "whoami") == 0) { + (void)fprintf(stderr, "usage: whoami\n"); + } else { + (void)fprintf(stderr, "usage: id [user]\n"); + (void)fprintf(stderr, " id -G [-n] [user]\n"); + (void)fprintf(stderr, " id -g [-nr] [user]\n"); + (void)fprintf(stderr, " id -p [user]\n"); + (void)fprintf(stderr, " id -u [-nr] [user]\n"); + } + exit(1); +} diff --git a/commands/id/whoami.1 b/commands/id/whoami.1 new file mode 100644 index 000000000..bcb6e87a4 --- /dev/null +++ b/commands/id/whoami.1 @@ -0,0 +1,60 @@ +.\" $NetBSD: whoami.1,v 1.9 2003/08/07 11:14:07 agc Exp $ +.\" +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" from: @(#)whoami.1 8.1 (Berkeley) 6/6/93 +.\" $NetBSD: whoami.1,v 1.9 2003/08/07 11:14:07 agc Exp $ +.\" +.Dd June 6, 1993 +.Dt WHOAMI 1 +.Os +.Sh NAME +.Nm whoami +.Nd display effective user id +.Sh SYNOPSIS +.Nm +.Sh DESCRIPTION +The +.Nm +utility has been obsoleted by the +.Xr id 1 +utility, and is equivalent to +.Dq Nm id Fl un . +The command +.Dq Nm id Fl p +is suggested for normal interactive use. +.Pp +The +.Nm +utility displays your effective user ID as a name. +.Pp +The +.Nm +utility exits 0 on success, and \*[Gt]0 if an error occurs. +.Sh SEE ALSO +.Xr id 1 diff --git a/commands/touch/Makefile b/commands/touch/Makefile new file mode 100644 index 000000000..c641ea2d8 --- /dev/null +++ b/commands/touch/Makefile @@ -0,0 +1,6 @@ +# $NetBSD: Makefile,v 1.3 1994/12/07 09:19:47 jtc Exp $ +# @(#)Makefile 8.1 (Berkeley) 6/6/93 + +PROG= touch + +.include diff --git a/commands/touch/touch.1 b/commands/touch/touch.1 new file mode 100644 index 000000000..6ec2c1356 --- /dev/null +++ b/commands/touch/touch.1 @@ -0,0 +1,163 @@ +.\" $OpenBSD: touch.1,v 1.14 2007/08/06 19:16:06 sobrado Exp $ +.\" $NetBSD: touch.1,v 1.8 1995/08/31 22:10:05 jtc Exp $ +.\" +.\" Copyright (c) 1991, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)touch.1 8.3 (Berkeley) 4/28/95 +.\" +.Dd $Mdocdate: August 6 2007 $ +.Dt TOUCH 1 +.Os +.Sh NAME +.Nm touch +.Nd change file access and modification times +.Sh SYNOPSIS +.Nm touch +.Op Fl acm +.Op Fl r Ar file +.Op Fl t Ar [[CC]YY]MMDDhhmm[.SS] +.Ar +.Sh DESCRIPTION +The +.Nm +utility sets the modification and access times of files to the +current time of day. +If the file doesn't exist, it is created with default permissions. +.Pp +The options are as follows: +.Bl -tag -width Ds +.It Fl a +Change the access time of the file. +The modification time of the file is not changed unless the +.Fl m +flag is also specified. +.It Fl c +Do not create the file if it does not exist. +The +.Nm +utility does not treat this as an error. +No error messages are displayed and the exit value is not affected. +.It Fl m +Change the modification time of the file. +The access time of the file is not changed unless the +.Fl a +flag is also specified. +.It Fl r Ar file +Use the access and modification times from the specified file +instead of the current time of day. +.It Fl t Ar [[CC]YY]MMDDhhmm[.SS] +Change the access and modification times to the specified time. +The argument should be in the form +.Dq [[CC]YY]MMDDhhmm[.SS] +where each pair of letters represents the following: +.Pp +.Bl -tag -width Ds -compact -offset indent +.It Ar CC +The first two digits of the year (the century). +.It Ar YY +The second two digits of the year. +If +.Dq YY +is specified, but +.Dq CC +is not, a value for +.Dq YY +between 69 and 99 results in a +.Dq CC +value of 19. +Otherwise, a +.Dq CC +value of 20 is used. +.It Ar MM +The month of the year, from 1 to 12. +.It Ar DD +The day of the month, from 1 to 31. +.It Ar hh +The hour of the day, from 0 to 23. +.It Ar mm +The minute of the hour, from 0 to 59. +.It Ar SS +The second of the minute, from 0 to 61. +.El +.Pp +If the +.Dq CC +and +.Dq YY +letter pairs are not specified, the values default to the current +year. +If the +.Dq SS +letter pair is not specified, the value defaults to 0. +.El +.Pp +The +.Nm +utility exits 0 on success or >0 if an error occurred. +.Sh SEE ALSO +.Xr utimes 2 +.Sh STANDARDS +The +.Nm +utility is compliant with the +.St -p1003.1-2004 +specification. +.Pp +The obsolescent form of +.Nm touch , +where a time format is specified as the first argument, is supported. +When no +.Fl r +or +.Fl t +option is specified, there are at least two arguments, and the first +argument is a string of digits either eight or ten characters in length, +the first argument is interpreted as a time specification of the form +.Dq MMDDhhmm[YY] . +.Pp +The +.Dq MM , +.Dq DD , +.Dq hh +and +.Dq mm +letter pairs are treated as their counterparts specified to the +.Fl t +option. +If the +.Dq YY +letter pair is in the range 69 to 99, the year is set from 1969 to 1999; +otherwise, the year is set in the 21st century. +.Sh HISTORY +A +.Nm +utility appeared in +.At v7 . diff --git a/commands/touch/touch.c b/commands/touch/touch.c new file mode 100644 index 000000000..efedae1e0 --- /dev/null +++ b/commands/touch/touch.c @@ -0,0 +1,331 @@ +/* $OpenBSD: touch.c,v 1.17 2007/08/06 19:16:06 sobrado Exp $ */ +/* $NetBSD: touch.c,v 1.11 1995/08/31 22:10:06 jtc Exp $ */ + +/* + * Copyright (c) 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void stime_arg1(char *, struct timeval *); +void stime_arg2(char *, int, struct timeval *); +void stime_file(char *, struct timeval *); +__dead void usage(void); + +char * __progname; + +int +main(int argc, char *argv[]) +{ + struct stat sb; + struct timeval tv[2]; + struct utimbuf timbuf; + int aflag, cflag, mflag, ch, fd, len, rval, timeset; + char *p; + + (void)setlocale(LC_ALL, ""); + __progname = argv[0]; + + aflag = cflag = mflag = timeset = 0; + if (gettimeofday(&tv[0], NULL)) + err(1, "gettimeofday"); + + while ((ch = getopt(argc, argv, "acfmr:t:")) != -1) + switch (ch) { + case 'a': + aflag = 1; + break; + case 'c': + cflag = 1; + break; + case 'f': + break; + case 'm': + mflag = 1; + break; + case 'r': + timeset = 1; + stime_file(optarg, tv); + break; + case 't': + timeset = 1; + stime_arg1(optarg, tv); + break; + default: + usage(); + } + argc -= optind; + argv += optind; + + /* Default is both -a and -m. */ + if (aflag == 0 && mflag == 0) + aflag = mflag = 1; + + /* + * If no -r or -t flag, at least two operands, the first of which + * is an 8 or 10 digit number, use the obsolete time specification. + */ + if (!timeset && argc > 1) { + (void)strtol(argv[0], &p, 10); + len = p - argv[0]; + if (*p == '\0' && (len == 8 || len == 10)) { + timeset = 1; + stime_arg2(*argv++, len == 10, tv); + } + } + + /* Otherwise use the current time of day. */ + if (!timeset) + tv[1] = tv[0]; + + if (*argv == NULL) + usage(); + + for (rval = 0; *argv; ++argv) { + /* See if the file exists. */ + if (stat(*argv, &sb)) { + if (!cflag) { + /* Create the file. */ + fd = open(*argv, + O_WRONLY | O_CREAT, DEFFILEMODE); + if (fd == -1 || fstat(fd, &sb) || close(fd)) { + rval = 1; + warn("%s", *argv); + continue; + } + + /* If using the current time, we're done. */ + if (!timeset) + continue; + } else + continue; + } + +#if 0 + if (!aflag) + TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atimespec); + if (!mflag) + TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtimespec); +#else + if (!aflag) + tv[0].tv_sec = sb.st_atime; + if (!mflag) + tv[1].tv_sec = sb.st_mtime; +#endif + + /* Try utimes(2). */ +#if 0 + if (!utimes(*argv, tv)) + continue; +#else + timbuf.actime = tv[0].tv_sec; + timbuf.modtime = tv[1].tv_sec; + if (!utime(*argv, &timbuf)) + continue; +#endif + + /* If the user specified a time, nothing else we can do. */ + if (timeset) { + rval = 1; + warn("%s", *argv); + } + + /* + * System V and POSIX 1003.1 require that a NULL argument + * set the access/modification times to the current time. + * The permission checks are different, too, in that the + * ability to write the file is sufficient. Take a shot. + */ +#if 0 + if (!utimes(*argv, NULL)) + continue; +#else + if (!utime(*argv, NULL)) + continue; +#endif + + rval = 1; + warn("%s", *argv); + } + exit(rval); +} + +#define ATOI2(s) ((s) += 2, ((s)[-2] - '0') * 10 + ((s)[-1] - '0')) + +void +stime_arg1(char *arg, struct timeval *tvp) +{ + struct tm *lt; + time_t tmptime; + int yearset; + char *dot, *p; + /* Start with the current time. */ + tmptime = tvp[0].tv_sec; + if ((lt = localtime(&tmptime)) == NULL) + err(1, "localtime"); + /* [[CC]YY]MMDDhhmm[.SS] */ + for (p = arg, dot = NULL; *p != '\0'; p++) { + if (*p == '.' && dot == NULL) + dot = p; + else if (!isdigit((unsigned char)*p)) + goto terr; + } + if (dot == NULL) + lt->tm_sec = 0; /* Seconds defaults to 0. */ + else { + *dot++ = '\0'; + if (strlen(dot) != 2) + goto terr; + lt->tm_sec = ATOI2(dot); + if (lt->tm_sec > 61) /* Could be leap second. */ + goto terr; + } + + yearset = 0; + switch (strlen(arg)) { + case 12: /* CCYYMMDDhhmm */ + lt->tm_year = ATOI2(arg) * 100 - TM_YEAR_BASE; + yearset = 1; + /* FALLTHROUGH */ + case 10: /* YYMMDDhhmm */ + if (yearset) { + yearset = ATOI2(arg); + lt->tm_year += yearset; + } else { + yearset = ATOI2(arg); + /* Preserve current century. */ + lt->tm_year = ((lt->tm_year / 100) * 100) + yearset; + } + /* FALLTHROUGH */ + case 8: /* MMDDhhmm */ + lt->tm_mon = ATOI2(arg); + if (lt->tm_mon > 12 || lt->tm_mon == 0) + goto terr; + --lt->tm_mon; /* Convert from 01-12 to 00-11 */ + lt->tm_mday = ATOI2(arg); + if (lt->tm_mday > 31 || lt->tm_mday == 0) + goto terr; + lt->tm_hour = ATOI2(arg); + if (lt->tm_hour > 23) + goto terr; + lt->tm_min = ATOI2(arg); + if (lt->tm_min > 59) + goto terr; + break; + default: + goto terr; + } + + lt->tm_isdst = -1; /* Figure out DST. */ + tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt); + if (tvp[0].tv_sec == -1) +terr: errx(1, + "out of range or illegal time specification: [[CC]YY]MMDDhhmm[.SS]"); + + tvp[0].tv_usec = tvp[1].tv_usec = 0; +} + +void +stime_arg2(char *arg, int year, struct timeval *tvp) +{ + struct tm *lt; + time_t tmptime; + /* Start with the current time. */ + tmptime = tvp[0].tv_sec; + if ((lt = localtime(&tmptime)) == NULL) + err(1, "localtime"); + + lt->tm_mon = ATOI2(arg); /* MMDDhhmm[YY] */ + if (lt->tm_mon > 12 || lt->tm_mon == 0) + goto terr; + --lt->tm_mon; /* Convert from 01-12 to 00-11 */ + lt->tm_mday = ATOI2(arg); + if (lt->tm_mday > 31 || lt->tm_mday == 0) + goto terr; + lt->tm_hour = ATOI2(arg); + if (lt->tm_hour > 23) + goto terr; + lt->tm_min = ATOI2(arg); + if (lt->tm_min > 59) + goto terr; + if (year) { + year = ATOI2(arg); /* Preserve current century. */ + lt->tm_year = ((lt->tm_year / 100) * 100) + year; + } + lt->tm_sec = 0; + + lt->tm_isdst = -1; /* Figure out DST. */ + tvp[0].tv_sec = tvp[1].tv_sec = mktime(lt); + if (tvp[0].tv_sec == -1) +terr: errx(1, + "out of range or illegal time specification: MMDDhhmm[YY]"); + + tvp[0].tv_usec = tvp[1].tv_usec = 0; +} + +void +stime_file(char *fname, struct timeval *tvp) +{ + struct stat sb; + + if (stat(fname, &sb)) + err(1, "%s", fname); +#if 0 + TIMESPEC_TO_TIMEVAL(tvp, &sb.st_atimespec); + TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtimespec); +#else + (tvp + 0)->tv_sec = sb.st_atime; + (tvp + 1)->tv_sec = sb.st_mtime; +#endif +} + +__dead void +usage(void) +{ + extern char *__progname; + + (void)fprintf(stderr, + "usage: %s [-acm] [-r file] [-t [[CC]YY]MMDDhhmm[.SS]] file ...\n", + __progname); + exit(1); +} diff --git a/commands/touch/touch.d b/commands/touch/touch.d new file mode 100644 index 000000000..3115d9cea --- /dev/null +++ b/commands/touch/touch.d @@ -0,0 +1,30 @@ + +touch.o: /usr/include/ansi.h +touch.o: /usr/include/ctype.h +touch.o: /usr/include/err.h +touch.o: /usr/include/errno.h +touch.o: /usr/include/fcntl.h +touch.o: /usr/include/limits.h +touch.o: /usr/include/locale.h +touch.o: /usr/include/machine/interrupt.h +touch.o: /usr/include/minix/config.h +touch.o: /usr/include/minix/dir.h +touch.o: /usr/include/minix/limits.h +touch.o: /usr/include/minix/sys_config.h +touch.o: /usr/include/minix/type.h +touch.o: /usr/include/minix/types.h +touch.o: /usr/include/stdarg.h +touch.o: /usr/include/stdint.h +touch.o: /usr/include/stdio.h +touch.o: /usr/include/stdlib.h +touch.o: /usr/include/string.h +touch.o: /usr/include/sys/cdefs.h +touch.o: /usr/include/sys/select.h +touch.o: /usr/include/sys/stat.h +touch.o: /usr/include/sys/time.h +touch.o: /usr/include/sys/types.h +touch.o: /usr/include/time.h +touch.o: /usr/include/tzfile.h +touch.o: /usr/include/unistd.h +touch.o: /usr/include/utime.h +touch.o: touch.c