]> err.no Git - sash/blob - cmds.c
Stop stripping during build. Also thanks to Helmut Grohne. Closes: #852771
[sash] / cmds.c
1 /*
2  * Copyright (c) 2014 by David I. Bell
3  * Permission is granted to use, distribute, or modify this source,
4  * provided that this copyright notice remains intact.
5  *
6  * Most simple built-in commands are here.
7  */
8
9 #include "sash.h"
10
11 #include <sys/types.h>
12 #include <sys/stat.h>
13 #include <sys/mount.h>
14 #include <signal.h>
15 #include <pwd.h>
16 #include <grp.h>
17 #include <utime.h>
18 #include <errno.h>
19
20 #if     HAVE_LINUX_MOUNT
21 #include <linux/fs.h>
22 #endif
23
24 /* Need to tell loop.h what the actual dev_t type is. */
25 #undef dev_t
26 #if defined(__alpha) || (defined(__sparc__) && defined(__arch64__))
27 #define dev_t unsigned int
28 #else
29 #define dev_t unsigned short
30 #endif
31 #include <linux/loop.h>
32 #undef dev_t
33 #define dev_t dev_t
34
35
36 int
37 do_echo(int argc, const char ** argv)
38 {
39         BOOL    first;
40
41         first = TRUE;
42
43         while (argc-- > 1)
44         {
45                 if (!first)
46                         fputc(' ', stdout);
47
48                 first = FALSE;
49                 fputs(*(++argv), stdout);
50         }
51
52         fputc('\n', stdout);
53
54         return 0;
55 }
56
57
58 int
59 do_pwd(int argc, const char ** argv)
60 {
61         char    buf[PATH_LEN];
62
63         if (getcwd(buf, PATH_LEN) == NULL)
64         {
65                 fprintf(stderr, "Cannot get current directory\n");
66
67                 return 1;
68         }
69
70         printf("%s\n", buf);
71
72         return 0;
73 }
74
75
76 int
77 do_cd(int argc, const char ** argv)
78 {
79         const char *    path;
80
81         if (argc > 1)
82                 path = argv[1];
83         else
84         {
85                 path = getenv("HOME");
86
87                 if (path == NULL)
88                 {
89                         fprintf(stderr, "No HOME environment variable\n");
90
91                         return 1;
92                 }
93         }
94
95         if (chdir(path) < 0)
96         {
97                 perror(path);
98
99                 return 1;
100         }
101
102         return 0;
103 }
104
105
106 int
107 do_mkdir(int argc, const char ** argv)
108 {
109         int r = 0;
110
111         while (argc-- > 1)
112         {
113                 if (mkdir(argv[1], 0777) < 0)
114                 {
115                         perror(argv[1]);
116                         r = 1;
117                 }
118
119                 argv++;
120         }
121
122         return r;
123 }
124
125
126 int
127 do_mknod(int argc, const char ** argv)
128 {
129         const char *    cp;
130         int             mode;
131         int             major;
132         int             minor;
133
134         mode = 0666;
135
136         if (strcmp(argv[2], "b") == 0)
137                 mode |= S_IFBLK;
138         else if (strcmp(argv[2], "c") == 0)
139                 mode |= S_IFCHR;
140         else
141         {
142                 fprintf(stderr, "Bad device type\n");
143
144                 return 1;
145         }
146
147         major = 0;
148         cp = argv[3];
149
150         while (isDecimal(*cp))
151                 major = major * 10 + *cp++ - '0';
152
153         if (*cp || (major < 0) || (major > 255))
154         {
155                 fprintf(stderr, "Bad major number\n");
156
157                 return 1;
158         }
159
160         minor = 0;
161         cp = argv[4];
162
163         while (isDecimal(*cp))
164                 minor = minor * 10 + *cp++ - '0';
165
166         if (*cp || (minor < 0) || (minor > 255))
167         {
168                 fprintf(stderr, "Bad minor number\n");
169
170                 return 1;
171         }
172
173         if (mknod(argv[1], mode, major * 256 + minor) < 0)
174         {
175                 perror(argv[1]);
176
177                 return 1;
178         }
179
180         return 0;
181 }
182
183
184 #if HAVE_LINUX_PIVOT
185
186 int
187 do_pivot_root(int argc, const char ** argv)
188 {
189         if (pivot_root(argv[1], argv[2]) < 0)
190         {
191                 perror("pivot_root");
192
193                 return 1;
194         }
195
196         return 0;
197 }
198
199 #endif
200
201
202 #if HAVE_LINUX_CHROOT
203
204 int
205 do_chroot(int argc, const char ** argv)
206 {
207         if (chroot(argv[1]) < 0)
208         {
209                 perror("chroot");
210
211                 return 1;
212         }
213
214         return 0;
215 }
216
217 #endif
218
219
220 int
221 do_rmdir(int argc, const char ** argv)
222 {
223         int r = 0;
224
225         while (argc-- > 1)
226         {
227                 if (rmdir(argv[1]) < 0)
228                 {
229                         perror(argv[1]);
230                         r = 1;
231                 }
232
233                 argv++;
234         }
235
236         return r;
237 }
238
239
240 int
241 do_sync(int argc, const char ** argv)
242 {
243         sync();
244
245         return 0;
246 }
247
248
249 int
250 do_rm(int argc, const char ** argv)
251 {
252         int r = 0;
253
254         while (argc-- > 1)
255         {
256                 if (unlink(argv[1]) < 0)
257                 {
258                         perror(argv[1]);
259                         r = 1;
260                 }
261
262                 argv++;
263         }
264
265         return r;
266 }
267
268
269 int
270 do_chmod(int argc, const char ** argv)
271 {
272         const char *    cp;
273         int             mode;
274         int             r;
275
276         r = 0;
277         mode = 0;
278         cp = argv[1];
279
280         while (isOctal(*cp))
281                 mode = mode * 8 + (*cp++ - '0');
282
283         if (*cp)
284         {
285                 fprintf(stderr, "Mode must be octal\n");
286
287                 return 1;
288         }
289
290         argc--;
291         argv++;
292
293         while (argc-- > 1)
294         {
295                 if (chmod(argv[1], mode) < 0)
296                 {
297                         perror(argv[1]);
298                         r = 1;
299                 }
300
301                 argv++;
302         }
303
304         return r;
305 }
306
307
308 int
309 do_chown(int argc, const char ** argv)
310 {
311         const char *    cp;
312         int             uid;
313         struct passwd * pwd;
314         struct stat     statBuf;
315         int             r;
316
317         r = 0;
318         cp = argv[1];
319
320         if (isDecimal(*cp))
321         {
322                 uid = 0;
323
324                 while (isDecimal(*cp))
325                         uid = uid * 10 + (*cp++ - '0');
326
327                 if (*cp)
328                 {
329                         fprintf(stderr, "Bad uid value\n");
330
331                         return 1;
332                 }
333         }
334         else
335         {
336                 pwd = getpwnam(cp);
337
338                 if (pwd == NULL)
339                 {
340                         fprintf(stderr, "Unknown user name\n");
341
342                         return 1;
343                 }
344
345                 uid = pwd->pw_uid;
346         }
347
348         argc--;
349         argv++;
350
351         while (argc-- > 1)
352         {
353                 argv++;
354
355                 if ((stat(*argv, &statBuf) < 0) ||
356                         (chown(*argv, uid, statBuf.st_gid) < 0))
357                 {
358                         perror(*argv);
359                         r = 1;
360                 }
361         }
362
363         return r;
364 }
365
366
367 int
368 do_chgrp(int argc, const char ** argv)
369 {
370         const char *    cp;
371         int             gid;
372         struct group *  grp;
373         struct stat     statBuf;
374         int             r;
375
376         r = 0;
377         cp = argv[1];
378
379         if (isDecimal(*cp))
380         {
381                 gid = 0;
382
383                 while (isDecimal(*cp))
384                         gid = gid * 10 + (*cp++ - '0');
385
386                 if (*cp)
387                 {
388                         fprintf(stderr, "Bad gid value\n");
389
390                         return 1;
391                 }
392         }
393         else
394         {
395                 grp = getgrnam(cp);
396
397                 if (grp == NULL)
398                 {
399                         fprintf(stderr, "Unknown group name\n");
400
401                         return 1;
402                 }
403
404                 gid = grp->gr_gid;
405         }
406
407         argc--;
408         argv++;
409
410         while (argc-- > 1)
411         {
412                 argv++;
413
414                 if ((stat(*argv, &statBuf) < 0) ||
415                         (chown(*argv, statBuf.st_uid, gid) < 0))
416                 {
417                         perror(*argv);
418                         r = 1;
419                 }
420         }
421
422         return r;
423 }
424
425
426 int
427 do_touch(int argc, const char ** argv)
428 {
429         const char *    name;
430         int             fd;
431         struct utimbuf  now;
432         int             r;
433
434         r = 0;
435         time(&now.actime);
436         now.modtime = now.actime;
437
438         while (argc-- > 1)
439         {
440                 name = *(++argv);
441
442                 fd = open(name, O_CREAT | O_WRONLY | O_EXCL, 0666);
443
444                 if (fd >= 0)
445                 {
446                         close(fd);
447
448                         continue;
449                 }
450
451                 if (errno != EEXIST)
452                 {
453                         perror(name);
454                         r = 1;
455
456                         continue;
457                 }
458
459                 if (utime(name, &now) < 0)
460                 {
461                         perror(name);
462                         r = 1;
463                 }
464         }
465
466         return r;
467 }
468
469
470 int
471 do_mv(int argc, const char ** argv)
472 {
473         const char *    srcName;
474         const char *    destName;
475         const char *    lastArg;
476         BOOL            dirFlag;
477         int             r;
478
479         r = 0;
480         lastArg = argv[argc - 1];
481
482         dirFlag = isDirectory(lastArg);
483
484         if ((argc > 3) && !dirFlag)
485         {
486                 fprintf(stderr, "%s: not a directory\n", lastArg);
487
488                 return 1;
489         }
490
491         while (!intFlag && (argc-- > 2))
492         {
493                 srcName = *(++argv);
494
495                 if (access(srcName, 0) < 0)
496                 {
497                         perror(srcName);
498                         r = 1;
499
500                         continue;
501                 }
502
503                 destName = lastArg;
504
505                 if (dirFlag)
506                         destName = buildName(destName, srcName);
507
508                 if (rename(srcName, destName) >= 0)
509                         continue;
510
511                 if (errno != EXDEV)
512                 {
513                         perror(destName);
514                         r = 1;
515
516                         continue;
517                 }
518
519                 if (!copyFile(srcName, destName, TRUE))
520                 {
521                         r = 1;
522
523                         continue;
524                 }
525
526                 if (unlink(srcName) < 0)
527                 {
528                         perror(srcName);
529                         r = 1;
530                 }
531         }
532
533         return r;
534 }
535
536
537 int
538 do_ln(int argc, const char ** argv)
539 {
540         const char *    srcName;
541         const char *    destName;
542         const char *    lastArg;
543         BOOL            dirFlag;
544         int             r;
545
546         r = 0;
547
548         if (argv[1][0] == '-')
549         {
550                 if (strcmp(argv[1], "-s"))
551                 {
552                         fprintf(stderr, "Unknown option\n");
553
554                         return 1;
555                 }
556
557                 if (argc != 4)
558                 {
559                         fprintf(stderr, "Wrong number of arguments for symbolic link\n");
560
561                         return 1;
562                 }
563
564 #ifdef  S_ISLNK
565                 if (symlink(argv[2], argv[3]) < 0)
566                 {
567                         perror(argv[3]);
568
569                         return 1;
570                 }
571
572                 return 0;
573 #else
574                 fprintf(stderr, "Symbolic links are not allowed\n");
575
576                 return 1;
577 #endif
578         }
579
580         /*
581          * Here for normal hard links.
582          */
583         lastArg = argv[argc - 1];
584         dirFlag = isDirectory(lastArg);
585
586         if ((argc > 3) && !dirFlag)
587         {
588                 fprintf(stderr, "%s: not a directory\n", lastArg);
589
590                 return 1;
591         }
592
593         while (argc-- > 2)
594         {
595                 srcName = *(++argv);
596
597                 if (access(srcName, 0) < 0)
598                 {
599                         perror(srcName);
600                         r = 1;
601
602                         continue;
603                 }
604
605                 destName = lastArg;
606
607                 if (dirFlag)
608                         destName = buildName(destName, srcName);
609
610                 if (link(srcName, destName) < 0)
611                 {
612                         perror(destName);
613                         r = 1;
614
615                         continue;
616                 }
617         }
618
619         return r;
620 }
621
622
623 int
624 do_cp(int argc, const char ** argv)
625 {
626         const char *    srcName;
627         const char *    destName;
628         const char *    lastArg;
629         BOOL            dirFlag;
630         int             r;
631
632         r = 0;
633         lastArg = argv[argc - 1];
634
635         dirFlag = isDirectory(lastArg);
636
637         if ((argc > 3) && !dirFlag)
638         {
639                 fprintf(stderr, "%s: not a directory\n", lastArg);
640
641                 return 1;
642         }
643
644         while (!intFlag && (argc-- > 2))
645         {
646                 srcName = *(++argv);
647                 destName = lastArg;
648
649                 if (dirFlag)
650                         destName = buildName(destName, srcName);
651
652                 if (!copyFile(srcName, destName, FALSE))
653                         r = 1;
654         }
655
656         return r;
657 }
658
659
660 int
661 do_mount(int argc, const char ** argv)
662 {
663         const char *    str;
664         const char *    type;
665         int             flags;
666
667         argc--;
668         argv++;
669
670         type = MOUNT_TYPE;
671
672 #if     HAVE_LINUX_MOUNT
673         flags = MS_MGC_VAL;
674 #else
675         flags = 0;
676 #endif
677
678         while ((argc > 0) && (**argv == '-'))
679         {
680                 argc--;
681                 str = *argv++;
682
683                 while (*++str) switch (*str)
684                 {
685                         case 't':
686                                 if ((argc <= 0) || (**argv == '-'))
687                                 {
688                                         fprintf(stderr, "Missing file system type\n");
689
690                                         return 1;
691                                 }
692
693                                 type = *argv++;
694                                 argc--;
695                                 break;
696
697 #if     HAVE_LINUX_MOUNT
698                         case 'r':
699                                 flags |= MS_RDONLY;
700                                 break;
701
702                         case 'm':
703                                 flags |= MS_REMOUNT;
704                                 break;
705
706                         case 's':
707                                 flags |= MS_NOSUID;
708                                 break;
709
710                         case 'e':
711                                 flags |= MS_NOEXEC;
712                                 break;
713
714 #elif   HAVE_BSD_MOUNT
715                         case 'r':
716                                 flags |= MNT_RDONLY;
717                                 break;
718
719                         case 's':
720                                 flags |= MNT_NOSUID;
721                                 break;
722
723                         case 'e':
724                                 flags |= MNT_NOEXEC;
725                                 break;
726 #endif
727                         default:
728                                 fprintf(stderr, "Unknown option\n");
729
730                                 return 1;
731                 }
732         }
733
734         if (argc != 2)
735         {
736                 fprintf(stderr, "Wrong number of arguments for mount\n");
737
738                 return 1;
739         }
740
741 #if     HAVE_LINUX_MOUNT
742
743         if (mount(argv[0], argv[1], type, flags, 0) < 0)
744         {
745                 perror("mount failed");
746                 return 1;
747         }
748 #elif   HAVE_BSD_MOUNT
749         {
750                 struct      ufs_args ufs;
751                 struct      adosfs_args adosfs;
752                 struct      iso_args iso;
753                 struct      mfs_args mfs;
754                 struct      msdosfs_args msdosfs;
755                 void *      args;
756
757                 if (!strcmp(type, "ffs") || !strcmp(type, "ufs"))
758                 {
759                         ufs.fspec = (char*) argv[0];
760                         args = &ufs;
761                 }
762                 else if (!strcmp(type, "adosfs"))
763                 {
764                         adosfs.fspec = (char*) argv[0];
765                         adosfs.uid = 0;
766                         adosfs.gid = 0;
767                         args = &adosfs;
768                 }
769                 else if (!strcmp(type, "cd9660"))
770                 {
771                         iso.fspec = (char*) argv[0];
772                         args = &iso;
773                 }
774                 else if (!strcmp(type, "mfs"))
775                 {
776                         mfs.fspec = (char*) argv[0];
777                         args = &mfs;
778                 }
779                 else if (!strcmp(type, "msdos"))
780                 {
781                         msdosfs.fspec = (char*) argv[0];
782                         msdosfs.uid = 0;
783                         msdosfs.gid = 0;
784                         args = &msdosfs;
785                 }
786                 else
787                 {
788                         fprintf(stderr, "Unknown filesystem type: %s", type);
789                         fprintf(stderr,
790                             "Supported: ffs ufs adosfs cd9660 mfs msdos\n");
791
792                         return 1;
793                 }
794
795                 if (mount(type, argv[1], flags, args) < 0)
796                 {
797                         perror(argv[0]);
798
799                         return 1;
800                 }
801         }
802 #endif
803         return 0;
804 }
805
806
807 int
808 do_umount(int argc, const char ** argv)
809 {
810 #if     HAVE_LINUX_MOUNT
811         if (umount(argv[1]) < 0)
812         {
813                 perror(argv[1]);
814
815                 return 1;
816         }
817 #elif   HAVE_BSD_MOUNT
818         {
819                 const char *    str;
820                 int             flags = 0;
821
822                 for (argc--, argv++;
823                     (argc > 0) && (**argv == '-');)
824                 {
825                         argc--;
826                         str = *argv++;
827
828                         while (*++str)
829 {
830                                 switch (*str)
831                                 {
832                                         case 'f':
833                                                 flags = MNT_FORCE;
834                                                 break;
835                                 }
836                         }
837                 }
838
839                 if (unmount(argv[0], flags) < 0)
840                 {
841                         perror(argv[0]);
842
843                         return 1;
844                 }
845         }
846 #endif
847         return 0;
848 }
849
850
851 int
852 do_cmp(int argc, const char ** argv)
853 {
854         int             fd1;
855         int             fd2;
856         int             cc1;
857         int             cc2;
858         long            pos;
859         const char *    bp1;
860         const char *    bp2;
861         char            buf1[BUF_SIZE];
862         char            buf2[BUF_SIZE];
863         struct  stat    statBuf1;
864         struct  stat    statBuf2;
865         int             r;
866
867         r = 0;
868
869         if (stat(argv[1], &statBuf1) < 0)
870         {
871                 perror(argv[1]);
872
873                 return 1;
874         }
875
876         if (stat(argv[2], &statBuf2) < 0)
877         {
878                 perror(argv[2]);
879
880                 return 1;
881         }
882
883         if ((statBuf1.st_dev == statBuf2.st_dev) &&
884                 (statBuf1.st_ino == statBuf2.st_ino))
885         {
886                 printf("Files are links to each other\n");
887
888                 return 0;
889         }
890
891         if (statBuf1.st_size != statBuf2.st_size)
892         {
893                 printf("Files are different sizes\n");
894
895                 return 1;
896         }
897
898         fd1 = open(argv[1], O_RDONLY);
899
900         if (fd1 < 0)
901         {
902                 perror(argv[1]);
903
904                 return 1;
905         }
906
907         fd2 = open(argv[2], O_RDONLY);
908
909         if (fd2 < 0)
910         {
911                 perror(argv[2]);
912                 close(fd1);
913
914                 return 1;
915         }
916
917         pos = 0;
918
919         while (TRUE)
920         {
921                 if (intFlag)
922                         goto closefiles;
923
924                 cc1 = read(fd1, buf1, sizeof(buf1));
925
926                 if (cc1 < 0)
927                 {
928                         perror(argv[1]);
929                         r = 1;
930                         goto closefiles;
931                 }
932
933                 cc2 = read(fd2, buf2, sizeof(buf2));
934
935                 if (cc2 < 0)
936                 {
937                         perror(argv[2]);
938                         r = 1;
939                         goto closefiles;
940                 }
941
942                 if ((cc1 == 0) && (cc2 == 0))
943                 {
944                         printf("Files are identical\n");
945                         r = 0;
946                         goto closefiles;
947                 }
948
949                 if (cc1 < cc2)
950                 {
951                         printf("First file is shorter than second\n");
952                         r = 1;
953                         goto closefiles;
954                 }
955
956                 if (cc1 > cc2)
957                 {
958                         printf("Second file is shorter than first\n");
959                         r = 1;
960                         goto closefiles;
961                 }
962
963                 if (memcmp(buf1, buf2, cc1) == 0)
964                 {
965                         pos += cc1;
966
967                         continue;
968                 }
969
970                 bp1 = buf1;
971                 bp2 = buf2;
972
973                 while (*bp1++ == *bp2++)
974                         pos++;
975
976                 printf("Files differ at byte position %ld\n", pos);
977                 r = 1;
978
979                 goto closefiles;
980         }
981
982 closefiles:
983         close(fd1);
984         close(fd2);
985
986         return r;
987 }
988
989
990 int
991 do_more(int argc, const char ** argv)
992 {
993         FILE *          fp;
994         const char *    name;
995         int             ch;
996         int             line;
997         int             col;
998         int             pageLines;
999         int             pageColumns;
1000         char            buf[80];
1001
1002         /*
1003          * Get the width and height of the screen if it is set.
1004          * If not, then default it.
1005          */
1006         pageLines = 0;
1007         pageColumns = 0;
1008
1009         name = getenv("LINES");
1010
1011         if (name)
1012                 pageLines = atoi(name);
1013
1014         name = getenv("COLS");
1015
1016         if (name)
1017                 pageColumns = atoi(name);
1018
1019         if (pageLines <= 0)
1020                 pageLines = 24;
1021
1022         if (pageColumns <= 0)
1023                 pageColumns = 80;
1024
1025         /*
1026          * OK, process each file.
1027          */
1028         while (argc-- > 1)
1029         {
1030                 name = *(++argv);
1031
1032                 fp = fopen(name, "r");
1033
1034                 if (fp == NULL)
1035                 {
1036                         perror(name);
1037
1038                         return 1;
1039                 }
1040
1041                 printf("<< %s >>\n", name);
1042                 line = 1;
1043                 col = 0;
1044
1045                 while (fp && ((ch = fgetc(fp)) != EOF))
1046                 {
1047                         switch (ch)
1048                         {
1049                                 case '\r':
1050                                         col = 0;
1051                                         break;
1052
1053                                 case '\n':
1054                                         line++;
1055                                         col = 0;
1056                                         break;
1057
1058                                 case '\t':
1059                                         col = ((col + 1) | 0x07) + 1;
1060                                         break;
1061
1062                                 case '\b':
1063                                         if (col > 0)
1064                                                 col--;
1065                                         break;
1066
1067                                 default:
1068                                         col++;
1069                         }
1070
1071                         putchar(ch);
1072
1073                         if (col >= pageColumns)
1074                         {
1075                                 col -= pageColumns;
1076                                 line++;
1077                         }
1078
1079                         if (line < pageLines)
1080                                 continue;
1081
1082                         if (col > 0)
1083                                 putchar('\n');
1084
1085                         printf("--More--");
1086                         fflush(stdout);
1087
1088                         if (intFlag || (read(0, buf, sizeof(buf)) < 0))
1089                         {
1090                                 if (fp)
1091                                         fclose(fp);
1092
1093                                 return 0;
1094                         }
1095
1096                         ch = buf[0];
1097
1098                         if (ch == ':')
1099                                 ch = buf[1];
1100
1101                         switch (ch)
1102                         {
1103                                 case 'N':
1104                                 case 'n':
1105                                         fclose(fp);
1106                                         fp = NULL;
1107                                         break;
1108
1109                                 case 'Q':
1110                                 case 'q':
1111                                         fclose(fp);
1112
1113                                         return 0;
1114                         }
1115
1116                         col = 0;
1117                         line = 1;
1118                 }
1119
1120                 if (fp)
1121                         fclose(fp);
1122         }
1123
1124         return 0;
1125 }
1126
1127
1128 int
1129 do_sum(int argc, const char ** argv)
1130 {
1131         const char *    name;
1132         int             fd;
1133         int             cc;
1134         int             ch;
1135         int             i;
1136         unsigned long   checksum;
1137         char            buf[BUF_SIZE];
1138         int             r;
1139
1140         argc--;
1141         argv++;
1142         r = 0;
1143
1144         while (argc-- > 0)
1145         {
1146                 name = *argv++;
1147
1148                 fd = open(name, O_RDONLY);
1149
1150                 if (fd < 0)
1151                 {
1152                         perror(name);
1153                         r = 1;
1154
1155                         continue;
1156                 }
1157
1158                 checksum = 0;
1159
1160                 while ((cc = read(fd, buf, sizeof(buf))) > 0)
1161                 {
1162                         for (i = 0; i < cc; i++)
1163                         {
1164                                 ch = buf[i];
1165
1166                                 if ((checksum & 0x01) != 0)
1167                                         checksum = (checksum >> 1) + 0x8000;
1168                                 else
1169                                         checksum = (checksum >> 1);
1170
1171                                 checksum = (checksum + ch) & 0xffff;
1172                         }
1173                 }
1174
1175                 if (cc < 0)
1176                 {
1177                         perror(name);
1178                         r = 1;
1179
1180                         (void) close(fd);
1181
1182                         continue;
1183                 }
1184
1185                 (void) close(fd);
1186
1187                 printf("%05lu %s\n", checksum, name);
1188         }
1189
1190         return r;
1191 }
1192
1193
1194 int
1195 do_exit(int argc, const char ** argv)
1196 {
1197         int r = 0;
1198
1199         if (getpid() == 1)
1200         {
1201                 fprintf(stderr, "You are the INIT process!\n");
1202
1203                 return 1;
1204         }
1205
1206         if (argc == 2)
1207         {
1208                 r = atoi(argv[1]);
1209         }
1210
1211         exit(r);
1212
1213         return 1;
1214 }
1215
1216
1217 int
1218 do_setenv(int argc, const char ** argv)
1219 {
1220         const char *    name;
1221         const char *    value;
1222         char *          str;
1223
1224         name = argv[1];
1225         value = argv[2];
1226
1227         /*
1228          * The value given to putenv must remain around, so we must malloc it.
1229          * Note: memory is not reclaimed if the same variable is redefined.
1230          */
1231         str = malloc(strlen(name) + strlen(value) + 2);
1232
1233         if (str == NULL)
1234         {
1235                 fprintf(stderr, "Cannot allocate memory\n");
1236
1237                 return 1;
1238         }
1239
1240         strcpy(str, name);
1241         strcat(str, "=");
1242         strcat(str, value);
1243
1244         putenv(str);
1245
1246         return 0;
1247 }
1248
1249
1250 int
1251 do_printenv(int argc, const char ** argv)
1252 {
1253         const char **   env;
1254         extern char **  environ;
1255         int             len;
1256
1257         env = (const char **) environ;
1258
1259         if (argc == 1)
1260         {
1261                 while (*env)
1262                         printf("%s\n", *env++);
1263
1264                 return 0;
1265         }
1266
1267         len = strlen(argv[1]);
1268
1269         while (*env)
1270         {
1271                 if ((strlen(*env) > len) && (env[0][len] == '=') &&
1272                         (memcmp(argv[1], *env, len) == 0))
1273                 {
1274                         printf("%s\n", &env[0][len+1]);
1275
1276                         return 0;
1277                 }
1278                 env++;
1279         }
1280
1281         return 0;
1282 }
1283
1284
1285 int
1286 do_umask(int argc, const char ** argv)
1287 {
1288         const char *    cp;
1289         int             mask;
1290
1291         if (argc <= 1)
1292         {
1293                 mask = umask(0);
1294                 umask(mask);
1295                 printf("%03o\n", mask);
1296
1297                 return 0;
1298         }
1299
1300         mask = 0;
1301         cp = argv[1];
1302
1303         while (isOctal(*cp))
1304                 mask = mask * 8 + *cp++ - '0';
1305
1306         if (*cp || (mask & ~0777))
1307         {
1308                 fprintf(stderr, "Bad umask value\n");
1309
1310                 return 1;
1311         }
1312
1313         umask(mask);
1314
1315         return 0;
1316 }
1317
1318
1319 int
1320 do_kill(int argc, const char ** argv)
1321 {
1322         const char *    cp;
1323         int             sig;
1324         int             pid;
1325         int             r;
1326
1327         r = 0;
1328         sig = SIGTERM;
1329
1330         if (argv[1][0] == '-')
1331         {
1332                 cp = &argv[1][1];
1333
1334                 if (strcmp(cp, "HUP") == 0)
1335                         sig = SIGHUP;
1336                 else if (strcmp(cp, "INT") == 0)
1337                         sig = SIGINT;
1338                 else if (strcmp(cp, "QUIT") == 0)
1339                         sig = SIGQUIT;
1340                 else if (strcmp(cp, "KILL") == 0)
1341                         sig = SIGKILL;
1342                 else if (strcmp(cp, "STOP") == 0)
1343                         sig = SIGSTOP;
1344                 else if (strcmp(cp, "CONT") == 0)
1345                         sig = SIGCONT;
1346                 else if (strcmp(cp, "USR1") == 0)
1347                         sig = SIGUSR1;
1348                 else if (strcmp(cp, "USR2") == 0)
1349                         sig = SIGUSR2;
1350                 else if (strcmp(cp, "TERM") == 0)
1351                         sig = SIGTERM;
1352                 else
1353                 {
1354                         sig = 0;
1355
1356                         while (isDecimal(*cp))
1357                                 sig = sig * 10 + *cp++ - '0';
1358
1359                         if (*cp)
1360                         {
1361                                 fprintf(stderr, "Unknown signal\n");
1362
1363                                 return 1;
1364                         }
1365                 }
1366
1367                 argc--;
1368                 argv++;
1369         }
1370
1371         while (argc-- > 1)
1372         {
1373                 cp = *(++argv);
1374                 pid = 0;
1375
1376                 while (isDecimal(*cp))
1377                         pid = pid * 10 + *cp++ - '0';
1378
1379                 if (*cp)
1380                 {
1381                         fprintf(stderr, "Non-numeric pid\n");
1382
1383                         return 1;
1384                 }
1385
1386                 if (kill(pid, sig) < 0)
1387                 {
1388                         perror(*argv);
1389                         r = 1;
1390                 }
1391         }
1392
1393         return r;
1394 }
1395
1396
1397 int
1398 do_where(int argc, const char ** argv)
1399 {
1400         const char *    program;
1401         const char *    dirName;
1402         char *          path;
1403         char *          endPath;
1404         char *          fullPath;
1405         BOOL            found;
1406         int             r;
1407
1408         found = FALSE;
1409         program = argv[1];
1410
1411         if (strchr(program, '/') != NULL)
1412         {
1413                 fprintf(stderr, "Program name cannot include a path\n");
1414
1415                 return 1;
1416         }
1417
1418         path = getenv("PATH");
1419
1420         fullPath = getChunk(strlen(path) + strlen(program) + 2);
1421         path = chunkstrdup(path);
1422
1423         if ((path == NULL) || (fullPath == NULL))
1424         {
1425                 fprintf(stderr, "Memory allocation failed\n");
1426
1427                 return 1;
1428         }
1429
1430         /*
1431          * Check out each path to see if the program exists and is
1432          * executable in that path.
1433          */
1434         for (; path; path = endPath)
1435         {
1436                 /*
1437                  * Find the end of the next path and NULL terminate
1438                  * it if necessary.
1439                  */
1440                 endPath = strchr(path, ':');
1441
1442                 if (endPath)
1443                         *endPath++ = '\0';
1444
1445                 /*
1446                  * Get the directory name, defaulting it to DOT if
1447                  * it is null.
1448                  */
1449                 dirName = path;
1450
1451                 if (dirName == '\0')
1452                         dirName = ".";
1453
1454                 /*
1455                  * Construct the full path of the program.
1456                  */
1457                 strcpy(fullPath, dirName);
1458                 strcat(fullPath, "/");
1459                 strcat(fullPath, program);
1460
1461                 /*
1462                  * See if the program exists and is executable.
1463                  */
1464                 if (access(fullPath, X_OK) < 0)
1465                 {
1466                         if (errno != ENOENT)
1467                         {
1468                                 perror(fullPath);
1469                                 r = 1;
1470                         }
1471
1472                         continue;
1473                 }
1474
1475                 printf("%s\n", fullPath);
1476                 found = TRUE;
1477         }
1478
1479         if (!found)
1480         {
1481                 printf("Program \"%s\" not found in PATH\n", program);
1482                 r = 1;
1483         }
1484
1485         return r;
1486 }
1487
1488 #if HAVE_LINUX_LOSETUP
1489
1490 int
1491 do_losetup(int argc, const char ** argv)
1492 {
1493         int loopfd;
1494         int targfd;
1495         struct loop_info loopInfo;
1496
1497         if (!strcmp(argv[1], "-d"))
1498         {
1499                 loopfd = open(argv[2], O_RDWR);
1500
1501                 if (loopfd < 0)
1502                 {
1503                         fprintf(stderr, "Error opening %s: %s\n", argv[2], 
1504                                 strerror(errno));
1505
1506                         return 1;
1507                 }
1508
1509                 if (ioctl(loopfd, LOOP_CLR_FD, 0))
1510                 {
1511                         fprintf(stderr, "Error unassociating device: %s\n", 
1512                                 strerror(errno));
1513
1514                         return 1;
1515                 }
1516         }
1517
1518         loopfd = open(argv[1], O_RDWR);
1519
1520         if (loopfd < 0)
1521         {
1522                 fprintf(stderr, "Error opening %s: %s\n", argv[1], 
1523                         strerror(errno));
1524
1525                 return 1;
1526         }
1527
1528         targfd = open(argv[2], O_RDWR);
1529
1530         if (targfd < 0)
1531         {
1532                 fprintf(stderr, "Error opening %s: %s\n", argv[2], 
1533                         strerror(errno));
1534
1535                 return 1;
1536         }
1537
1538         if (ioctl(loopfd, LOOP_SET_FD, targfd))
1539         {
1540                 fprintf(stderr, "Error setting up loopback device: %s\n", 
1541                         strerror(errno));
1542
1543                 return 1;
1544         }
1545
1546         memset(&loopInfo, 0, sizeof(loopInfo));
1547         strcpy(loopInfo.lo_name, argv[2]);
1548
1549         if (ioctl(loopfd, LOOP_SET_STATUS, &loopInfo))
1550         {
1551                 fprintf(stderr, "Error setting up loopback device: %s\n", 
1552                         strerror(errno));
1553
1554                 return 1;
1555         }
1556
1557         return 0;
1558 }
1559
1560 #endif
1561
1562 /* END CODE */