4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
34 * make a copy in spool directory
37 static int _Transfer
= 0;
43 char Sgrade
[NAMESIZE
];
47 void cleanup(), ruux(), usage();
48 int eaccess(), guinfo(), vergrd(), gwd(), ckexpf(), uidstat(), uidxcp(),
50 void commitall(), wfabort(), mailst(), gename(), svcfile();
52 char Sfile
[MAXFULLNAME
];
55 main(argc
, argv
, envp
)
64 char sys1
[MAXFULLNAME
], sys2
[MAXFULLNAME
];
65 char fwd1
[MAXFULLNAME
], fwd2
[MAXFULLNAME
];
66 char file1
[MAXFULLNAME
], file2
[MAXFULLNAME
];
67 short jflag
= 0; /* -j flag Jobid printout */
71 /* Set locale environment variables local definitions */
72 (void) setlocale(LC_ALL
, "");
73 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
74 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it wasn't */
76 (void) textdomain(TEXT_DOMAIN
);
78 /* this fails in some versions, but it doesn't hurt */
82 (void) setuid(UUCPUID
);
85 (void) strcpy(Logfile
, LOGUUCP
);
89 (void) strcpy(Progname
, "uucp");
95 if (eaccess(GRADES
, 0) != -1) {
98 sprintf(Sgrade
, "%s", "default");
102 * find name of local system
108 Optns
[3] = Nuser
[0] = Sfile
[0] = NULLCHAR
;
111 * find id of user who spawned command to
114 (void) guinfo(Uid
, User
);
117 * create/append command log
119 commandlog(argc
,argv
);
121 while ((ret
= getopt(argc
, argv
, "Ccdfg:jmn:rs:x:")) != EOF
) {
125 * make a copy of the file in the spool
152 snprintf(Xopts
, sizeof (Xopts
), "-g%s", optarg
);
154 if (strlen(optarg
) < (size_t)2 && isalnum(*optarg
))
157 (void) fprintf(stderr
, gettext("No"
158 " administrator defined service"
159 " grades available on this"
161 (void) fprintf(stderr
, gettext("UUCP"
162 " service grades range from"
163 " [A-Z][a-z] only.\n"));
168 (void) strncpy(Sgrade
, optarg
, NAMESIZE
-1);
169 Sgrade
[NAMESIZE
-1] = NULLCHAR
;
170 if (vergrd(Sgrade
) != SUCCESS
)
175 case 'j': /* job id */
180 * send notification to local user
184 (void) strcat(Optns
, "m");
188 * send notification to user on remote
189 * if no user specified do not send notification
193 * We should add "n" option to Optns only once,
194 * even if multiple -n option are passed to uucp
197 (void) strlcat(Optns
, "n", sizeof (Optns
));
200 (void) sprintf(Nuser
, "%.8s", optarg
);
203 * We do the copy multiple times when multiple
204 * -n options are specified, but
205 * only the last -n value is used.
207 (void) snprintf(Uopts
, sizeof (Uopts
), "-n%s ", Nuser
);
212 * create JCL files but do not start uucico
223 /* "m" needed for compatability */
224 (void) strcat(Optns
, "mo");
231 Debug
= atoi(optarg
);
235 fprintf(stderr
, gettext("WARNING: uucp built with SMALL"
236 " flag defined -- no debug info available\n"));
245 DEBUG(4, "\n\n** %s **\n", "START");
249 (void) snprintf(Sfile
, MAXFULLNAME
, "%s/%s",
252 (void) snprintf(Sfile
, MAXFULLNAME
, "%s", fopt
);
256 if (strlcpy(Sfile
, "dummy", sizeof (Sfile
)) >= sizeof (Sfile
))
260 * work in WORKSPACE directory
262 ret
= chdir(WORKSPACE
);
264 (void) fprintf(stderr
, gettext("No work directory - %s -"
265 " get help\n"), WORKSPACE
);
269 if (Nuser
[0] == NULLCHAR
)
270 (void) strcpy(Nuser
, User
);
271 (void) strcpy(Loginuser
, User
);
272 DEBUG(4, "UID %ld, ", (long) Uid
);
273 DEBUG(4, "User %s\n", User
);
274 if (argc
- optind
< 2) {
279 * set up "to" system and file names
282 (void) split(argv
[argc
- 1], sys2
, fwd2
, file2
);
283 if (*sys2
!= NULLCHAR
) {
284 (void) strncpy(Rmtname
, sys2
, MAXBASENAME
);
285 Rmtname
[MAXBASENAME
] = NULLCHAR
;
287 /* get real Myname - it depends on who I'm calling--Rmtname */
288 (void) mchFind(Rmtname
);
291 if (versys(sys2
) != 0) {
292 (void) fprintf(stderr
,
293 gettext("bad system: %s\n"), sys2
);
298 DEBUG(9, "sys2: %s, ", sys2
);
299 DEBUG(9, "fwd2: %s, ", fwd2
);
300 DEBUG(9, "file2: %s\n", file2
);
303 * if there are more than 2 argsc, file2 is a directory
305 if (argc
- optind
> 2)
306 (void) strcat(file2
, "/");
309 * do each from argument
312 for ( ; optind
< argc
- 1; optind
++) {
313 (void) split(argv
[optind
], sys1
, fwd1
, file1
);
314 if (*sys1
!= NULLCHAR
) {
315 if (versys(sys1
) != 0) {
316 (void) fprintf(stderr
,
317 gettext("bad system: %s\n"), sys1
);
322 /* source files can have at most one ! */
323 if (*fwd1
!= NULLCHAR
) {
325 (void) fprintf(stderr
,
326 gettext("illegal syntax %s\n"), argv
[optind
]);
331 * check for required remote expansion of file names -- generate
332 * and execute a uux command
334 * uucp owl!~/dan/.. ~/dan/
336 * NOTE: The source file part must be full path name.
337 * If ~ it will be expanded locally - it assumes the remote
338 * names are the same.
341 if (*sys1
!= NULLCHAR
)
342 if ((strchr(file1
, '*') != NULL
343 || strchr(file1
, '?') != NULL
344 || strchr(file1
, '[') != NULL
)) {
345 /* do a uux command */
346 if (ckexpf(file1
) == FAIL
)
348 (void) strncpy(Rmtname
, sys1
, MAXBASENAME
);
349 Rmtname
[MAXBASENAME
] = NULLCHAR
;
350 /* get real Myname - it depends on who I'm calling--Rmtname */
351 (void) mchFind(Rmtname
);
353 if (*sys2
== NULLCHAR
)
355 ruux(sys1
, sys1
, file1
, sys2p
, fwd2
, file2
);
360 * check for forwarding -- generate and execute a uux command
362 * uucp uucp.c raven!owl!~/dan/
365 if (*fwd2
!= NULLCHAR
) {
366 ruux(sys2
, sys1
, file1
, "", fwd2
, file2
);
371 * check for both source and destination on other systems --
372 * generate and execute a uux command
375 if (*sys1
!= NULLCHAR
)
376 if ( (!EQUALS(Myname
, sys1
))
378 && (!EQUALS(sys2
, Myname
)) ) {
379 ruux(sys2
, sys1
, file1
, "", fwd2
, file2
);
385 if (*sys1
== NULLCHAR
) {
386 if (*sys2
== NULLCHAR
)
388 (void) strcpy(sys1
, Myname
);
390 (void) strncpy(Rmtname
, sys1
, MAXBASENAME
);
391 Rmtname
[MAXBASENAME
] = NULLCHAR
;
392 /* get real Myname - it depends on who I'm calling--Rmtname */
393 (void) mchFind(Rmtname
);
395 if (*sys2
== NULLCHAR
)
399 DEBUG(4, "sys1 - %s, ", sys1
);
400 DEBUG(4, "file1 - %s, ", file1
);
401 DEBUG(4, "Rmtname - %s\n", Rmtname
);
402 if (copy(sys1
, file1
, sys2p
, file2
))
406 /* move the work files to their proper places */
410 * Wait for all background uux processes to finish so
411 * that our caller will know that we're done with all
412 * input files and it's safe to remove them.
414 while (wait(NULL
) != -1)
418 * do not spawn daemon if -r option specified
424 limit
= ulimit(1, (long) 0);
425 if (limit
< MINULIMIT
) {
427 "ULIMIT (%ld) < MINULIMIT (%ld)", limit
, MINULIMIT
);
428 logent(msg
, "Low-ULIMIT");
435 (void) strncpy(Jobid
, jid(), NAMESIZE
);
436 printf("%s\n", Jobid
);
444 * cleanup lock files before exiting
450 static int first
= 1;
456 wfabort(); /* this may be extreme -- abort all work */
459 (void) fprintf(stderr
,
460 gettext("uucp failed completely (%d)\n"), (-code
));
464 (void) fprintf(stderr
, gettext(
465 "uucp failed partially: %d file(s) sent; %d error(s)\n"),
472 static FILE *syscfile();
474 * generate copy files for s1!f1 -> s2!f2
475 * Note: only one remote machine, other situations
476 * have been taken care of in main.
479 * Non-zero -> failure
483 char *s1
, *f1
, *s2
, *f2
;
486 struct stat stbuf
, stbuf1
;
488 char dfile
[NAMESIZE
];
489 char cfile
[NAMESIZE
];
490 char command
[10+(2*MAXFULLNAME
)];
491 char file1
[MAXFULLNAME
], file2
[MAXFULLNAME
];
495 (void) strcpy(file1
, f1
);
496 (void) strcpy(file2
, f2
);
497 if (!EQUALS(s1
, Myname
))
499 if (!EQUALS(s2
, Myname
))
502 DEBUG(4, "copy: file1=<%s> ", file1
);
503 DEBUG(4, "file2=<%s>\n", file2
);
510 DEBUG(4, "all work here %d\n", type
);
513 * check access control permissions
521 if (chkperm(file1
, file2
, strchr(Optns
, 'd')) &&
522 (access(file2
, W_OK
) == -1)) {
523 (void) fprintf(stderr
, gettext("permission denied\n"));
530 * Changed from uidxcp() to fic file made and owner
531 * being modified for existing files, and local file
534 DEBUG(2, "local copy: %s -> ", file1
);
535 DEBUG(2, "%s\n", file2
);
537 sprintf(command
, "cp %s %s", file1
, file2
);
538 if ((cfp
= popen(command
, "r")) == NULL
) {
540 DEBUG(5, "popen failed - errno %d\n", errno
);
544 if (pclose(cfp
) != 0) {
545 DEBUG(5, "Copy failed - errno %d\n", errno
);
551 * if user specified -m, notify "local" user
555 "REQUEST: %s!%s --> %s!%s (%s)\n(SYSTEM %s) copy succeeded\n",
556 s1
, file1
, s2
, file2
, User
, s2
);
557 mailst(User
, "copy succeeded", msg
, "", "");
560 * if user specified -n, notify "remote" user
563 sprintf(msg
, "%s from %s!%s arrived\n",
565 mailst(Nuser
, msg
, msg
, "", "");
573 DEBUG(4, "receive file - %d\n", type
);
576 * expand source and destination file names
577 * and check access permissions
586 gename(DATAPRE
, s2
, Grade
, dfile
);
589 * insert JCL card in file
591 cfp
= syscfile(cfile
, s1
);
593 "R %s %s %s %s %s %o %s %s\n", file1
, file2
,
595 *Sfile
? Sfile
: "dummy",
598 (void) sprintf(msg
, "%s!%s --> %s!%s", Rmtname
, file1
,
600 logent(msg
, "QUEUED");
609 /* XQTDIR hook enables 3rd party uux requests (cough) */
610 DEBUG(4, "Workdir = <%s>\n", Wrkdir
);
611 if (file2
[0] != '~' && !EQUALS(Wrkdir
, XQTDIR
))
614 DEBUG(4, "send file - %d\n", type
);
616 if (uidstat(file1
, &stbuf
) != 0) {
617 (void) fprintf(stderr
,
618 gettext("can't get status for file %s\n"), file1
);
621 if ((stbuf
.st_mode
& S_IFMT
) == S_IFDIR
) {
622 (void) fprintf(stderr
,
623 gettext("directory name illegal - %s\n"), file1
);
626 /* see if I can read this file as read uid, gid */
627 if (access(file1
, R_OK
) != 0) {
628 (void) fprintf(stderr
,
629 gettext("uucp can't read (%s) mode (%o)\n"),
630 file1
, stbuf
.st_mode
&0777);
635 * make a copy of file in spool directory
638 gename(DATAPRE
, s2
, Grade
, dfile
);
640 if (Copy
|| !READANY(file1
) ) {
642 if (uidxcp(file1
, dfile
))
645 (void) chmod(dfile
, DFILEMODE
);
648 cfp
= syscfile(cfile
, s2
);
649 (void) fprintf(cfp
, "S %s %s %s %s %s %lo %s %s\n",
650 file1
, file2
, User
, Optns
, dfile
,
651 (long) stbuf
.st_mode
& LEGALMODE
, Nuser
, Sfile
);
653 (void) sprintf(msg
, "%s!%s --> %s!%s", Myname
, file1
,
655 logent(msg
, "QUEUED");
664 * syscfile(file, sys)
667 * get the cfile for system sys (creat if need be)
668 * return stream pointer
671 * stream pointer to open cfile
681 if (gtcfile(file
, sys
) == FAIL
) {
682 gename(CMDPRE
, sys
, Grade
, file
);
683 ASSERT(access(file
, 0) != 0, Fl_EXISTS
, file
, errno
);
684 cfp
= fdopen(creat(file
, CFILEMODE
), "w");
685 svcfile(file
, sys
, Sgrade
);
687 cfp
= fopen(file
, "a");
688 ASSERT(cfp
!= NULL
, Ct_OPEN
, file
, errno
);
694 * generate and execute a uux command
698 ruux(rmt
, sys1
, file1
, sys2
, fwd2
, file2
)
699 char *rmt
, *sys1
, *file1
, *sys2
, *fwd2
, *file2
;
707 /* get real Myname - it depends on who I'm calling--rmt */
713 if (*Xopts
!= NULLCHAR
)
714 xarg
[narg
++] = Xopts
;
718 (void) sprintf(cmd
, "%s!uucp -C", rmt
);
720 if (*Uopts
!= NULLCHAR
)
721 (void) sprintf(cmd
+strlen(cmd
), " (%s) ", Uopts
);
723 if (*sys1
== NULLCHAR
|| EQUALS(sys1
, Myname
)) {
726 (void) sprintf(cmd
+strlen(cmd
), " %s!%s ", sys1
, file1
);
729 if (!EQUALS(rmt
, sys1
))
730 (void) sprintf(cmd
+strlen(cmd
), " (%s!%s) ", sys1
, file1
);
732 (void) sprintf(cmd
+strlen(cmd
), " (%s) ", file1
);
734 if (*fwd2
!= NULLCHAR
) {
735 if (*sys2
!= NULLCHAR
)
736 (void) sprintf(cmd
+strlen(cmd
),
737 " (%s!%s!%s) ", sys2
, fwd2
, file2
);
739 (void) sprintf(cmd
+strlen(cmd
), " (%s!%s) ", fwd2
, file2
);
742 if (*sys2
== NULLCHAR
|| EQUALS(sys2
, Myname
))
745 (void) sprintf(cmd
+strlen(cmd
), " (%s!%s) ", sys2
, file2
);
749 xarg
[narg
] = (char *) 0;
752 for (i
=0; i
< narg
; i
++) {
753 strcat(xcmd
, xarg
[i
]);
756 DEBUG(2, "cmd: %s\n", xcmd
);
757 logent(xcmd
, "QUEUED");
760 ASSERT(setuid(getuid()) == 0, "setuid", "failed", 99);
771 (void) fprintf(stderr
, gettext(
772 "Usage: %s [-c|-C] [-d|-f] [-g GRADE] [-jm] [-n USER]\\\n"
773 "[-r] [-s FILE] [-x DEBUG_LEVEL] source-files destination-file\n"),